This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch asf-site in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-website.git
commit 63aae5f2aea374553c000d22f58eb495f12528ba Author: Willem Jiang <jiangni...@huawei.com> AuthorDate: Thu Jul 19 14:26:05 2018 +0800 Publish the website --- content/assets/images/scaffold/DirectInvoke.png | Bin 0 -> 7713 bytes .../scaffold/EdgeOnlySupportConsumerHandler.png | Bin 0 -> 14500 bytes content/assets/images/scaffold/InvokeViaEdge.png | Bin 0 -> 19978 bytes content/assets/images/scaffold/LoginViaEdge.png | Bin 0 -> 108503 bytes content/assets/images/scaffold/LogonViaEdge.png | Bin 0 -> 99103 bytes .../images/scaffold/PerformanceTestDeploy.png | Bin 0 -> 9400 bytes .../docs/apache-servicecomb-day-slides/index.html | 4 +- .../apache-servicecomb-incubating-day/index.html | 4 +- .../index.html | 217 ++++++++-- .../index.html | 2 +- content/cn/year-archive/index.html | 184 ++++++++ .../index.html | 4 +- .../apache-servicecomb-incubating-day/index.html | 6 +- content/feed.xml | 463 +++++++-------------- content/sitemap.xml | 4 + content/sitemap/index.html | 2 + content/users/service-heartbeat/index.html | 2 +- 17 files changed, 531 insertions(+), 361 deletions(-) diff --git a/content/assets/images/scaffold/DirectInvoke.png b/content/assets/images/scaffold/DirectInvoke.png new file mode 100644 index 0000000..ec53d06 Binary files /dev/null and b/content/assets/images/scaffold/DirectInvoke.png differ diff --git a/content/assets/images/scaffold/EdgeOnlySupportConsumerHandler.png b/content/assets/images/scaffold/EdgeOnlySupportConsumerHandler.png new file mode 100644 index 0000000..6497a83 Binary files /dev/null and b/content/assets/images/scaffold/EdgeOnlySupportConsumerHandler.png differ diff --git a/content/assets/images/scaffold/InvokeViaEdge.png b/content/assets/images/scaffold/InvokeViaEdge.png new file mode 100644 index 0000000..2d2c26f Binary files /dev/null and b/content/assets/images/scaffold/InvokeViaEdge.png differ diff --git a/content/assets/images/scaffold/LoginViaEdge.png b/content/assets/images/scaffold/LoginViaEdge.png new file mode 100644 index 0000000..c564507 Binary files /dev/null and b/content/assets/images/scaffold/LoginViaEdge.png differ diff --git a/content/assets/images/scaffold/LogonViaEdge.png b/content/assets/images/scaffold/LogonViaEdge.png new file mode 100644 index 0000000..f5846c4 Binary files /dev/null and b/content/assets/images/scaffold/LogonViaEdge.png differ diff --git a/content/assets/images/scaffold/PerformanceTestDeploy.png b/content/assets/images/scaffold/PerformanceTestDeploy.png new file mode 100644 index 0000000..77e8fa4 Binary files /dev/null and b/content/assets/images/scaffold/PerformanceTestDeploy.png differ diff --git a/content/cn/docs/apache-servicecomb-day-slides/index.html b/content/cn/docs/apache-servicecomb-day-slides/index.html index 2515828..251b8aa 100644 --- a/content/cn/docs/apache-servicecomb-day-slides/index.html +++ b/content/cn/docs/apache-servicecomb-day-slides/index.html @@ -678,11 +678,11 @@ <h2 class="archive__item-title" itemprop="headline"> - <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" rel="permalink">如何从一名开源小白成长为Apache Committer + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 </a> </h2> - <p class="archive__item-excerpt" itemprop="description">如何从一名开源小白成长为Apache Committer + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 </p> <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> diff --git a/content/cn/docs/apache-servicecomb-incubating-day/index.html b/content/cn/docs/apache-servicecomb-incubating-day/index.html index e13384f..4009a12 100644 --- a/content/cn/docs/apache-servicecomb-incubating-day/index.html +++ b/content/cn/docs/apache-servicecomb-incubating-day/index.html @@ -718,11 +718,11 @@ <h2 class="archive__item-title" itemprop="headline"> - <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" rel="permalink">如何从一名开源小白成长为Apache Committer + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 </a> </h2> - <p class="archive__item-excerpt" itemprop="description">如何从一名开源小白成长为Apache Committer + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 </p> <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> diff --git a/content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html b/content/cn/docs/easy-build-microservice-system-part-III/index.html similarity index 51% copy from content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html copy to content/cn/docs/easy-build-microservice-system-part-III/index.html index 88185e8..0a527e8 100644 --- a/content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html +++ b/content/cn/docs/easy-build-microservice-system-part-III/index.html @@ -19,12 +19,12 @@ -<title>如何从一名开源小白成长为Apache Committer - Apache ServiceComb (incubating)</title> +<title>轻松微服务系列:开发高性能边缘服务 - Apache ServiceComb (incubating)</title> -<meta name="description" content="如何从一名开源小白成长为Apache Committer"> +<meta name="description" content="轻松微服务系列:开发高性能边缘服务"> @@ -33,21 +33,21 @@ <meta property="og:locale" content="cn"> <meta property="og:site_name" content="Apache ServiceComb (incubating)"> -<meta property="og:title" content="如何从一名开源小白成长为Apache Committer"> +<meta property="og:title" content="轻松微服务系列:开发高性能边缘服务"> - <link rel="canonical" href="http://github.com/pages/apache/incubator-servicecomb-website/cn/docs/how-to-grow-up-to-be-an-apache-committer/"> - <meta property="og:url" content="http://github.com/pages/apache/incubator-servicecomb-website/cn/docs/how-to-grow-up-to-be-an-apache-committer/"> + <link rel="canonical" href="http://github.com/pages/apache/incubator-servicecomb-website/cn/docs/easy-build-microservice-system-part-III/"> + <meta property="og:url" content="http://github.com/pages/apache/incubator-servicecomb-website/cn/docs/easy-build-microservice-system-part-III/"> - <meta property="og:description" content="如何从一名开源小白成长为Apache Committer"> + <meta property="og:description" content="轻松微服务系列:开发高性能边缘服务"> <meta name="twitter:site" content="@ServiceComb"> - <meta name="twitter:title" content="如何从一名开源小白成长为Apache Committer"> - <meta name="twitter:description" content="如何从一名开源小白成长为Apache Committer"> + <meta name="twitter:title" content="轻松微服务系列:开发高性能边缘服务"> + <meta name="twitter:description" content="轻松微服务系列:开发高性能边缘服务"> <meta name="twitter:url" content=""> @@ -70,7 +70,7 @@ <meta property="og:type" content="article"> - <meta property="article:published_time" content="2018-06-06T00:00:00+08:00"> + <meta property="article:published_time" content="2018-06-07T00:00:00+08:00"> @@ -226,7 +226,7 @@ - <a href=/docs/how-to-grow-up-to-be-an-apache-committer/>English</a> + <a href=/docs/easy-build-microservice-system-part-III/>English</a> </div> </nav> @@ -347,16 +347,16 @@ <article class="page" itemscope itemtype="http://schema.org/CreativeWork"> - <meta itemprop="headline" content="如何从一名开源小白成长为Apache Committer"> - <meta itemprop="description" content="如何从一名开源小白成长为Apache Committer"> - <meta itemprop="datePublished" content="June 06, 2018"> - <meta itemprop="dateModified" content="June 06, 2018"> + <meta itemprop="headline" content="轻松微服务系列:开发高性能边缘服务"> + <meta itemprop="description" content="轻松微服务系列:开发高性能边缘服务"> + <meta itemprop="datePublished" content="June 07, 2018"> + <meta itemprop="dateModified" content="June 07, 2018"> <div class="page__inner-wrap"> <header> - <h1 class="page__title" itemprop="headline">如何从一名开源小白成长为Apache Committer + <h1 class="page__title" itemprop="headline">轻松微服务系列:开发高性能边缘服务 </h1> <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> @@ -373,43 +373,164 @@ <section class="page__content" itemprop="text"> - <h2 id="如何从一名开源小白成长为apache-committer">如何从一名开源小白成长为Apache Committer</h2> -<p>今天收到了来自Apache Vote我成为Committer的邮件,代表自己的贡献得到了充分的肯定;除了感谢团队的给力支持,我更希望将自己的成长经历——如何践行Apache Way的心得介绍给大家,让大家爱上Apache开源社区,也能和我一样成长为自己喜爱项目的Committer。</p> + <h2 id="轻松微服务系列开发高性能边缘服务">轻松微服务系列:开发高性能边缘服务</h2> +<p>在前一篇博文<a href="http://servicecomb.incubator.apache.org/cn/docs/easy-build-microservice-system-part-II/">《轻松微服务系列:快速实现客户关系管理系统的用户服务》</a>,我们已经详细演示了从Archetype创建微服务后如何填充业务逻辑,快速构建包含JWT认证的用户服务。这篇博文我们将目光聚焦在Edge服务上,介绍如何构建高性能边缘服务应对高吞吐API网关的挑战。</p> -<h3 id="根据个人贡献获得价值government-by-merit">根据个人贡献获得价值(Government By Merit)</h3> -<p>回忆我刚参与ServiceComb项目,面对上万行的存量代码,总觉得无从下手,甚至认为开源社区高手如云,如果没有深厚且对口的技术功底,还是不要来掺和了。</p> +<h3 id="什么是边缘服务edge-service">什么是边缘服务(Edge Service)</h3> +<p>边缘服务也是一个微服务,微服务化系统通常使用边缘服务(Edge Service)作为所有其它微服务的统一入口,因此它也常常会被称为API Gateway,使用边缘服务的好处有如下几点:</p> +<ul> + <li>动态路由:动态配置URL地址与微服务之间的对应关系,便于扩展,以及实现版本灰度发布等;</li> + <li>统一认证:在入口处进行访问认证,避免需要在所有的微服务中都承载重复的认证机制;</li> + <li>集中监控:与统一认证类似,在边缘服务对入口调用进行监控,容易统计流量信息。</li> +</ul> -<p>在这个困难而关键的时候,社区导师给了我明确的指导——<strong>不要怕,从小事做起,不要“善小而不为”</strong>。于是我静下心来,在Jira上寻找最简单的任务,主动请缨的<a href="https://github.com/apache/incubator-servicecomb-java-chassis/pull/91">第一个任务</a>是支持配置兼容,具体需求是<code class="highlighter-rouge">cse.xxx</code>配置项和<code class="highlighter-rouge">servicecomb.xxx</code>配置项要具备等同效果,经过一番努力,成功Merge PR ;之后我又接下另一个简单任务,增加一个Annotation用于支持Json String作为请求参数……</p> +<h3 id="边缘服务的作用和原理">边缘服务的作用和原理</h3> +<p>我们先来看不使用边缘服务,UI直接调用用户服务的场景:</p> -<p>Apache Way非常看重个人贡献,没有贡献,一切无从谈起,<strong>与开源软件同行,不仅看你获得了多少,更要坚持长期贡献</strong>,这是它与商业软件最大的不同。贡献并不区分大小,无论是增加重大特性,还是小小的改进、Bug Fix和修订文档错误,这些同样是项目茁壮成长的关键。</p> +<p><img src="/assets/images/scaffold/DirectInvoke.png" alt="DirectInvoke" /></p> -<p><strong>实际上大多数开源爱好者都是从修订文档错误开始的</strong>,例如改正错别字、格式不正确以及订正描述等等,我对ServiceComb的理解也绝大多数来自<a href="https://github.com/apache/incubator-servicecomb-website/pulls?q=is%3Apr+is%3Aclosed+author%3Azhengyangyong">这方面的工作</a>;这样不但能够在阅读文档的过程中更快的了解技术细节,也比较容易入手做出贡献。</p> +<p>可以看出这种调用方式,UI缺乏一定的灵活性,体现在:</p> +<ul> + <li>UI的实现绑定了Chassis的编程语言Java,无法使用PHP等其它前端技术开发;</li> + <li>UI访问微服务的路径无法动态配置,如果作为后端的微服务系统发生调整,则UI很可能需要修改;</li> + <li>UI很容易混入复合(编排)调用的逻辑,使得结构变得复杂难以维护。</li> +</ul> -<p>总之坚持下来,个人积累的贡献慢慢变厚,获得Apache的认可自然水到渠成。</p> +<p>我们再看引入边缘服务后,UI如何通过边缘服务调用用户服务:</p> -<h3 id="社区驱动community">社区驱动(Community)</h3> -<p>参与社区是技术成长最快的方式之一,Follow Apache社区的方式有订阅<a href="http://servicecomb.incubator.apache.org/cn/developers/subscribe-mail-list/">邮件列表</a>和加入<a href="http://servicecomb.incubator.apache.org/cn/developers/use-gitter/">Gitter</a>聊天室;从看大家讨论(讨论邮件一般会使用[Discussion]开头),到回答大家的问题(回复邮件和发送Gitter聊天),相信用不了多久你就能收获颇丰,并冒出自己的想法,迈出第一步提交第一个PR也就不难了。</p> +<p><img src="/assets/images/scaffold/InvokeViaEdge.png" alt="InvokeViaEdge" /></p> -<p><a href="http://servicecomb.incubator.apache.org/">ServiceComb</a>作为一个微服务一站式解决方案,融合侵入式、非侵入式场景并支持多语言,解放开发者,帮助用户和开发者将企业应用轻松微服务化和上云;大家在这里讨论的话题、发起的投票、以及提交的代码,无不与微服务密切相关。在这个社区中我不但学习到了知识,完成了开源(也包含微服务)小白的蜕变,还进一步接受了开源的洗礼——<strong>前辈指导我进步,我将所学传递给新人</strong>;这个过程中我结识了很多新朋友,大家互通有无,不但极大的开阔了视野,也提高了自己的社交能力。</p> +<p>Edge服务将在<code class="highlighter-rouge">9090</code>端口上接受http rest调用,我们设计了下面的转发规则:</p> -<p>Apache开发者来自全球,社区大多都是用英文来交流。通过阅读<a href="http://servicecomb.incubator.apache.org/users/">英文资料</a>,使用英文在<a href="http://servicecomb.incubator.apache.org/cn/developers/use-gitter/">Gitter</a>上与开发人员直接交流,通过英文邮件来探讨问题,在不知不觉中自己的英文水平也大大提高了。</p> +<div class="language-text highlighter-rouge"><pre class="highlight"><code>http://{edge-host-name}:9090/{ServiceComb微服务Name}/{服务路径&参数} +</code></pre> +</div> + +<p>用户微服务名(<code class="highlighter-rouge">service_description.name</code>)是<code class="highlighter-rouge">user-service</code>,因此login调用URL:<em>cse://user-service/login</em>可以通过:<em>http://{edge-host-name}:9090/user-service/login</em> 访问。</p> + +<p>如此一来,微服务名成为了路径的一部分,http协议的<code class="highlighter-rouge">hostname</code>和<code class="highlighter-rouge">port</code>将固定指向Edge服务保持不变,灵活性大大增加了。</p> -<h3 id="协作开发collaborative-development">协作开发(Collaborative Development)</h3> -<p>这也是我极力推荐参与开源社区开发的重要原因之一,<strong>当你提交PR后,无论代码有多么烂,你总能收获宝贵的Comments</strong>,不花钱获得编程大师的指点——教你怎么写出优秀的代码,这是多么合算的买卖!</p> +<p>到此我们还可以再做一点点改进,引入一个自定义配置<code class="highlighter-rouge">edge.routing-short-path.{简称}</code>,映射微服务名:</p> -<p>我在参与ServiceComb社区前,只知道Java基本语法,IDE不熟练(之前一直是用VS写C#,不使用Eclipse和IntelliJ IDEA),不会Git,不懂Maven,还能有更糟糕的起点吗:)</p> +<div class="highlighter-rouge"><pre class="highlight"><code>edge: + routing-short-path: + user: user-service +</code></pre> +</div> -<p>不用担心,社区会指导你。我前文提到的第一个简单的任务,花费了将近一周时间,被打回来了四五次后才被Merge;一个PR收获60+ Comments也是家常便饭。这个过程中我的Java水平成长得飞快,不久后就能独立承担新特性的设计和开发——<a href="http://servicecomb.incubator.apache.org/cn/users/metrics-in-1.0.0-m1/">Metrics</a>,当然,完成这个新特性的过程中Committer和其他开发者给予了很多支持,所以,请大胆的提交你的第一个PR,成为一名Contributor吧。</p> +<p>上面的配置代表:<em>http://{edge-host-name}:9090/user/login</em> 等效于:<em>http://{edge-host-name}:9090/user-service/login</em> ,如此一来:</p> +<ol> + <li>URL能够更加简洁;</li> + <li>当微服务名发生变化,只需要调整对应的配置,不需要更改前端UI路径代码。</li> +</ol> + +<h3 id="实现边缘服务">实现边缘服务</h3> +<h4 id="第一步引入edge-core依赖">第一步:引入Edge Core依赖</h4> +<div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt"><dependency></span> + <span class="nt"><groupId></span>org.apache.servicecomb<span class="nt"></groupId></span> + <span class="nt"><artifactId></span>edge-core<span class="nt"></artifactId></span> +<span class="nt"></dependency></span> +</code></pre> +</div> -<h3 id="民主开放和透明consensus-open-and-transparency">民主,开放和透明(Consensus, Open and Transparency)</h3> -<p>在Apache社区里投票至关重要,你可以感受到你的建议将被充分重视,我很喜欢这种参与感;大家的讨论和建议也完全公开透明,并且能够长时间通过邮件列表查询到,沟通效率非常高。所以大家多多参与,一定能收获惊喜,从万能的社区里寻找自己想要的答案,请记住,<strong>当你对某个问题产生困惑,即使是强大的StackOverflow也不会有原作者的答复更为准确</strong>。</p> +<h4 id="第二步编写调度器dispatcher">第二步:编写调度器Dispatcher</h4> +<p>Edge服务的核心就是调度器Dispatcher,ServiceComb Edge Core中的Dispatcher基于高性能的Vertx Reactive,轻松应对百万量级API请求的挑战;只需要继承AbstractEdgeDispatcher抽象类,添加对应的逻辑即可:</p> + +<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">EdgeDispatcher</span> <span class="kd">extends</span> <span class="n">AbstractEdgeDispatcher</span> <span class="o">{</span> + <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">LOGGER</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">EdgeDispatcher</span><span class="o">.</span><span class="na">class</span><span class="o">);</span> + + <span class="c1">//此Dispatcher的优先级,Order级越小,路由策略优先级越高</span> + <span class="kd">public</span> <span class="kt">int</span> <span class="nf">getOrder</span><span class="o">()</span> <span class="o">{</span> + <span class="k">return</span> <span class="mi">10000</span><span class="o">;</span> + <span class="o">}</span> + + <span class="c1">//初始化Dispatcher的路由策略</span> + <span class="kd">public</span> <span class="kt">void</span> <span class="nf">init</span><span class="o">(</span><span class="n">Router</span> <span class="n">router</span><span class="o">)</span> <span class="o">{</span> + <span class="c1">///捕获 {ServiceComb微服务Name}/{服务路径&参数} 的URL</span> + <span class="n">String</span> <span class="n">regex</span> <span class="o">=</span> <span class="s">"/([^\\\\/]+)/(.*)"</span><span class="o">;</span> + <span class="n">router</span><span class="o">.</span><span class="na">routeWithRegex</span><span class="o">(</span><span class="n">regex</span><span class="o">).</span><span class="na">handler</span><span class="o">(</span><span class="n">CookieHandler</span><span class="o">.</span><span class="na">create</span><span class="o">());</span> + <span class="n">router</span><span class="o">.</span><span class="na">routeWithRegex</span><span class="o">(</span><span class="n">regex</span><span class="o">).</span><span class="na">handler</span><span class="o">(</span><span class="n">createBodyHandler</span><span class="o">());</span> + <span class="n">router</span><span class="o">.</span><span class="na">routeWithRegex</span><span class="o">(</span><span class="n">regex</span><span class="o">).</span><span class="na">failureHandler</span><span class="o">(</span><span class="k">this</span><span class="o">::</span><span class="n">onFailure</span><span class="o">).</span><span class="na">handler</span><span class="o">(</span><span class="k">this</span><span class="o">::</span><span class="n">onRequest</span><span clas [...] + <span class="o">}</span> + + <span class="c1">//处理请求,请注意</span> + <span class="kd">private</span> <span class="kt">void</span> <span class="nf">onRequest</span><span class="o">(</span><span class="n">RoutingContext</span> <span class="n">context</span><span class="o">)</span> <span class="o">{</span> + <span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">></span> <span class="n">pathParams</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">pathParams</span><span class="o">();</span> + <span class="c1">//从匹配的param0拿到{ServiceComb微服务Name}</span> + <span class="kd">final</span> <span class="n">String</span> <span class="n">service</span> <span class="o">=</span> <span class="n">pathParams</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"param0"</span><span class="o">);</span> + <span class="c1">//从匹配的param1拿到{服务路径&参数}</span> + <span class="n">String</span> <span class="n">path</span> <span class="o">=</span> <span class="s">"/"</span> <span class="o">+</span> <span class="n">pathParams</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"param1"</span><span class="o">);</span> + + <span class="c1">//还记得我们之前说的做出一点点改进吗?引入一个自定义配置edge.routing-short-path.{简称},映射微服务名;如果简称没有配置,那么就认为直接是微服务的名</span> + <span class="kd">final</span> <span class="n">String</span> <span class="n">serviceName</span> <span class="o">=</span> <span class="n">DynamicPropertyFactory</span><span class="o">.</span><span class="na">getInstance</span><span class="o">()</span> + <span class="o">.</span><span class="na">getStringProperty</span><span class="o">(</span><span class="s">"edge.routing-short-path."</span> <span class="o">+</span> <span class="n">service</span><span class="o">,</span> <span class="n">service</span><span class="o">).</span><span class="na">get</span><span class="o">();</span> + + <span class="c1">//创建一个Edge转发</span> + <span class="n">EdgeInvocation</span> <span class="n">edgeInvocation</span> <span class="o">=</span> <span class="k">new</span> <span class="n">EdgeInvocation</span><span class="o">();</span> + <span class="c1">//允许接受任意版本的微服务实例作为Provider,未来我们会使用此(设置版本)能力实现灰度发布</span> + <span class="n">edgeInvocation</span><span class="o">.</span><span class="na">setVersionRule</span><span class="o">(</span><span class="n">DefinitionConst</span><span class="o">.</span><span class="na">VERSION_RULE_ALL</span><span class="o">);</span> + <span class="n">edgeInvocation</span><span class="o">.</span><span class="na">init</span><span class="o">(</span><span class="n">serviceName</span><span class="o">,</span> <span class="n">context</span><span class="o">,</span> <span class="n">path</span><span class="o">,</span> <span class="n">httpServerFilters</span><span class="o">);</span> + <span class="n">edgeInvocation</span><span class="o">.</span><span class="na">edgeInvoke</span><span class="o">();</span> + <span class="o">}</span> +<span class="o">}</span> +</code></pre> +</div> -<p>写在最后,我想说从一名开源小白成长为Apache Committer并不是无比艰难又遥不可及的事情,<strong>只需要日积月累的在社区中投入一点业余时间,就能梦想成真</strong>。当然最好找到自己感兴趣的社区,这会让这段旅途更加愉快,也能交到更多志同道合的的朋友。</p> +<h4 id="第三步加载调度器dispatcher">第三步:加载调度器Dispatcher</h4> +<p>ServiceComb Edge使用SPI(Service Provider Interface)的方式加载已经编写好的调度器Dispatcher,在resources目录下创建<code class="highlighter-rouge">META-INF.services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher</code>配置文件,写入上一步EdgeDispatcher的类全名:</p> + +<div class="language-text highlighter-rouge"><pre class="highlight"><code>{EdgeDispatcher的包名}.EdgeDispatcher +</code></pre> +</div> + +<h4 id="第四步配置microserviceyaml">第四步:配置microservice.yaml</h4> +<p>边缘服务本身也是一个微服务,同样需要配置microservice.yaml:</p> + +<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">APPLICATION_ID</span><span class="pi">:</span> <span class="s">scaffold</span> +<span class="s">service_description</span><span class="pi">:</span> + <span class="s">name</span><span class="pi">:</span> <span class="s">edge-service</span> + <span class="s">version</span><span class="pi">:</span> <span class="s">0.0.1</span> +<span class="s">servicecomb</span><span class="pi">:</span> + <span class="s">service</span><span class="pi">:</span> + <span class="s">registry</span><span class="pi">:</span> + <span class="c1">#配置ServiceCenter使得Edge能够发现其他微服务</span> + <span class="s">address</span><span class="pi">:</span> <span class="s">http://127.0.0.1:30100</span> + <span class="c1">#配置Rest Endpoint</span> + <span class="s">rest</span><span class="pi">:</span> + <span class="s">address</span><span class="pi">:</span> <span class="s">0.0.0.0:9090</span> + +<span class="c1">#自定义的简称机制配置(这是我们自行扩展实现的)</span> +<span class="s">edge</span><span class="pi">:</span> + <span class="s">routing-short-path</span><span class="pi">:</span> + <span class="s">user</span><span class="pi">:</span> <span class="s">user-service</span> +</code></pre> +</div> <blockquote> - <p>广告:我所在的Apache ServiceComb正<a href="http://servicecomb.incubator.apache.org/cn/developers/contributing">持续招募贡献者</a>,非常欢迎大家加入,让我们一起构建更好的微服务框架。</p> + <p>提示:</p> + <ol> + <li>除了配置Rest Endpoint,我们也支持配置Highway Endpoint,但Highway Endpoint只支持ServiceComb开发的微服务调用;</li> + <li>microservice.yaml中没有配置Handler,Edge支持所有Consumer端Handler,不支持Producer端Handler,调用链原理如下:</li> + </ol> + + <p><img src="/assets/images/scaffold/EdgeOnlySupportConsumerHandler.png" alt="EdgeOnlySupportConsumerHandler" /></p> + </blockquote> +<h3 id="验证边缘服务">验证边缘服务</h3> +<p>启动用户微服务和Edge服务,使用<a href="https://www.getpostman.com/">Postman</a>注册一个用户:</p> + +<p><img src="/assets/images/scaffold/LogonViaEdge.png" alt="LogonViaEdge" /></p> + +<p>成功,现在我们使用新注册的用户名<code class="highlighter-rouge">ldg</code>登录:</p> + +<p><img src="/assets/images/scaffold/LoginViaEdge.png" alt="LoginViaEdge" /></p> + +<p>同样成功,并在Response中已经包含了正确的<code class="highlighter-rouge">AUTHORIZATION</code>Header。</p> + +<h3 id="性能比拼">性能比拼</h3> +<p>ServiceComb Java Chassis也支持集成Netflix Zuul作为网关服务,我们做了一次性能比较,使用ServiceComb Edge作为网关吞吐能力大幅优于Netflix Zuul,性能测试项目源代码在<a href="https://github.com/zhengyangyong/gateway-perf">这里</a>。</p> + </section> @@ -429,11 +550,15 @@ - <a href="/tags/#apache-way" class="page__taxonomy-item" rel="tag">Apache Way</a><span class="sep">, </span> + <a href="/tags/#api-gateway" class="page__taxonomy-item" rel="tag">API Gateway</a><span class="sep">, </span> + + + + <a href="/tags/#edge-service" class="page__taxonomy-item" rel="tag">Edge Service</a><span class="sep">, </span> - <a href="/tags/#committer" class="page__taxonomy-item" rel="tag">Committer</a> + <a href="/tags/#zuul" class="page__taxonomy-item" rel="tag">Zuul</a> </span> </p> @@ -445,7 +570,7 @@ - <p class="page__date"><strong><i class="fa fa-fw fa-calendar" aria-hidden="true"></i> 最新的:</strong> <time datetime="2018-06-06">2018年6月6日</time></p> + <p class="page__date"><strong><i class="fa fa-fw fa-calendar" aria-hidden="true"></i> 最新的:</strong> <time datetime="2018-06-07">2018年6月7日</time></p> @@ -456,20 +581,20 @@ <h4 class="page__share-title">分享</h4> - <a href="https://twitter.com/intent/tweet?via=ServiceComb&text=如何从一名开源小白成长为Apache Committer /cn/docs/how-to-grow-up-to-be-an-apache-committer/" class="btn btn--twitter" title="分享 Twitter"><i class="fa fa-fw fa-twitter" aria-hidden="true"></i><span> Twitter</span></a> + <a href="https://twitter.com/intent/tweet?via=ServiceComb&text=轻松微服务系列:开发高性能边缘服务 /cn/docs/easy-build-microservice-system-part-III/" class="btn btn--twitter" title="分享 Twitter"><i class="fa fa-fw fa-twitter" aria-hidden="true"></i><span> Twitter</span></a> - <a href="https://www.facebook.com/sharer/sharer.php?u=/cn/docs/how-to-grow-up-to-be-an-apache-committer/" class="btn btn--facebook" title="分享 Facebook"><i class="fa fa-fw fa-facebook" aria-hidden="true"></i><span> Facebook</span></a> + <a href="https://www.facebook.com/sharer/sharer.php?u=/cn/docs/easy-build-microservice-system-part-III/" class="btn btn--facebook" title="分享 Facebook"><i class="fa fa-fw fa-facebook" aria-hidden="true"></i><span> Facebook</span></a> - <a href="https://plus.google.com/share?url=/cn/docs/how-to-grow-up-to-be-an-apache-committer/" class="btn btn--google-plus" title="分享 Google Plus"><i class="fa fa-fw fa-google-plus" aria-hidden="true"></i><span> Google+</span></a> + <a href="https://plus.google.com/share?url=/cn/docs/easy-build-microservice-system-part-III/" class="btn btn--google-plus" title="分享 Google Plus"><i class="fa fa-fw fa-google-plus" aria-hidden="true"></i><span> Google+</span></a> - <a href="https://www.linkedin.com/shareArticle?mini=true&url=/cn/docs/how-to-grow-up-to-be-an-apache-committer/" class="btn btn--linkedin" title="分享 LinkedIn"><i class="fa fa-fw fa-linkedin" aria-hidden="true"></i><span> LinkedIn</span></a> + <a href="https://www.linkedin.com/shareArticle?mini=true&url=/cn/docs/easy-build-microservice-system-part-III/" class="btn btn--linkedin" title="分享 LinkedIn"><i class="fa fa-fw fa-linkedin" aria-hidden="true"></i><span> LinkedIn</span></a> </section> <nav class="pagination"> - <a href="/cn/docs/easy-build-microservice-system-part-II/" class="pagination--pager" title="轻松微服务系列:快速实现客户关系管理系统的用户服务 + <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" class="pagination--pager" title="如何从一名开源小白成长为Apache Committer ">向前</a> @@ -520,7 +645,7 @@ <input type="url" id="comment-form-url" name="fields[url]" tabindex="4"/> </fieldset> <fieldset class="hidden" style="display: none;"> - <input type="hidden" name="options[slug]" value="how-to-grow-up-to-be-an-apache-committer"> + <input type="hidden" name="options[slug]" value="easy-build-microservice-system-part-III"> <label for="comment-form-location">Not used. Leave blank if you are a human.</label> <input type="text" id="comment-form-location" name="fields[hidden]" autocomplete="off"/> </fieldset> @@ -699,8 +824,8 @@ <div class="col"> <ul> <p class="header">贡献</p> - <li><a href="https://github.com/apache/incubator-servicecomb-website/issues/new?title=Issue with _posts/cn/2018-06-06-how-to-grow-up-to-be-an-apache-committer.md">报告本网页问题</a></li> - <li><a href="https://github.com/apache/incubator-servicecomb-website/edit/master/_posts/cn/2018-06-06-how-to-grow-up-to-be-an-apache-committer.md">在Github上编辑此页</a></li> + <li><a href="https://github.com/apache/incubator-servicecomb-website/issues/new?title=Issue with _posts/cn/2018-06-07-easy-build-microservice-system-part-III.md">报告本网页问题</a></li> + <li><a href="https://github.com/apache/incubator-servicecomb-website/edit/master/_posts/cn/2018-06-07-easy-build-microservice-system-part-III.md">在Github上编辑此页</a></li> <li><a href="/cn/developers/submit-codes/">代码提交指南</a></li> <li><a href="/cn/security">安全</a></li> </ul> diff --git a/content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html b/content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html index 88185e8..cd2040c 100644 --- a/content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html +++ b/content/cn/docs/how-to-grow-up-to-be-an-apache-committer/index.html @@ -473,7 +473,7 @@ ">向前</a> - <a href="/docs/apache-servicecomb-incubating-day/" class="pagination--pager" title="Microservice Meetup: Detailed Agenda of Apache ServiceComb (incubating) Day + <a href="/cn/docs/easy-build-microservice-system-part-III/" class="pagination--pager" title="轻松微服务系列:开发高性能边缘服务 ">向后</a> </nav> diff --git a/content/cn/year-archive/index.html b/content/cn/year-archive/index.html index 32bb550..ab38db3 100644 --- a/content/cn/year-archive/index.html +++ b/content/cn/year-archive/index.html @@ -462,6 +462,37 @@ <h2 class="archive__item-title" itemprop="headline"> + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 +</a> + + </h2> + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 +</p> + + <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> + + + + + 少于 1 分钟 阅读 + +</p> + + </article> +</div> + + + + + + + + +<div class="list__item"> + <article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork"> + + <h2 class="archive__item-title" itemprop="headline"> + <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" rel="permalink">如何从一名开源小白成长为Apache Committer </a> @@ -1370,6 +1401,26 @@ <!-- If not equal to previous then it must be unique as sorted --> +<!-- Push to group_names --> + + + + + + +<!-- If not equal to previous then it must be unique as sorted --> + + + + + +<!-- If not equal to previous then it must be unique as sorted --> + + +<!-- Push to group_names --> + + + @@ -1508,6 +1559,16 @@ <!-- If not equal to previous then it must be unique as sorted --> +<!-- Push to group_names --> + + + + + + +<!-- If not equal to previous then it must be unique as sorted --> + + @@ -2017,6 +2078,63 @@ +<!-- Collect if contains --> + + + +<!-- Push to group_items --> + + + +<!-- Collect if contains --> + + + +<!-- Push to group_items --> + + + +<!-- Collect if contains --> + + + +<!-- Push to group_items --> + + + + + + <h2 id="api-gateway" class="archive__subtitle">API Gateway</h2> + + + + + +<div class="list__item"> + <article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork"> + + <h2 class="archive__item-title" itemprop="headline"> + + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 +</a> + + </h2> + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 +</p> + + <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> + + + + + 少于 1 分钟 阅读 + +</p> + + </article> +</div> + + <h2 id="apache-way" class="archive__subtitle">Apache Way</h2> @@ -2213,6 +2331,39 @@ + <h2 id="edge-service" class="archive__subtitle">Edge Service</h2> + + + + + +<div class="list__item"> + <article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork"> + + <h2 class="archive__item-title" itemprop="headline"> + + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 +</a> + + </h2> + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 +</p> + + <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> + + + + + 少于 1 分钟 阅读 + +</p> + + </article> +</div> + + + + <h2 id="jwt" class="archive__subtitle">JWT</h2> @@ -2469,6 +2620,39 @@ + <h2 id="zuul" class="archive__subtitle">Zuul</h2> + + + + + +<div class="list__item"> + <article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork"> + + <h2 class="archive__item-title" itemprop="headline"> + + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 +</a> + + </h2> + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 +</p> + + <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> + + + + + 少于 1 分钟 阅读 + +</p> + + </article> +</div> + + + + <h2 id="gradle" class="archive__subtitle">gradle</h2> diff --git a/content/docs/apache-servicecomb-incubating-day-report/index.html b/content/docs/apache-servicecomb-incubating-day-report/index.html index 0d44b88..74343a1 100644 --- a/content/docs/apache-servicecomb-incubating-day-report/index.html +++ b/content/docs/apache-servicecomb-incubating-day-report/index.html @@ -635,11 +635,11 @@ About 80 participants attended the workshop on-site and about 300 participants w <h2 class="archive__item-title" itemprop="headline"> - <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" rel="permalink">如何从一名开源小白成长为Apache Committer + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 </a> </h2> - <p class="archive__item-excerpt" itemprop="description">如何从一名开源小白成长为Apache Committer + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 </p> <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> diff --git a/content/docs/apache-servicecomb-incubating-day/index.html b/content/docs/apache-servicecomb-incubating-day/index.html index 879b740..6a9b481 100644 --- a/content/docs/apache-servicecomb-incubating-day/index.html +++ b/content/docs/apache-servicecomb-incubating-day/index.html @@ -567,7 +567,7 @@ The microservice open source project - Apache ServiceComb (incubating) will host <nav class="pagination"> - <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" class="pagination--pager" title="如何从一名开源小白成长为Apache Committer + <a href="/cn/docs/easy-build-microservice-system-part-III/" class="pagination--pager" title="轻松微服务系列:开发高性能边缘服务 ">Previous</a> @@ -742,11 +742,11 @@ The microservice open source project - Apache ServiceComb (incubating) will host <h2 class="archive__item-title" itemprop="headline"> - <a href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" rel="permalink">如何从一名开源小白成长为Apache Committer + <a href="/cn/docs/easy-build-microservice-system-part-III/" rel="permalink">轻松微服务系列:开发高性能边缘服务 </a> </h2> - <p class="archive__item-excerpt" itemprop="description">如何从一名开源小白成长为Apache Committer + <p class="archive__item-excerpt" itemprop="description">轻松微服务系列:开发高性能边缘服务 </p> <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> diff --git a/content/feed.xml b/content/feed.xml index a2e2229..5b8dbcf 100644 --- a/content/feed.xml +++ b/content/feed.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.4.3">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2018-07-05T17:36:57+08:00</updated><id>/</id><title type="html">Apache ServiceComb (incubating)</title><subtitle>The homepage of ServiceComb</subtitle><author><name>{"name"=>nil, "avatar"=> [...] +<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.4.3">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2018-07-12T20:46:46+08:00</updated><id>/</id><title type="html">Apache ServiceComb (incubating)</title><subtitle>The homepage of ServiceComb</subtitle><author><name>{"name"=>nil, "avatar"=> [...] <p> <br /> <strong>Event Date/Time</strong>: Wednesday, June 27, 2018, 11:00 – 17:30</p> @@ -322,7 +322,163 @@ The microservice open source project - Apache ServiceComb (incubating) will host <p> <br /> <strong>If you want to freely visit the LC3 booth except attending the meet up , please go to our Gitter to inquire:</strong> <br /> -<a href="https://gitter.im/ServiceCombUsers/Lobby">ServiceComb Gitter Room</a></p></content><author><name>Zen Lin</name><email>zenlintechnofr...@gmail.com</email><uri>http://zenlintechnofreak.github.io</uri></author><category term="microservice" /><category term="Meetup" /><summary type="html">Real time updated information of Apache ServiceComb (incubating) Day</summary></entry><entry xml:lang="cn"><title type="html">如何从一名开源小白成长为Apache Committer</title><link h [...] +<a href="https://gitter.im/ServiceCombUsers/Lobby">ServiceComb Gitter Room</a></p></content><author><name>Zen Lin</name><email>zenlintechnofr...@gmail.com</email><uri>http://zenlintechnofreak.github.io</uri></author><category term="microservice" /><category term="Meetup" /><summary type="html">Real time updated information of Apache ServiceComb (incubating) Day</summary></entry><entry xml:lang="cn"><title type="html">轻松微服务系列:开发高性能边缘服务</title><link href="/cn/do [...] +<p>在前一篇博文<a href="http://servicecomb.incubator.apache.org/cn/docs/easy-build-microservice-system-part-II/">《轻松微服务系列:快速实现客户关系管理系统的用户服务》</a>,我们已经详细演示了从Archetype创建微服务后如何填充业务逻辑,快速构建包含JWT认证的用户服务。这篇博文我们将目光聚焦在Edge服务上,介绍如何构建高性能边缘服务应对高吞吐API网关的挑战。</p> + +<h3 id="什么是边缘服务edge-service">什么是边缘服务(Edge Service)</h3> +<p>边缘服务也是一个微服务,微服务化系统通常使用边缘服务(Edge Service)作为所有其它微服务的统一入口,因此它也常常会被称为API Gateway,使用边缘服务的好处有如下几点:</p> +<ul> + <li>动态路由:动态配置URL地址与微服务之间的对应关系,便于扩展,以及实现版本灰度发布等;</li> + <li>统一认证:在入口处进行访问认证,避免需要在所有的微服务中都承载重复的认证机制;</li> + <li>集中监控:与统一认证类似,在边缘服务对入口调用进行监控,容易统计流量信息。</li> +</ul> + +<h3 id="边缘服务的作用和原理">边缘服务的作用和原理</h3> +<p>我们先来看不使用边缘服务,UI直接调用用户服务的场景:</p> + +<p><img src="/assets/images/scaffold/DirectInvoke.png" alt="DirectInvoke" /></p> + +<p>可以看出这种调用方式,UI缺乏一定的灵活性,体现在:</p> +<ul> + <li>UI的实现绑定了Chassis的编程语言Java,无法使用PHP等其它前端技术开发;</li> + <li>UI访问微服务的路径无法动态配置,如果作为后端的微服务系统发生调整,则UI很可能需要修改;</li> + <li>UI很容易混入复合(编排)调用的逻辑,使得结构变得复杂难以维护。</li> +</ul> + +<p>我们再看引入边缘服务后,UI如何通过边缘服务调用用户服务:</p> + +<p><img src="/assets/images/scaffold/InvokeViaEdge.png" alt="InvokeViaEdge" /></p> + +<p>Edge服务将在<code class="highlighter-rouge">9090</code>端口上接受http rest调用,我们设计了下面的转发规则:</p> + +<div class="language-text highlighter-rouge"><pre class="highlight"><code>http://{edge-host-name}:9090/{ServiceComb微服务Name}/{服务路径&amp;参数} +</code></pre> +</div> + +<p>用户微服务名(<code class="highlighter-rouge">service_description.name</code>)是<code class="highlighter-rouge">user-service</code>,因此login调用URL:<em>cse://user-service/login</em>可以通过:<em>http://{edge-host-name}:9090/user-service/login</em> 访问。</p> + +<p>如此一来,微服务名成为了路径的一部分,http协议的<code class="highlighter-rouge">hostname</code>和<code class="highlighter-rouge">port</code>将固定指向Edge服务保持不变,灵活性大大增加了。</p> + +<p>到此我们还可以再做一点点改进,引入一个自定义配置<code class="highlighter-rouge">edge.routing-short-path.{简称}</code>,映射微服务名:</p> + +<div class="highlighter-rouge"><pre class="highlight"><code>edge: + routing-short-path: + user: user-service +</code></pre> +</div> + +<p>上面的配置代表:<em>http://{edge-host-name}:9090/user/login</em> 等效于:<em>http://{edge-host-name}:9090/user-service/login</em> ,如此一来:</p> +<ol> + <li>URL能够更加简洁;</li> + <li>当微服务名发生变化,只需要调整对应的配置,不需要更改前端UI路径代码。</li> +</ol> + +<h3 id="实现边缘服务">实现边缘服务</h3> +<h4 id="第一步引入edge-core依赖">第一步:引入Edge Core依赖</h4> +<div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;dependency&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.apache.servicecomb<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>edge-core<span class="nt">&lt;/artifactId&gt;</span> +<span class="nt">&lt;/dependency&gt;</span> +</code></pre> +</div> + +<h4 id="第二步编写调度器dispatcher">第二步:编写调度器Dispatcher</h4> +<p>Edge服务的核心就是调度器Dispatcher,ServiceComb Edge Core中的Dispatcher基于高性能的Vertx Reactive,轻松应对百万量级API请求的挑战;只需要继承AbstractEdgeDispatcher抽象类,添加对应的逻辑即可:</p> + +<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">EdgeDispatcher</span> <span class="kd">extends</span> <span class="n">AbstractEdgeDispatcher</span> <span class="o">{</span> + <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">LOGGER</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class=" [...] + + <span class="c1">//此Dispatcher的优先级,Order级越小,路由策略优先级越高</span> + <span class="kd">public</span> <span class="kt">int</span> <span class="nf">getOrder</span><span class="o">()</span> <span class="o">{</span> + <span class="k">return</span> <span class="mi">10000</span><span class="o">;</span> + <span class="o">}</span> + + <span class="c1">//初始化Dispatcher的路由策略</span> + <span class="kd">public</span> <span class="kt">void</span> <span class="nf">init</span><span class="o">(</span><span class="n">Router</span> <span class="n">router</span><span class="o">)</span> <span class="o">{</span> + <span class="c1">///捕获 {ServiceComb微服务Name}/{服务路径&amp;参数} 的URL</span> + <span class="n">String</span> <span class="n">regex</span> <span class="o">=</span> <span class="s">"/([^\\\\/]+)/(.*)"</span><span class="o">;</span> + <span class="n">router</span><span class="o">.</span><span class="na">routeWithRegex</span><span class="o">(</span><span class="n">regex</span><span class="o">).</span><span class="na">handler</span><span class="o">(</span><span class="n">CookieHandler</span><span class="o"> [...] + <span class="n">router</span><span class="o">.</span><span class="na">routeWithRegex</span><span class="o">(</span><span class="n">regex</span><span class="o">).</span><span class="na">handler</span><span class="o">(</span><span class="n">createBodyHandler</span><span class="o" [...] + <span class="n">router</span><span class="o">.</span><span class="na">routeWithRegex</span><span class="o">(</span><span class="n">regex</span><span class="o">).</span><span class="na">failureHandler</span><span class="o">(</span><span class="k">this</span><span class="o">: [...] + <span class="o">}</span> + + <span class="c1">//处理请求,请注意</span> + <span class="kd">private</span> <span class="kt">void</span> <span class="nf">onRequest</span><span class="o">(</span><span class="n">RoutingContext</span> <span class="n">context</span><span class="o">)</span> <span class="o">{</span> + <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">pathParams</span> <span class="o">=</span> <span class="n">context</span><span class="o"& [...] + <span class="c1">//从匹配的param0拿到{ServiceComb微服务Name}</span> + <span class="kd">final</span> <span class="n">String</span> <span class="n">service</span> <span class="o">=</span> <span class="n">pathParams</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"param0"</span><span class="o&qu [...] + <span class="c1">//从匹配的param1拿到{服务路径&amp;参数}</span> + <span class="n">String</span> <span class="n">path</span> <span class="o">=</span> <span class="s">"/"</span> <span class="o">+</span> <span class="n">pathParams</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">" [...] + + <span class="c1">//还记得我们之前说的做出一点点改进吗?引入一个自定义配置edge.routing-short-path.{简称},映射微服务名;如果简称没有配置,那么就认为直接是微服务的名</span> + <span class="kd">final</span> <span class="n">String</span> <span class="n">serviceName</span> <span class="o">=</span> <span class="n">DynamicPropertyFactory</span><span class="o">.</span><span class="na">getInstance</span><span class="o">()</span> + <span class="o">.</span><span class="na">getStringProperty</span><span class="o">(</span><span class="s">"edge.routing-short-path."</span> <span class="o">+</span> <span class="n">service</span><span class="o">,</span> <span class="n">service</span><span class="o">).</span>&l [...] + + <span class="c1">//创建一个Edge转发</span> + <span class="n">EdgeInvocation</span> <span class="n">edgeInvocation</span> <span class="o">=</span> <span class="k">new</span> <span class="n">EdgeInvocation</span><span class="o">();</span> + <span class="c1">//允许接受任意版本的微服务实例作为Provider,未来我们会使用此(设置版本)能力实现灰度发布</span> + <span class="n">edgeInvocation</span><span class="o">.</span><span class="na">setVersionRule</span><span class="o">(</span><span class="n">DefinitionConst</span><span class="o">.</span><span class="na">VERSION_RULE_ALL</span><span class="o">);</span> + <span class="n">edgeInvocation</span><span class="o">.</span><span class="na">init</span><span class="o">(</span><span class="n">serviceName</span><span class="o">,</span> <span class="n">context</span><span class="o">,</span> <span class="n">path</span><span class="o">,< [...] + <span class="n">edgeInvocation</span><span class="o">.</span><span class="na">edgeInvoke</span><span class="o">();</span> + <span class="o">}</span> +<span class="o">}</span> +</code></pre> +</div> + +<h4 id="第三步加载调度器dispatcher">第三步:加载调度器Dispatcher</h4> +<p>ServiceComb Edge使用SPI(Service Provider Interface)的方式加载已经编写好的调度器Dispatcher,在resources目录下创建<code class="highlighter-rouge">META-INF.services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher</code>配置文件,写入上一步EdgeDispatcher的类全名:</p> + +<div class="language-text highlighter-rouge"><pre class="highlight"><code>{EdgeDispatcher的包名}.EdgeDispatcher +</code></pre> +</div> + +<h4 id="第四步配置microserviceyaml">第四步:配置microservice.yaml</h4> +<p>边缘服务本身也是一个微服务,同样需要配置microservice.yaml:</p> + +<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">APPLICATION_ID</span><span class="pi">:</span> <span class="s">scaffold</span> +<span class="s">service_description</span><span class="pi">:</span> + <span class="s">name</span><span class="pi">:</span> <span class="s">edge-service</span> + <span class="s">version</span><span class="pi">:</span> <span class="s">0.0.1</span> +<span class="s">servicecomb</span><span class="pi">:</span> + <span class="s">service</span><span class="pi">:</span> + <span class="s">registry</span><span class="pi">:</span> + <span class="c1">#配置ServiceCenter使得Edge能够发现其他微服务</span> + <span class="s">address</span><span class="pi">:</span> <span class="s">http://127.0.0.1:30100</span> + <span class="c1">#配置Rest Endpoint</span> + <span class="s">rest</span><span class="pi">:</span> + <span class="s">address</span><span class="pi">:</span> <span class="s">0.0.0.0:9090</span> + +<span class="c1">#自定义的简称机制配置(这是我们自行扩展实现的)</span> +<span class="s">edge</span><span class="pi">:</span> + <span class="s">routing-short-path</span><span class="pi">:</span> + <span class="s">user</span><span class="pi">:</span> <span class="s">user-service</span> +</code></pre> +</div> + +<blockquote> + <p>提示:</p> + <ol> + <li>除了配置Rest Endpoint,我们也支持配置Highway Endpoint,但Highway Endpoint只支持ServiceComb开发的微服务调用;</li> + <li>microservice.yaml中没有配置Handler,Edge支持所有Consumer端Handler,不支持Producer端Handler,调用链原理如下:</li> + </ol> + + <p><img src="/assets/images/scaffold/EdgeOnlySupportConsumerHandler.png" alt="EdgeOnlySupportConsumerHandler" /></p> + +</blockquote> + +<h3 id="验证边缘服务">验证边缘服务</h3> +<p>启动用户微服务和Edge服务,使用<a href="https://www.getpostman.com/">Postman</a>注册一个用户:</p> + +<p><img src="/assets/images/scaffold/LogonViaEdge.png" alt="LogonViaEdge" /></p> + +<p>成功,现在我们使用新注册的用户名<code class="highlighter-rouge">ldg</code>登录:</p> + +<p><img src="/assets/images/scaffold/LoginViaEdge.png" alt="LoginViaEdge" /></p> + +<p>同样成功,并在Response中已经包含了正确的<code class="highlighter-rouge">AUTHORIZATION</code>Header。</p> + +<h3 id="性能比拼">性能比拼</h3> +<p>ServiceComb Java Chassis也支持集成Netflix Zuul作为网关服务,我们做了一次性能比较,使用ServiceComb Edge作为网关吞吐能力大幅优于Netflix Zuul,性能测试项目源代码在<a href="https://github.com/zhengyangyong/gateway-perf">这里</a>。</p></content><author><name>Yangyong Zheng</name><email>yangyong.zh...@huawei.com</email><uri>https://zhengyangyong.github.io</uri></author><category term="Edge Service" /><category term="API Gateway" /><category term="Zuul" /><summary type="html">轻松微服务系列:开发高性能边缘服务</summary></ent [...] <p>今天收到了来自Apache Vote我成为Committer的邮件,代表自己的贡献得到了充分的肯定;除了感谢团队的给力支持,我更希望将自己的成长经历——如何践行Apache Way的心得介绍给大家,让大家爱上Apache开源社区,也能和我一样成长为自己喜爱项目的Committer。</p> <h3 id="根据个人贡献获得价值government-by-merit">根据个人贡献获得价值(Government By Merit)</h3> @@ -1362,305 +1518,4 @@ java -jar xxxx.jar <p>这个最关键了,大家扫码,上面是ServiceComb小助手,可以帮你拉到微信群里,如果大家有兴趣想加入到我们SAGA项目开发可以与ServiceComb小助手联系。</p> -<p><img src="/assets/images/saga/Saga.039.jpeg" alt="" /></p></content><author><name>Willem Jiang</name></author><category term="Saga" /><category term="QCon" /><summary type="html">2018年QConBeijing Saga分布式事务解决方案与实践演讲实录</summary></entry><entry xml:lang="cn"><title type="html">如何设计一个优质的微服务框架:Apache ServiceComb 的开放性设计</title><link href="/cn/docs/open-design/" rel="alternate" type="text/html" title="如何设计一个优质的微服务框架:Apache ServiceComb 的开放性设计" /><published [...] -本文讲述了整个 开源微服务框架 Apache ServiceComb 设计形成的前因后果,尝试从理念、思想和实践结合的维度剖析一个优质的微服务框架应该具备哪些要素,包括但不限于 对开发者友好、高性能、内外部扩展性等。 <br /> -阅读本文有利于加深对微服务理念和框架的理解,给予微服务用户或开发者以帮助,这也是 Apache ServiceComb 的前身华为云微服务引擎的智慧结晶,从细节处承载了华为云自身多年云化转型的经验。</p> - -<!-- more --> - -<h2 id="写在前面">写在前面</h2> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 的前身为华为云的 <a href="https://support.huaweicloud.com/usermanual-servicestage/zh-cn_topic_0053812706.html">微服务引擎 CSE (Cloud Service Engine) 云服务</a>, ServiceComb 的早期版本和多数第一批做微服务或分布式框架先贤一样,为了追求高性能,做过非常多如 改善编码效率 和改进通信协议等尝试。然而,随着业务规模的递增,需求也逐渐呈现多样化,单方面通过传统手段追求高性能导致在面对多样化需求时遇到了各种挑战,遗留系统的通信、接入各种不同的终端、协议健壮性、防攻击等各种挑战迎面而来。</p> - -<p>Apache ServiceComb,愿景是帮助企业快速构建云原生应用,通过一系列解决方案帮助用户快速开发微服务应用的同时实现对这些微服务应用的高效运维管理,保持中立性以避免厂商LockIn成为了关键任务。对于此, Apache ServiceComb 需要有友好的机制能够对接各微服务主流技术栈技术 或 开发框架。</p> - -<p>在系列挑战的驱动下, Aapche ServiceComb 设计团队逐步形成了 “全面开放,使用标准协议,架构易于拆分和扩展,对开发人员友好,可以与业界其他主流框架互通集成” 的共识, 本文将着重分享这些共识是如何体现在Apache ServiceComb 的设计中的。</p> - -<h2 id="开放和标准">开放和标准</h2> - -<p>开放和标准应用到设计的不同的层面。一方面是连接组织和开发人员,一方面是连接异构系统。组织和开发人员的复杂性来源于技能的多样性,大家使用不同的开发语言,同一种开发语言存在多样的开发习惯;系统的多样性来源于系统之间的通信协议,为了实现与异构系统的通信,必须具备良好的适配不同通信协议的能力。</p> - -<h3 id="连接组织和开发人员">连接组织和开发人员</h3> - -<h4 id="编程风格">编程风格</h4> - -<p>每位技术人员都或多或少拥有自己的 Coding 习惯或爱好的技术, 使用个人熟练的方式从事技术工作往往更加高效和舒适。</p> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 的早期版本实现了 gRPC 协议,然而在项目演进过程中我们发现大量技术人员并不熟悉书写 IDL , 对 IDL 具体支持哪些特性也不清楚。 大多数情况下,用户每碰到一个场景就需要翻开协议规范看一遍, 而 IDL 缺少配套的编辑或语法检查等工具也导致了开发效率的降低。</p> - -<p>于是 Apache ServiceComb 设计团队开始思考是否有方法能够在确保保持用户开发习惯的前提下支持 gRPC 。</p> - -<p>设计团队结合自己的 Java 编程史,分析当下主流框架,并听取社区用户的反馈找到了一些共性:</p> - -<ul> - <li>使用 RPC 方式描述对外接口。gRPC 、Corba 、WebService 等技术人员谙于此道。</li> - <li>使用 JAX-RS 或 Spring MVC 风格开发 REST 接口。REST 风格开发随着微服务架构兴起,JAX-RS 和 Spring MVC 已然成为 Java REST 的开发事实标准, Spring 的拥抱者都比较熟悉。</li> -</ul> - -<p>Apache ServiceComb 很快在社区设计层面达成了一致,通过缺省支持以上共性来拥抱90%的开发者, 让大多数的 Java 开发者们能够快速开始工作。</p> - -<p>除以上共识外,Apache ServiceComb 还额外做了进一步的优化,以保证不同编程风格的兼容性,使用户或开发者倍感灵活及舒适。</p> - -<p>在下面的例子中,展示了 Provider和Consumer 代码的各种实现,在同一个微服务中,这些编程方式可以同时出现;同一段 Consumer 代码中可以访问各种不同的编程风格的 Provider 实现。</p> - -<p><strong>RPC 方式的 Provider</strong></p> - -<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="nd">@RpcSchema</span><span class="o">(</span><span class="n">schemaId</span><span class="o">=</span><span class="s">"hello"</span><span class="o">)</span> -<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloImpl</span> <span class="kd">implements</span> <span class="n">Hello</span><span class="o">{</span> - <span class="nd">@Override</span> - <span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHi</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">){</span> - <span class="k">return</span><span class="s">"Hello"</span><span class="o">+</span><span class="n">name</span><span class="o">;</span> - <span class="o">}</span> - - <span class="nd">@Override</span> - <span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">(</span><span class="n">Person</span> <span class="n">person</span><span class="o">){</span> - <span class="k">return</span><span class="s">"Helloperson"</span><span class="o">+</span><span class="n">person</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span> - <span class="o">}</span> -<span class="o">}</span> -</code></pre> -</div> - -<p><strong>JAX-RS 方式的 Provider</strong></p> - -<p><em>代码片段来自于 <a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/samples/jaxrs-sample">Apache ServiceComb JAX-RS sample</a></em></p> - -<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="nd">@RestSchema</span><span class="o">(</span><span class="n">schemaId</span><span class="o">=</span><span class="s">"jaxrsHello"</span><span class="o">)</span> -<span class="nd">@Path</span><span class="o">(</span><span class="s">"/jaxrshello"</span><span class="o">)</span> -<span class="nd">@Produces</span><span class="o">(</span><span class="n">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON</span><span class="o">)</span> -<span class="kd">public</span> <span class="kd">class</span> <span class="nc">JaxrsHelloImpl</span> <span class="kd">implements</span> <span class="n">Hello</span><span class="o">{</span> - - <span class="nd">@Path</span><span class="o">(</span><span class="s">"/sayhi"</span><span class="o">)</span> - <span class="nd">@POST</span> - <span class="nd">@Override</span> - <span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHi</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">){</span> - <span class="k">return</span><span class="s">"Hello"</span><span class="o">+</span><span class="n">name</span><span class="o">;</span> - <span class="o">}</span> - - <span class="nd">@Path</span><span class="o">(</span><span class="s">"/sayhello"</span><span class="o">)</span> - <span class="nd">@POST</span> - <span class="nd">@Override</span> - <span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">(</span><span class="n">Person</span> <span class="n">person</span><span class="o">){</span> - <span class="k">return</span><span class="s">"Helloperson"</span><span class="o">+</span><span class="n">person</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span> - <span class="o">}</span> -<span class="o">}</span> -</code></pre> -</div> - -<p><strong>Spring MVC 方式的 Provider</strong></p> - -<p><em>代码片段来自于 <a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/samples/springmvc-sample">Apache ServiceComb Spring MVC sample</a></em></p> - -<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="nd">@RestSchema</span><span class="o">(</span><span class="n">schemaId</span><span class="o">=</span><span class="s">"springmvcHello"</span><span class="o">)</span> -<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">path</span><span class="o">=</span><span class="s">"/springmvchello"</span><span class="o">,</span><span class="n">produces</span><span class="o">=</span><span class="n">MediaType</span><span class=&quo [...] -<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SpringmvcHelloImpl</span> <span class="kd">implements</span> <span class="n">Hello</span><span class="o">{</span> - - <span class="nd">@Override</span> - <span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">path</span><span class="o">=</span><span class="s">"/sayhi"</span><span class="o">,</span><span class="n">method</span><span class="o">=</span><span class="n">RequestMethod</span><span class="o&q [...] - <span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHi</span><span class="o">(</span><span class="nd">@RequestParam</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">"name"</span><span class="o" [...] - <span class="k">return</span><span class="s">"Hello"</span><span class="o">+</span><span class="n">name</span><span class="o">;</span> - <span class="o">}</span> - - <span class="nd">@Override</span> - <span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">path</span><span class="o">=</span><span class="s">"/sayhello"</span><span class="o">,</span><span class="n">method</span><span class="o">=</span><span class="n">RequestMethod</span><span class=" [...] - <span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">(</span><span class="nd">@RequestBody</span> <span class="n">Person</span> <span class="n">person</span><span class="o">){</span> - <span class="k">return</span><span class="s">"Helloperson"</span><span class="o">+</span><span class="n">person</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span> - <span class="o">}</span> -<span class="o">}</span> -</code></pre> -</div> - -<p><strong>RPC 方式访问上述三种服务的 Consumer</strong></p> - -<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="nd">@RpcReference</span><span class="o">(</span><span class="n">microserviceName</span><span class="o">=</span><span class="s">"hello"</span><span class="o">,</span><span class="n">schemaId</span><spa [...] -<span class="kd">private</span> <span class="n">Hello</span> <span class="n">hello</span><span class="o">;</span> -<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">hello</span><span class="o">.</span><span class="na">sayHi</span><span class="o">(</span><span [...] -</code></pre> -</div> - -<p><em>以上代码片段全部出自 <a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/samples/">Apache ServiceComb Samples</a>,有兴趣者可阅读了解或贡献更多的智慧。</em></p> - -<p>直至此处,或许开发者会产生疑问,既然 Consumer 可以通过一致的 API 方式访问不同的Provider,为何还需要额外的 JAX-RS 和 Spring MVC 标签?</p> - -<p>原因是,这里的设计依据是 <a href="http://servicecomb.incubator.apache.org/cn/">Apache ServiceComb</a>的 Consumer考虑的不仅限于 类SDK 的 Consumer,还有浏览器等非 SDK 类的 Consumer,浏览器的 Conumer 识别的是 Http 形式的消息。 通过定义和使用这些标签, 我们可以更加精细的指定浏览器如何访问后台接口。 类似于 Web Service 的 WSDL 描述语言, Apache ServiceComb 称之为<a href="http://servicecomb.incubator.apache.org/cn/users/service-contract/">服务契约</a>。</p> - -<p>服务的契约会在服务运行时通过代码定义自动生成,并注册到<a href="https://github.com/apache/incubator-servicecomb-service-center">服务中心</a>。契约也可在运行时用于独立的服务治理逻辑开发,生成 Consumer 代码。此外,也可作为 API 文档对外发布,供非 SDK 的 Consumer 参考。</p> - -<h4 id="服务契约"><strong><a href="http://servicecomb.incubator.apache.org/cn/users/service-contract/">服务契约</a></strong></h4> - -<p>微服务强调服务自治,对外体现的功能全部以松耦合的接口方式提供,并且只能以通信的方式实现相互访问。此原则给团队协作带来了根本性的变革。</p> - -<p>微服务的一个开发团队通常由5~6个人的全功能团队组成,端到端的完成 场景需求分析、架构功能设计、开发和运维,团队组织结构和业务系统的架构相匹配。团队建立后的核心问题就是团队之间如何进行高效的协作沟通,以决定不同微服务之间的协作通信。</p> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">Apache ServiceComb</a> 通过确保让开发人员保持自己的固有编程习惯及设计上的松耦合灵活性,让微服务团队之间可以进行高效协作,以避免在不同的微服务团队讨论编程风格受限于历史旧账而浪费宝贵的精力和时间。</p> - -<p>在 RPC 的世界里,有 Corda IDL,WSDL,ProtoBuffer 等可以参考的优秀实践, REST 风格的接口让团队之间可以通过 HTTP 语义进行沟通,但却不能像 IDL 一样描述跨语言的数据格式。Open API 的出现很好地解决了这个问题。</p> - -<p>Open API 首先是一个不断发展壮大中的开放的标准。Open API 能兼顾 RPC 、REST 等不同的开发方式,并且吸收了大量的跨语言经验,能够在不同的语言之间进行解析。</p> - -<p>对于 Java 开发者,下面的代码片段是日常所打交道的:</p> - -<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">User</span><span class="pi">:</span> - <span class="s">type:object</span> - <span class="s">properties</span><span class="pi">:</span> -<span class="s">age</span><span class="pi">:</span> - <span class="s">type:integer</span> -</code></pre> -</div> - -<p>如果开发人员有丰富的跨语言开发经验,可以看出 Swagger 在解决跨语言编程方面API定义冲突的努力, 如 Swagger 通过 format 来定义数据类型的存储格式,以解决不同的语言在数据类型表示上的差异:</p> - -<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">User</span><span class="pi">:</span> - <span class="s">type:object</span> - <span class="s">properties</span><span class="pi">:</span> -<span class="s">age</span><span class="pi">:</span> - <span class="s">type:integer</span> - <span class="s">format:int32</span> -</code></pre> -</div> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache SerivceComb</a> 既遵循常规开发规范也特别关注开发效率。开发者可以先写接口定义后写代码, 也可直接通过自己熟悉的方式编写写代码, 两种方式都会生成 <a href="http://servicecomb.incubator.apache.org/cn/users/service-contract/">服务契约</a>(Open API 描述文件),并且将内容注册到<a href="https://github.com/apache/incubator-servicecomb-service-center">服务中心</a>。使用者可以从服务中心下载相关的服务契约进行开发。 Apache ServiceComb 的各种治理结构也是基于契约的,可以让开发者独立于业务实现对系统进 [...] - -<h3 id="连接异构系统">连接异构系统</h3> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 早期版本提供了gRPC、REST、SOAP等多种协议,当前主要<a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/">支持 REST 和Highway 高性能私有 RPC 两种协议</a>。</p> - -<h4 id="highway-高性能私有-rpc-协议"><a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/#highway-rpc%E5%8D%8F%E8%AE%AE">Highway 高性能私有 RPC 协议</a></h4> - -<p>gRPC 相对于 REST 的最显著优点就是性能,它采用长连接、高效的二进制序列化方式,提供多种语言支持, 提供了 IDL 语言约束开发者按照标准的方式工作, 一切看起来是那么的完美。</p> - -<p>实际上,<a href="http://servicecomb.incubator.apache.org/cn/">Apache ServiceComb </a>的第一轮重构,首选也是 gRPC 。历史第一次在<a href="https://support.huaweicloud.com/usermanual-servicestage/zh-cn_topic_0053812706.html">华为云 微服务引擎 CSE</a> 上线以后,面对了来自网关压力挑战。</p> - -<p>网关作为业务接入端,必须高效的管理连接和保证公平,长连接容易导致拒绝服务。gRPC 程序开发完成后,开发人员无法利用系统提供的各种工具进行测试,网络包分析也变得困难,给生产环境上的开发联调造成了困难。随着业务规模的增长,gRPC 面临了诸如“其他三方系统如何与之直接通信? 如何跨网关与它间接通信?”等更严峻的挑战。</p> - -<p>解决这些问题,将需要我们扩展和改善老的协议和程序,提供 gRPC 客户端支持,开发者需自行提供一个额外的表示层用于业务接口的逻辑转换,造成大量的重复代码。同时由于 gRPC 依赖于接口定义,并根据定义生成代码,一套代码只能跑在 gRPC 协议上,如果用户希望业务应用可以使用如 REST等其他更加灵活的方式, 就需自行重新实现一套新的代码逻辑。据以上的血泪史, gRPC 最终被 Apache ServiceComb 设计团队定义为只能在中小型系统内部之间使用,并通过协议网关与外部系统进行通信。并实现了 <a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/#highway-rpc%E5%8D%8F%E8%AE%AE">高性能私有协议 Highway</a> 作为RPC首选默认协议。</p> - -<h4 id="rest-通信协议"><a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/">REST 通信协议</a></h4> - -<p>REST 相较 gRPC ,最大的痛点是性能。</p> - -<p>多数技术人员脑海里一个不成文的根深蒂固的观点:”二进制编码效率远高于文本协议,采用二进制编码的系统的性能远高于采用文本的 HTTP ”。该观点甚至会让多数决策止步于理论,多数人甚至不愿尝试去优化 REST。</p> - -<p>可喜的是 <a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 迈出了重构 REST 底层通信实现的第一步,基于 Netty 的异步框架来替换 Tomcat 实现,实践的效果大大超出预期,部分基准测试数据结果显示比 gRPC 还好, gRPC最终输在了HTTP2 协议上的额外报文。</p> - -<p>优化后的 REST 和业界开源的其他基于二进制的 RPC 实现的性能基本持平。在一个简单的提供数据库查询的代码逻辑中,优化后的REST通信框架处理时间,占比总处理时间远小于千分之一,这意味着再继续在框架层面进行大量优化也抵不上业务应用层面最简单的一个操作带来的消耗,Apache ServiceComb对 REST 的优化已经满足要求,最终也选择了 <a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/">REST</a> 作为首选和缺省协议(HTTP + json)。</p> - -<p>我们并没有就此止步。</p> - -<p>需要迁移到 <a href="https://support.huaweicloud.com/usermanual-servicestage/zh-cn_topic_0053812706.html">华为云 微服务引擎 CSE</a> 的业务日益增长,部分历史遗留系统也需进行对接。通信协议对应不同的开发者接口,每每增加通信协议,则需要对业务代码进行大量的重复构建,造成大量无谓消耗。这是当时的华为云化转型以及当下很多云化转型企业或者云原生企业必将面临的痛点。</p> - -<p>于是乎,通信协议层被剥离了出来,和业务代码隔离,系统运行基于契约,<a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 实现通信协议扩展机制。通信协议扩展机制,帮助用户解决与 gRPC 框架、自定义二进制框架等许多遗留系统的对接通信问题。</p> - -<p>在 Apache ServiceComb 框架中,<a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/">切换协议</a>非常简单,不需要修改一行业务代码。多个协议共存也是允许的。</p> - -<div class="language-yaml highlighter-rouge"><pre class="highlight"><code><span class="s">ServiceComb</span><span class="pi">:</span> - <span class="s">rest</span><span class="pi">:</span> - <span class="s">address:0.0.0.0:8084</span> - <span class="s">highway</span><span class="pi">:</span> - <span class="s">address:0.0.0.0:8094</span> -</code></pre> -</div> - -<h2 id="扩展性">扩展性</h2> - -<p>扩展性是系统进一步发展的基石。<a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 创造性地将扩展性拓展到 Provider 和 Consumer,让开发者拥有一致的开发体验。</p> - -<h3 id="内部系统结构">内部系统结构</h3> - -<p>连接开发者和通信协议层面已经让系统具备了很大的扩展性。微服务化给系统解耦、团队自治带来了很大的灵活性,加快了开发生产效率,但同时带来了服务管控的复杂性,在微服务领域,不得不考虑雪崩效应、调用跟踪、性能监控与分析等实际管控治理问题。</p> - -<p>基于服务契约,<a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 提供了<a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/handlers">动态插拔扩展的处理链机制</a>,并且为这些管控治理能力提供了默认实现,用户可以灵活插拔这些处理模块,或调整它们的顺序以应对不同的处理场景,或自行实现以增加新的处理模块。Provider 和 Consumer 都会经过该处理链,这给客户端治理功能开发带来了极大的便利性。Apache ServiceComb 的运行结构如下:</p> - -<p class="figure-caption"><img src="/assets/images/open-design-running-arch.png" alt="running-arch" class="align-center" /> <br /> -图1 Apache ServiceComb 运行时架构</p> - -<p>Apache ServiceComb 同时支持同步和异步两种编程接口,并在通信实现上采用了纯异步方式,对于运行模型的扩展,也是基于异步回调接口的。该方式提供了比同步模式(比如 Filter)更加优雅灵活的扩展方式。</p> - -<p>在Apache ServiceComb 结构中,几个核心的扩展机制均在 <a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/core/src/main/java/org/apache/servicecomb/core">core 模块</a> 进行定义:</p> - -<p><strong><a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/core/src/main/java/org/apache/servicecomb/core/provider/producer">Producer Provider</a></strong></p> - -<p>Provider 编程模型的扩展,通过实现这个接口,可以适配不同的 Provider编 程风格;默认支持 RPC、Spring MVC 和 JAX-RS 三种风格。</p> - -<p><strong><a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/core/src/main/java/org/apache/servicecomb/core/provider/consumer">Consumer Provider</a></strong></p> - -<p>Consumer 编程模型的扩展,通过实现这个接口,可以适配不同的 Consumer 编程风格;默认支持 RPC和RestTemplate 两种风格。RestTemplate 是 Spring MVC 提供的 REST 编程接口,可以在服务层解除接口依赖,只依赖数据模型。</p> - -<p><strong><a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/core/src/main/java/org/apache/servicecomb/core/handler">Handler</a></strong></p> - -<p>处理链的接口,通过扩展该接口,可以在处理过程中插入任意的逻辑。默认已经支持<a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/handlers/handler-loadbalance">负载均衡</a>、<a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/handlers/handler-fault-injection">错误注入</a>、<a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/handlers/handler-flowcontrol-qps">流量控制</a>和<a hre [...] - -<p><strong><a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/transports">Transport</a></strong></p> - -<p>通信协议扩展,默认支持<a href="http://servicecomb.incubator.apache.org/cn/users/communicate-protocol/">REST over Vertx、Rest over Servlet、Highway</a>协议。</p> - -<p><strong>Invocation</strong></p> - -<p>中立的对象。所有的运行模型都面向这个中立的对象进行编程,当定义好服务接口后,对服务的治理和服务业务逻辑的开发可并行进行。在编程模型和通信模型里面,也面向这个对象进行编解码。</p> - -<h3 id="对接外部系统">对接外部系统</h3> - -<p><a href="https://github.com/apache/incubator-servicecomb-java-chassis">Apache ServiceComb Java-chassis</a> 预留了对接外部系统的接口,以让开发者或用户可以灵活快速切换使用第三方提供的服务,这里所指的外部系统包括但不限于:服务注册发现的服务中心、配置管控和治理的配置中心、运行监控和运维的治理中心等。</p> - -<p>下图展示了不同的开发框架支持和运行的第三方系统情况,这些基础服务都给开发者预留了可以进行支持接入的接口。</p> - -<p class="figure-caption"><img src="/assets/images/open-design-third-party-plugin.png" alt="third-party-plugin" class="align-center" /> <br /> -图2 Apache ServiceComb 外部扩展接入</p> - -<p>重要的扩展:</p> - -<p><strong><a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client">ServiceRegistryClient</a>:</strong></p> - -<p>实现这个接口以对接不同的注册服务。</p> - -<p><strong><a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/foundations/foundation-config">ConfigCenterConfigurationSource</a></strong></p> - -<p>实现这个接口以对接不同的配置服务。</p> - -<p>此外,ServiceComb还提供了对接<a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/tracing/tracing-zipkin">Zipkin</a>、Servo等开源系统的功能,这些可以从<a href="https://github.com/apache/incubator-servicecomb-java-chassis/">github代码</a>中查找到对应的例子。</p> - -<h3 id="运行环境集成">运行环境集成</h3> - -<p>一个完整的业务系统不是使用RPC框架就算完成了,它们还需要其他的计算资源。对于一般的业务系统都需要访问数据库,或者基于 J2EE 的设施进行工作。</p> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">开源微服务框架 Apache ServiceComb</a> 可以以轻量级的方式运行,也可集成到其他系统框架。下面的示意图说明了 Apache ServiceComb 的一些工作环境。</p> - -<p class="figure-caption"><img src="/assets/images/open-design-integrate-with-running-environment.png" alt="integrate-with-running-environment" class="align-center" /> <br /> -图3 Apache ServiceComb 运行环境集成</p> - -<ul> - <li>若业务只需 REST 接口,可以轻量级的方式运行 Apache ServiceComb 。所有的REST接口运行于ServiceComb 提供的 Netty HTTP 之上。</li> - <li>若业务是基于 J2EE 来构建,那么 Apache ServiceComb 可以作为一个 Servlet ,运行于 Web 容器里面(如 Tomcat、Jetty 等)。</li> - <li>若业务基于 Spring Boot 生态构建,Apache ServiceComb 可作为一个starter对外提供 REST 服务,开发者可以自由使用其他基于 Spring Boot 的功能。</li> -</ul> - -<p>由于 Apache ServiceComb 使用了Spring,因此天然继承了Spring的原有优势,可和很多通用的组件很好的集成,如 mybatis、JPA 等。各种集成方式,都可以从<a href="http://servicecomb.incubator.apache.org/cn/">ServiceComb官网</a>或者<a href="https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/demo">ServiceComb 示例库</a>找到对应的例子。</p> - -<h2 id="写在最后">写在最后</h2> - -<p>开源微服务框架 Apache ServiceComb 的主体代码是由华为云微服务引擎捐赠给 Apache 软件基金会的,愿景是帮助企业快速构建云原生应用,通过一系列解决方案帮助用户快速开发微服务应用的同时实现对这些微服务应用的高效运维管理。本次设计团队将开放性设计部分细节点点滴滴分享出来也是为了能够解放开发者和用户。</p> - -<p>当前越来越多的贡献者已加入到 社区行列,Apache ServiceComb 会和这些志愿者们一起一如既往坚持这个理念,争取给业界带来更多好的技术和分享。也期望有更多有志者一起行动。</p> - -<p><a href="http://servicecomb.incubator.apache.org/cn/docs/join_the_community/"><strong>如何加入Apache ServiceComb 社区</strong></a></p> - -<p><strong>致谢原稿作者: 刘宝</strong></p> - -<p><strong>参考文献</strong></p> - -<p>[1] 开源微服务框架 Apache ServiceComb 官网</p> - -<p><a href="http://servicecomb.incubator.apache.org/cn/">http://servicecomb.incubator.apache.org/cn/</a></p> - -<p>[2] 开源微服务框架 Apache ServiceComb 代码</p> - -<p><a href="https://github.com/apache/incubator-servicecomb-java-chassis">https://github.com/apache/incubator-servicecomb-java-chassis</a></p> - -<p><a href="https://github.com/apache/incubator-servicecomb-service-center">https://github.com/apache/incubator-servicecomb-service-center</a></p> - -<p><a href="https://github.com/apache/incubator-servicecomb-saga">https://github.com/apache/incubator-servicecomb-saga</a></p> - -<p>[3] 华为云微服务引擎 CSE(Cloud Service Engine)</p> - -<p>入口 <a href="https://www.huaweicloud.com/product/cse.html">https://www.huaweicloud.com/product/cse.html</a></p> - -<p>资料 <a href="http://support.huaweicloud.com/cse_dld/index.html">http://support.huaweicloud.com/cse_dld/index.html</a></p></content><author><name>Zen Lin, Bao Liu</name></author><category term="设计" /><category term="开放,扩展" /><summary type="html">本文讲述了整个 开源微服务框架 Apache ServiceComb 设计形成的前因后果,尝试从理念、思想和实践结合的维度剖析一个优质的微服务框架应该具备哪些要素,包括但不限于 对开发者友好、高性能、内外部扩展性>等。</summary></entry></feed> \ No newline at end of file +<p><img src="/assets/images/saga/Saga.039.jpeg" alt="" /></p></content><author><name>Willem Jiang</name></author><category term="Saga" /><category term="QCon" /><summary type="html">2018年QConBeijing Saga分布式事务解决方案与实践演讲实录</summary></entry></feed> \ No newline at end of file diff --git a/content/sitemap.xml b/content/sitemap.xml index 956a631..0f903f1 100644 --- a/content/sitemap.xml +++ b/content/sitemap.xml @@ -181,6 +181,10 @@ <lastmod>2018-06-06T11:00:00+08:00</lastmod> </url> <url> +<loc>/cn/docs/easy-build-microservice-system-part-III/</loc> +<lastmod>2018-06-07T19:00:00+08:00</lastmod> +</url> +<url> <loc>/docs/apache-servicecomb-incubating-day/</loc> <lastmod>2018-06-14T10:26:28+08:00</lastmod> </url> diff --git a/content/sitemap/index.html b/content/sitemap/index.html index 3c06d59..ac28007 100644 --- a/content/sitemap/index.html +++ b/content/sitemap/index.html @@ -377,6 +377,8 @@ <link rel="alternate" hreflang="cn" href="/cn/docs/how-to-grow-up-to-be-an-apache-committer/" /> +<link rel="alternate" hreflang="cn" href="/cn/docs/easy-build-microservice-system-part-III/" /> + <link rel="alternate" hreflang="en" href="/docs/apache-servicecomb-incubating-day/" /> <link rel="alternate" hreflang="cn" href="/cn/docs/apache-servicecomb-incubating-day/" /> diff --git a/content/users/service-heartbeat/index.html b/content/users/service-heartbeat/index.html index 69d6640..b743503 100644 --- a/content/users/service-heartbeat/index.html +++ b/content/users/service-heartbeat/index.html @@ -634,7 +634,7 @@ <h2 id="scenario">Scenario</h2> -<p>After a microservice instance is registered in the service center, the microservice need to periodically send heartbeats to the service center. If the service center receives no heartbeat within a specific period, the instance will be registered.</p> +<p>After a microservice instance is registered in the service center, the microservice need to periodically send heartbeats to the service center. If the service center receives no heartbeat within a specific period, the instance will be un-registered.</p> <h2 id="involved-apis">Involved APIs</h2>