This is an automated email from the ASF dual-hosted git repository. wangxin pushed a commit to branch asf-site in repository https://gitbox.apache.org/repos/asf/incubator-dubbo-website.git
The following commit(s) were added to refs/heads/asf-site by this push: new 426398a gene htmls 426398a is described below commit 426398a4b22fc86f69012a0e51d8ad745e1a6012 Author: Xin Wang <xin.victorw...@gmail.com> AuthorDate: Sun Jan 20 15:30:39 2019 +0800 gene htmls --- build/blog.js | 4 +- md_json/blog.json | 9 ++ zh-cn/blog/dubbo-fescar.html | 211 +++++++++++++++++++++++++++++++++++++++++++ zh-cn/blog/dubbo-fescar.json | 10 ++ zh-cn/blog/index.html | 2 +- 5 files changed, 233 insertions(+), 3 deletions(-) diff --git a/build/blog.js b/build/blog.js index 90945bb..a52f4ca 100644 --- a/build/blog.js +++ b/build/blog.js @@ -1,6 +1,6 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=78) [...] +!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=78) [...] Copyright (c) 2017 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames */ -!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else if("object"===o)for(var u in r)i.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...] \ No newline at end of file +!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else if("object"===o)for(var u in r)i.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...] \ No newline at end of file diff --git a/md_json/blog.json b/md_json/blog.json index 5a5027b..f2e3a34 100644 --- a/md_json/blog.json +++ b/md_json/blog.json @@ -303,6 +303,15 @@ "meta": {} }, { + "filename": "dubbo-fescar.md", + "link": "/zh-cn/blog/dubbo-fescar.html", + "meta": { + "title": "如何使用Fescar保证Dubbo微服务间的一致性", + "keywords": "Dubbo,Fescar,一致性", + "description": "本文主要介绍如何使用Fescar保证Dubbo微服务间的一致性" + } + }, + { "filename": "dubbo-generic-invoke.md", "link": "/zh-cn/blog/dubbo-generic-invoke.html", "meta": { diff --git a/zh-cn/blog/dubbo-fescar.html b/zh-cn/blog/dubbo-fescar.html new file mode 100644 index 0000000..1b78ca2 --- /dev/null +++ b/zh-cn/blog/dubbo-fescar.html @@ -0,0 +1,211 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + <meta name="keywords" content="Dubbo,Fescar,一致性" /> + <meta name="description" content="本文主要介绍如何使用Fescar保证Dubbo微服务间的一致性" /> + <!-- 网页标签标题 --> + <title>如何使用Fescar保证Dubbo微服务间的一致性</title> + <link rel="shortcut icon" href="/img/dubbo.ico"/> + <link rel="stylesheet" href="/build/blogDetail.css" /> +</head> +<body> + <div id="root"><div class="blog-detail-page" data-reactroot=""><header class="header-container header-container-normal"><div class="header-body"><a href="/zh-cn/index.html"><img class="logo" src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span class="icon-search"></span></div><span class="language-switch language-switch-normal">En</span><div class="header-menu"><img class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item menu-item-normal"><a h [...] +<h2>案例</h2> +<p>用户采购商品业务,整个业务包含3个微服务:</p> +<ul> +<li>库存服务: 扣减给定商品的库存数量。</li> +<li>订单服务: 根据采购请求生成订单。</li> +<li>账户服务: 用户账户金额扣减。</li> +</ul> +<h3>业务结构图</h3> +<p><img src="../../img/blog/fescar/fescar-1.png" alt="Architecture"></p> +<h3>StorageService</h3> +<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">StorageService</span> </span>{ + + <span class="hljs-comment">/** + * deduct storage count + */</span> + <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">deduct</span><span class="hljs-params">(String commodityCode, <span class="hljs-keyword">int</span> count)</span></span>; +} +</code></pre> +<h3>OrderService</h3> +<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">OrderService</span> </span>{ + + <span class="hljs-comment">/** + * create order + */</span> + <span class="hljs-function">Order <span class="hljs-title">create</span><span class="hljs-params">(String userId, String commodityCode, <span class="hljs-keyword">int</span> orderCount)</span></span>; +} +</code></pre> +<h3>AccountService</h3> +<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">AccountService</span> </span>{ + + <span class="hljs-comment">/** + * debit balance of user's account + */</span> + <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">debit</span><span class="hljs-params">(String userId, <span class="hljs-keyword">int</span> money)</span></span>; +} +</code></pre> +<h3>主要的业务逻辑:</h3> +<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BusinessServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">BusinessService</span> </span>{ + + <span class="hljs-keyword">private</span> StorageService storageService; + + <span class="hljs-keyword">private</span> OrderService orderService; + + <span class="hljs-comment">/** + * purchase + */</span> + <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">purchase</span><span class="hljs-params">(String userId, String commodityCode, <span class="hljs-keyword">int</span> orderCount)</span> </span>{ + + storageService.deduct(commodityCode, orderCount); + + orderService.create(userId, commodityCode, orderCount); + } +} +</code></pre> +<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StorageServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">StorageService</span> </span>{ + + <span class="hljs-keyword">private</span> StorageDAO storageDAO; + + <span class="hljs-meta">@Override</span> + <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deduct</span><span class="hljs-params">(String commodityCode, <span class="hljs-keyword">int</span> count)</span> </span>{ + Storage storage = <span class="hljs-keyword">new</span> Storage(); + storage.setCount(count); + storage.setCommodityCode(commodityCode); + storageDAO.update(storage); + } +} +</code></pre> +<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">OrderService</span> </span>{ + + <span class="hljs-keyword">private</span> OrderDAO orderDAO; + + <span class="hljs-keyword">private</span> AccountService accountService; + + <span class="hljs-function"><span class="hljs-keyword">public</span> Order <span class="hljs-title">create</span><span class="hljs-params">(String userId, String commodityCode, <span class="hljs-keyword">int</span> orderCount)</span> </span>{ + + <span class="hljs-keyword">int</span> orderMoney = calculate(commodityCode, orderCount); + + accountService.debit(userId, orderMoney); + + Order order = <span class="hljs-keyword">new</span> Order(); + order.userId = userId; + order.commodityCode = commodityCode; + order.count = orderCount; + order.money = orderMoney; + + <span class="hljs-keyword">return</span> orderDAO.insert(order); + } +} +</code></pre> +<h2>Fescar 分布式事务解决方案</h2> +<p><img src="../../img/blog/fescar/fescar-2.png" alt="undefined"></p> +<p>此处仅仅需要一行注解 <code>@GlobalTransactional</code> 写在业务发起方的方法上:</p> +<pre><code class="language-java"> + <span class="hljs-meta">@GlobalTransactional</span> + <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">purchase</span><span class="hljs-params">(String userId, String commodityCode, <span class="hljs-keyword">int</span> orderCount)</span> </span>{ + ...... + } +</code></pre> +<h2>Dubbo 与 Fescar 结合的例子</h2> +<h3>Step 1: 安装数据库</h3> +<ul> +<li>要求: MySQL (InnoDB 存储引擎)。</li> +</ul> +<p><strong>提示:</strong> 事实上例子中3个微服务需要3个独立的数据库,但为了方便我们使用同一物理库并配置3个逻辑连接串。</p> +<p>更改以下xml文件中的数据库url、username和password</p> +<p>dubbo-account-service.xml +dubbo-order-service.xml +dubbo-storage-service.xml</p> +<pre><code class="language-xml"> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"url"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"jdbc:mysql://x.x.x.x:3306/xxx"</span> /></span> + <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"xxx"</span> /></span> + <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"xxx"</span> /></span> +</code></pre> +<h3>Step 2: 为 Fescar 创建 UNDO_LOG 表</h3> +<p><code>UNDO_LOG</code> 此表用于 Fescar 的AT模式。</p> +<pre><code class="language-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`undo_log`</span> ( + <span class="hljs-string">`id`</span> <span class="hljs-built_in">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT, + <span class="hljs-string">`branch_id`</span> <span class="hljs-built_in">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`xid`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`rollback_info`</span> longblob <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`log_status`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`log_created`</span> datetime <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`log_modified`</span> datetime <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`ext`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>, + PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>), + <span class="hljs-keyword">KEY</span> <span class="hljs-string">`idx_unionkey`</span> (<span class="hljs-string">`xid`</span>,<span class="hljs-string">`branch_id`</span>) +) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> AUTO_INCREMENT=<span class="hljs-number">159</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8 +</code></pre> +<h3>Step 3: 创建相关业务表</h3> +<pre><code class="language-sql"> +<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`storage_tbl`</span>; +<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`storage_tbl`</span> ( + <span class="hljs-string">`id`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT, + <span class="hljs-string">`commodity_code`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`count`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span>, + PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>), + <span class="hljs-keyword">UNIQUE</span> <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`commodity_code`</span>) +) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8; + + +<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`order_tbl`</span>; +<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`order_tbl`</span> ( + <span class="hljs-string">`id`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT, + <span class="hljs-string">`user_id`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`commodity_code`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`count`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span>, + <span class="hljs-string">`money`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span>, + PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>) +) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8; + + +<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`account_tbl`</span>; +<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`account_tbl`</span> ( + <span class="hljs-string">`id`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT, + <span class="hljs-string">`user_id`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>, + <span class="hljs-string">`money`</span> <span class="hljs-built_in">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span>, + PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>) +) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8; +</code></pre> +<h3>Step 4: 启动 Fescar-Server 服务</h3> +<ul> +<li>下载Server <a href="https://github.com/alibaba/fescar/releases">package</a>, 并解压。</li> +<li>运行bin目录下的启动脚本。</li> +</ul> +<pre><code class="language-shell">sh fescar-server.sh $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA + +e.g. + +sh fescar-server.sh 8091 /home/admin/fescar/data/ +</code></pre> +<h3>Step 5: 运行例子</h3> +<ul> +<li>启动账户服务</li> +<li>启动库存服务</li> +<li>启动订单服务</li> +<li>运行BusinessService入口</li> +</ul> +<p><a href="https://github.com/alibaba/fescar/tree/develop/examples/src/main/java/com/alibaba/fescar/tm/dubbo">相关代码</a><br> +<a href="https://github.com/alibaba/fescar/">学习更多关于Fescar的内容</a></p> +</section><footer class="footer-container"><div class="footer-body"><img src="/img/dubbo_gray.png"/><img class="apache" src="/img/apache_logo.png"/><div class="cols-container"><div class="col col-12"><h3>Disclaimer</h3><p>Apache Dubbo is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making proce [...] + <script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script> + <script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script> + <script> + window.rootPath = ''; + </script> + <script src="/build/blogDetail.js"></script> + <!-- Global site tag (gtag.js) - Google Analytics --> + <script async src="https://www.googletagmanager.com/gtag/js?id=UA-112489517-1"></script> + <script> + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + + gtag('config', 'UA-112489517-1'); + </script> +</body> +</html> \ No newline at end of file diff --git a/zh-cn/blog/dubbo-fescar.json b/zh-cn/blog/dubbo-fescar.json new file mode 100644 index 0000000..574d8d9 --- /dev/null +++ b/zh-cn/blog/dubbo-fescar.json @@ -0,0 +1,10 @@ +{ + "filename": "dubbo-fescar.md", + "__html": "<h1>如何使用Fescar保证Dubbo微服务间的一致性</h1>\n<h2>案例</h2>\n<p>用户采购商品业务,整个业务包含3个微服务:</p>\n<ul>\n<li>库存服务: 扣减给定商品的库存数量。</li>\n<li>订单服务: 根据采购请求生成订单。</li>\n<li>账户服务: 用户账户金额扣减。</li>\n</ul>\n<h3>业务结构图</h3>\n<p><img src=\"../../img/blog/fescar/fescar-1.png\" alt=\"Architecture\"></p>\n<h3>StorageService</h3>\n<pre><code class=\"language-java\"><span class=\"hljs-keyword\">public</span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface</span> <span class=\"hljs-title\">Storage [...] + "link": "/zh-cn/blog/dubbo-fescar.html", + "meta": { + "title": "如何使用Fescar保证Dubbo微服务间的一致性", + "keywords": "Dubbo,Fescar,一致性", + "description": "本文主要介绍如何使用Fescar保证Dubbo微服务间的一致性" + } +} \ No newline at end of file diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html index bba9dd0..6018696 100644 --- a/zh-cn/blog/index.html +++ b/zh-cn/blog/index.html @@ -12,7 +12,7 @@ <link rel="stylesheet" href="/build/blog.css" /> </head> <body> - <div id="root"><div class="blog-list-page" data-reactroot=""><header class="header-container header-container-normal"><div class="header-body"><a href="/zh-cn/index.html"><img class="logo" src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span class="icon-search"></span></div><span class="language-switch language-switch-normal">En</span><div class="header-menu"><img class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item menu-item-normal"><a hre [...] + <div id="root"><div class="blog-list-page" data-reactroot=""><header class="header-container header-container-normal"><div class="header-body"><a href="/zh-cn/index.html"><img class="logo" src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span class="icon-search"></span></div><span class="language-switch language-switch-normal">En</span><div class="header-menu"><img class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item menu-item-normal"><a hre [...] <script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script> <script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script> <script>