blob: dbb2b768216997e916dde1dcd5b04b6d9fdd13d5 [file] [log] [blame]
<!doctype html>
<!--
Minimal Mistakes Jekyll Theme 4.4.1 by Michael Rose
Copyright 2017 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
-->
<html lang="cn" class="no-js">
<head>
<meta charset="utf-8">
<!-- begin SEO -->
<title>Consul Service Mesh实战 - Apache ServiceComb</title>
<meta name="description" content="Consul Service Mesh介绍与相关实践">
<meta name="author" content="Zhen Ju">
<meta property="og:locale" content="cn">
<meta property="og:site_name" content="Apache ServiceComb">
<meta property="og:title" content="Consul Service Mesh实战">
<link rel="canonical" href="https://github.com/pages/apache/incubator-servicecomb-website/cn/docs/consul-servicemesh">
<meta property="og:url" content="https://github.com/pages/apache/incubator-servicecomb-website/cn/docs/consul-servicemesh">
<meta property="og:description" content="Consul Service Mesh介绍与相关实践">
<meta name="twitter:site" content="@ServiceComb">
<meta name="twitter:title" content="Consul Service Mesh实战">
<meta name="twitter:description" content="Consul Service Mesh介绍与相关实践">
<meta name="twitter:url" content="">
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="@">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2018-07-21T00:00:00+08:00">
<script type="application/ld+json">
{
"@context" : "http://schema.org",
"@type" : "Person",
"name" : "Apache ServiceComb",
"url" : "https://github.com/pages/apache/incubator-servicecomb-website",
"sameAs" : null
}
</script>
<meta name="google-site-verification" content="HvJjNd7vvJ-yjSTHlBiIWEYxp_Hrz-PYEY5Idz9LRcA" />
<!-- end SEO -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Apache ServiceComb Feed">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
<script src="/assets/vendor/prism/prism.js"></script>
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css?v=1">
<link rel="stylesheet" href="/assets/vendor/prism/prism.css?v=1">
<!--[if lte IE 9]>
<style>
/* old IE unsupported flexbox fixes */
.greedy-nav .site-title {
padding-right: 3em;
}
.greedy-nav button {
position: absolute;
top: 0;
right: 0;
height: 100%;
}
</style>
<![endif]-->
<meta http-equiv="cleartype" content="on">
<!-- start custom head snippets -->
<!-- insert favicons. use http://realfavicongenerator.net/ -->
<link href="https://fonts.cat.net/css?family=Roboto:400,500,700|Source+Code+Pro" rel="stylesheet">
<script src="/assets/js/custom.js"></script>
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead" onmouseleave="$('#childrenShow').css('display', 'none')">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title active" href="/cn"><img src="https://www.apache.org/img/servicecomb.png"></a>
<ul class="visible-links">
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/cn/">首页</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/cn/developers/">项目</a>
</li>
<li class="def-nav-li" onmouseenter="$('#childrenShow').css('display', 'block')">
<a href="/cn/docs/users/">文档</a>
<ul id="childrenShow" class="def-children-show" onmouseleave="$('#childrenShow').css('display', 'none')">
<li><a href="/cn/docs/quick-start/" class="">入门指南</a></li>
<li><a href="/cn/docs/users/" class="">用户手册</a></li>
<li><a href="/cn/slides/" class="">大咖视频</a></li>
<li><a href="/cn/faqs/" class="">常见问题</a></li>
</ul>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/cn/developers/contributing">社区</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/cn/year-archive/">博文</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/cn/release/">下载</a>
</li>
</ul>
<button><div class="navicon"></div></button>
<ul class="hidden-links hidden"></ul>
<div class="nav-lang">
<a href=/docs/consul-servicemesh>English</a>
</div>
</nav>
</div>
</div>
</div>
<div id="main" role="main">
<div class="sidebar sticky">
<div class="back-to-home"><a href="/cn/">首页</a> > Consul Service Mesh实战</div>
<div itemscope itemtype="http://schema.org/Person">
<div class="author__content">
<h3 class="author__name" itemprop="name">Zhen Ju</h3>
<p class="author__bio" itemprop="description">
Curious about everything~
</p>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">关注</button>
<ul class="author__urls social-icons">
<li>
<a href="https://github.com/crystaldust" itemprop="url">
<i class="fa fa-fw fa-chain" aria-hidden="true"></i> 网站
</a>
</li>
<li>
<a href="mailto:juzhenatpku@gmail.com">
<meta itemprop="email" content="juzhenatpku@gmail.com" />
<i class="fa fa-fw fa-envelope-square" aria-hidden="true"></i> 电子邮箱
</a>
</li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs">
<i class="fa fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="http://schema.org/CreativeWork">
<meta itemprop="headline" content="Consul Service Mesh实战">
<meta itemprop="description" content="Consul Service Mesh介绍与相关实践">
<meta itemprop="datePublished" content="July 21, 2018">
<meta itemprop="dateModified" content="July 21, 2018">
<div class="page__inner-wrap">
<header>
<h1 class="page__title" itemprop="headline">Consul Service Mesh实战
</h1>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
少于 1 分钟 阅读
</p>
</header>
<section class="page__content" itemprop="text">
<h2 id="consul-service-mesh实战">Consul Service Mesh实战</h2>
<p>在最近发布的<a href="https://github.com/hashicorp/consul/releases">Consul1.2</a>中,<a href="https://www.hashicorp.com/">HashiCorp</a>宣布支持Service Mesh。作为一个优秀的分布式服务发现解决方案,Consul是如何支持Service Mesh的呢?本文将带读者一探究竟。</p>
<p>在Consul 1.2的<a href="https://www.hashicorp.com/blog/consul-1-2-service-mesh">release blog</a>中,Consul定义了Service Mesh的3个要素:</p>
<ol>
<li><strong>Discovery</strong>:服务可以互相找到</li>
<li><strong>Configuration</strong>:服务在运行时,可以从一个集中的源头获取配置</li>
<li><strong>Segmentation</strong>:服务之间的通信必须是加密并通过认证的</li>
</ol>
<p>实际上,Consul本身已经支持服务发现,并且实现了一个集群共享的KV存储方案,可以实现服务配置的存储。而最新的Consul 1.2中,新发布的Connect功能,可以为服务创建一个网络层的代理,这成为Consul Service Mesh方案中,数据面代理的基础。接下来,我们从这三个方面一一对Consul进行解析。</p>
<h4 id="discovery">Discovery</h4>
<p>Consul是一个跨数据中心的分布式服务发现解决方案。在Consul集群的每一个节点上,都运行一个Consul进程,成为一个Consul agent,一个agent可以以server或client两种模式运行。Client agent非常轻量,只需与Server agent交互,并维护Client自身很少的状态。而Server agent除了Client agent的所有功能,还提供额外的能力来完成基于Raft的一致性方案,因此Server agent的负载会更高,也需要更多的资源,运行在更加稳定的节点上。Consul agent可以通过join命令,指定集群中任意一个agent的IP,以加入集群,形成一个Consul cluster。如下图所示:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/consul-cluster.jpg" alt="consul-cluster" /></p>
<p>在单个节点上,Consul agent读取该节点服务的配置文件,获取该节点上服务的信息,并与cluster中其他agent通过gossip协议互相通信,完成集群内的服务注册与发现。当Consul cluster中的服务需要调用另一个服务时,可以通过API和DNS解析两种方式,向所在节点的Consul agent获取目标服务的具体地址,然后调用目标服务。</p>
<h4 id="configuration">Configuration</h4>
<p>除了服务注册与发现,Consul还内置了一个KV存储系统,用于Cluster之间共享数据。KV的Key是分层的,通过斜线<code class="highlighter-rouge">/</code>分隔,这样,可以在概念上对key进行组织和管理,用来保存不同的配置,并把配置分配给集群内的所有服务。例如,在一个集群内,运行了<code class="highlighter-rouge">webfront</code>服务,<code class="highlighter-rouge">webfront</code>服务需要获知当前是开发环境还是测试环境,以提供不同的页面表现。那么,我们在可以在节点A上用KV存储保存环境信息:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nodeA<span class="nv">$ </span>consul kv put services/webapi/metadata/env dev <span class="c">#假设env=dev表示测试环境</span>
</code></pre></div></div>
<p>服务运行过程中,假设任务调度器将<code class="highlighter-rouge">webfront</code>服务的实例调度到节点B和节点C,那么在节点B和C上可以通过Consul agent访问到环境信息:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nodeB<span class="nv">$ </span>consul kv get services/webapi/metadata/env
nodeB<span class="nv">$ </span>dev
</code></pre></div></div>
<p>当然,在实际的使用中,我们不仅可以通过命令行来获取KV数据,也可以通过RESTful API,向所在节点的Consul agent发送HTTP请求来获取数据。</p>
<h4 id="segmentation">Segmentation</h4>
<p>按照Consul的说明,Segmentation的意义在于使服务之间的网络请求都是经过TLS加密并认证的。那么,Consul是如何做到请求的自动TLS加密和认证的呢?</p>
<p>Consul 1.2新增了Connect功能,只需要在服务中增加一个<code class="highlighter-rouge">connect</code>配置,即可为该服务启动一个代理:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"service"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"webfront"</span><span class="p">,</span><span class="w">
</span><span class="nl">"connect"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"proxy"</span><span class="p">:</span><span class="w"> </span><span class="p">{}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>这样,Consul agent就会为<code class="highlighter-rouge">webfront</code>服务启动一个内置的proxy,proxy启动时,向所在节点的Consul agent(为了便于说明,假设为Client agent,其实Client/Server都是可能的)请求<code class="highlighter-rouge">webfront</code>所需要的root证书和leaf证书。Client agent检查本地的缓存,若已有所需证书,则直接将证书和私钥返回。否则就会生成一个新的私钥,并向Server agent发送CSR。Server对CSR进行验证,并返回签名的证书,Client agent拿到证书,把证书和私钥返回给proxy。这样,proxy就可以接受TLS请求了。这个过程如下:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/consul-tls.jpg" alt="consul-tls" /></p>
<p>并且,Consul中还有一个自动更新的机制,当Server中的根证书变化时,Client重新生成私钥,向Server发送CSR,获取签名的证书,并把签名的证书和私钥再发给proxy,完成证书的更新。</p>
<p>了解了Consul Connect,我们会发现,其实Connect功能帮每个服务启动了一个Proxy,对服务的inbound/outbound请求进行了TLS加密和认证,这个场景是否似曾相识?没错,就是Service Mesh中数据面sidecar的概念。只是这个Consul内建的sidecar目前能实现的功能还比较单一,只有TLS加密和认证。</p>
<p>现在,我们对Consul Service Mesh的三个要素都有了较为具体了解,那么,相比于一般意义上的Service Mesh方案,例如Istio,Conduit等,Consul的Service Mesh有何不同呢?我们不妨以Istio为例,看看Istio中是如何实现这三个要素的:</p>
<p><strong>Discovery</strong>:由Pilot结合服务发现机制(kubernetes,eureka,consul等)完成</p>
<p><strong>Configuration</strong>:由Pilot结合Kubernetes完成,用户使用kubectl定义Istio所需的Kubernetes资源,Pilot读取到这些资源后,转换为自己的Model,并通过xDS API将配置信息下发给Envoy</p>
<p><strong>Segmentation</strong>:Citadel结合Envoy完成,Citadel将证书颁发给每个服务的Envoy</p>
<p>因此,Istio的结构是这样的:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/istio-architecture.jpg" alt="istio-architecture" /></p>
<p>可以看到Discovery和Configuration都是在Istio控制面完成的。Segmentation是由控制面的Citadel+数据面的Envoy代理完成的。</p>
<p>根据HashiCorp的说明,在Consul的Service Mesh方案中,Consul作为控制面运行,Consul agent实现了服务发现和配置存储。同时,Consul agent再结合Connect启动的Proxy,完成了网络流量的加密与认证。如下图所示:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/consul-proxy-certs.jpg" alt="consul-proxy-certs" /></p>
<p>请注意,Consul的KV系统只完成了配置的存储,并没有像Istio一样,可以对配置进行动态修改并下发到数据面,目前Proxy的配置也是通过读取文件,然后在启动或重启代理时传入的,因此我们认为Consul的配置管理能力还需要完善。此外,因为Consul Connect启动的Proxy是一个4层代理,无法提供路由、熔断、重试等更高级的微服务治理能力,因此也不需要获取服务治理的配置。这是Consul Service Mesh的方案中治理能力欠缺的地方。不过,HashiCorp也表示Connect在1.2版本中只是Beta状态,未来会继续围绕Connect开发新的功能,包括UI的增强,支持Envoy作为proxy,与Nomad和Kubernetes的集成等。</p>
<h4 id="等等听说consul已经可以集成envoy了">等等,听说Consul已经可以集成Envoy了?</h4>
<p>没错!其实,在Consul1.2中,Connect已经可以通过指定一个可执行文件的路径来启动第三方代理了。Consul会以daemon模式启动第三方代理,在后台运行:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"service"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"webfront"</span><span class="p">,</span><span class="w">
</span><span class="nl">"connect"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"proxy"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"exec_mode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"daemon"</span><span class="p">,</span><span class="w">
</span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"/usr/bin/my-proxy"</span><span class="p">,</span><span class="w"> </span><span class="s2">"--listen"</span><span class="p">,</span><span class="w"> </span><span class="s2">"8800"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>那么,按照通常的思路,是不是可以直接指定Envoy,让Consul启动Envoy来实现集成呢?理论上确实可行,但是Consul是无法管理第三方代理的配置的,Envoy的配置只能由用户自行定义,增加了运维成本,也不便于管理。</p>
<p>这时,就轮到HashiCorp好基友<a href="https://www.solo.io/">solo.io</a>出品的<a href="https://github.com/solo-io/gloo-connect">Gloo Connect</a>闪亮登场了!solo.io是一家提供Cloud Native工具和集成方案的公司,例如支持Kubernetes和Istio的微服务debugger <a href="https://github.com/solo-io/squash">squash</a>,基于Envoy的function gateway解决方案<a href="https://github.com/solo-io/gloo">Gloo</a>。在刚刚过去的<a href="https://www.hashidays.com/">HashiDay 2018</a>上,solo.io和HashiCorp联合发布了Gloo Connect。Gloo产品线本身很有意思,Gloo与英文单词”胶水”(Glue)的发音一样,暗示着Gloo会作为”胶水”,将Cloud Native中的各种服务粘合在一起,那么,Gloo Connect是如何把Consul和Envoy粘合在一起的呢?</p>
<p>Gloo Connect作为Consul的第三方代理,在启动时会把Consul Connect proxy的配置和Gloo的配置转换成Envoy的配置,并启动Envoy实例。同时,Gloo Connect也可以通过命令行对Envoy的配置进行动态修改。下面,我们根据Gloo Connect的官方示例来演示如何将Consul与Envoy集成。</p>
<h6 id="tips">Tips</h6>
<p>根据Gloo Connect的<a href="https://github.com/solo-io/gloo-connect/blob/master/docs/getting-started/README.md">Getting Started文档</a>,Consul 1.2.0中,存在一个已知bug,运行示例需要下载一个<a href="https://github.com/solo-io/gloo-connect/releases/download/v0.1.0/consul">预先编译的Consul版本</a>,或者使用1.2.1版本,并把Consul配置到系统路径,或者当前目录。</p>
<p>首先,我们将gloo-connect项目clone到本地,进入getting-started目录,并编译运行<code class="highlighter-rouge">service.go</code></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git clone https://github.com/solo-io/gloo-connect/
<span class="nv">$ </span><span class="nb">cd </span>gloo-connect/docs/getting-started
<span class="nv">$ </span>go run service.go &amp;
</code></pre></div></div>
<p><code class="highlighter-rouge">service.go</code>运行后监听8080端口,交替返回200和500状态码。接下来,我们执行当前目录下的<code class="highlighter-rouge">run-consul.sh</code>脚本,该脚本会在<code class="highlighter-rouge">./run-data/consul-config</code>目录下生成两个配置信息<code class="highlighter-rouge">connect.json</code><code class="highlighter-rouge">service.json</code>,前者将gloo-connect指定为Consul Connect默认的proxy,后者定义了两个服务<code class="highlighter-rouge">microsvc1</code>(即我们运行的service.go) 和<code class="highlighter-rouge">test</code>,并定义了两者之间的代理:<code class="highlighter-rouge">microsvc1</code>配置了一个空规则的代理,<code class="highlighter-rouge">test</code>配置了一个监听1234端口的代理,任何访问1234端口的请求,都将被当作<code class="highlighter-rouge">test</code><code class="highlighter-rouge">microsvc1</code>的访问。最后,脚本启动consul,并设定consul的配置目录为<code class="highlighter-rouge">./run-data/consul-config</code>。此外,脚本还会运行gloo-connect和envoy,需要确保两者在系统路径或当前目录下并具有执行权限,gloo-connect项目的发布页面可以<a href="https://github.com/solo-io/gloo-connect/releases">下载编译好的gloo-connect和envoy</a></p>
<p>脚本启动后,我们通过进程管理工具,可以看到Consul为每个服务启动了第三方代理gloo-connect,而每个gloo-connect又启动了一个Envoy进程,并把转换好的配置传给Envoy:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/gloo-connect.png" alt="gloo-connect" /></p>
<p>此时,真正监听1234端口的就是Envoy进程了。下面,我们访问1234端口,会看到服务交替返回状态码200和500:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/req-microsvc1-by-proxy.png" alt="req-microsvc1-by-proxy" /></p>
<p>我们用gloo-connect命令为<code class="highlighter-rouge">microsvc1</code>的Envoy sidecar配置一条retry规则:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./gloo-connect <span class="nb">set </span>service microsvc1 <span class="nt">--http</span> <span class="nt">--retries</span><span class="o">=</span>3
</code></pre></div></div>
<p>这样,当通过Envoy代理访问<code class="highlighter-rouge">microsvc1</code>时,如果遇到500,会重试3次,其实在第一次重试时就会返回200了,因此我们访问1234端口,每次都会返回200:</p>
<p><img src="https://github.com/crystaldust/imagestorage/raw/master/consul-servicemesh/gloo-connect-retries.png" alt="gloo-connect-retries" /></p>
<p>这样,我们就借助一个第三方工具gloo-connect,实现了Consul和Envoy的集成!需要说明的是,gloo-connect也处于早期阶段,目前支持的配置还比较少,除了<code class="highlighter-rouge">retries</code>,只支持<code class="highlighter-rouge">http</code>(是否使用http模式,默认为false)和<code class="highlighter-rouge">timeout</code></p>
<h4 id="总结">总结</h4>
<p>目前来看,Consul Connect虽然还刚刚起步,但是已经让我们非常惊喜的看到了一个相对完整、简单易用的Service Mesh方案,通过第三方的集成,未来也许会有更多优秀的代理,甚至是用户自己定义的代理,不断加入到Consul的阵营中。随着Consul Connect的不断演进和HashiCorp的持续投入,我们相信,Consul会在未来的Service Mesh竞争中占有一席之地,也希望业界不断涌现Consul这样优秀的方案,给用户更多选择,让Service Mesh的世界越来越精彩。</p>
<h4 id="后记">后记</h4>
<p>不同于Istio、Conduit等“天生Service Mesh”的微服务方案,Consul本身是一个成熟的服务发现工具,其实现Service Mesh的思路非常有意思。在笔者看来,除去“控制面”“数据面”这种基于大的框架角度的划分,Service Mesh从功能上要完成三件事情:服务注册与发现,配置管理(存储、下发),服务治理。Consul在第一点已经做得非常好了,配置方面,Consul的集群内共享KV为实现配置管理奠定了坚实的基础,完全可以通过第三方工具、或者Consul自身增强的特性,基于KV实现配置的下发。服务治理方面与Consul本身关系不大,但是通过Connect,Consul具备了为服务配置代理或者集成第三方代理的能力,完全可以用已有的优秀代理来实现Service Mesh数据面,补足服务治理的能力。</p>
<p>Consul的方案,也给已经在业界流行并经过生产环境验证的“上一代”微服务框架带来很多启发。在Service Mesh概念流行之前,已有很多基于SDK的侵入式微服务框架。这些框架往往提供服务发现机制或者或者兼容开源的服务发现机制,有一些也提供配置的管理,只是需要在应用程序中引入SDK来实现服务治理,因此对于不同的语言,都要提供相应的SDK。但是相对于Consul,毕竟这些框架已经具备了微服务治理的能力,它们向Service Mesh转型的过程中,更需要的是将治理能力从SDK转移到网络层面的代理中。在这一点上,华为开源的微服务框架ServiceComb的做法非常值得参考。在ServiceComb中,已有Service Center实现服务的注册与发现,基于archaius的配置更新机制,以及提供治理能力的SDK(支持Java和Go两种语言),为了实现数据面的代理,ServiceComb团队将SDK中实现治理能力的代码剥离出来,基于此开发了网络代理<a href="https://github.com/go-chassis/mesher">Mesher</a>,Mesher的治理能力与SDK是基本对等的,并且共享同一套配置。这样,已经使用SDK的服务,不需要做任何修改,而使用其他语言开发的新应用,则可以通过Mesher获得ServiceComb的服务治理能力。最终,ServiceComb成为同时支持SDK和网络代理的混合式微服务方案,也是一个真正意义上的Service Mesh方案。</p>
</section>
<footer class="page__meta">
<p class="page__taxonomy">
<strong><i class="fa fa-fw fa-tags" aria-hidden="true"></i> 标签: </strong>
<span itemprop="keywords">
<a href="/tags/#consul" class="page__taxonomy-item" rel="tag">consul</a><span class="sep">, </span>
<a href="/tags/#microservice" class="page__taxonomy-item" rel="tag">microservice</a><span class="sep">, </span>
<a href="/tags/#servicemesh" class="page__taxonomy-item" rel="tag">servicemesh</a>
</span>
</p>
<p class="page__date"><strong><i class="fa fa-fw fa-calendar" aria-hidden="true"></i> 最新的:</strong> <time datetime="2018-07-21">2018年7月21日</time></p>
</footer>
<section class="page__share">
<h4 class="page__share-title">分享</h4>
<a href="https://twitter.com/intent/tweet?via=ServiceComb&text=Consul Service Mesh实战 /cn/docs/consul-servicemesh" 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/consul-servicemesh" 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/consul-servicemesh" 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/consul-servicemesh" 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="/docs/apache-servicecomb-incubating-day-report/" class="pagination--pager" title="Apache ServiceComb (incubating) Day Report
">向前</a>
<a href="/cn/docs/release-note-1-0-0" class="pagination--pager" title="[里程碑]Apache ServiceComb 1.0.0版本正式发布
">向后</a>
</nav>
</div>
<div class="page__comments">
<section id="static-comments">
<!-- Start static comments -->
<div class="js-comments">
</div>
<!-- End static comments -->
<!-- Start new comment form -->
<h4 class="page__comments-title">留下评论</h4>
<p class="small">您的电子邮箱地址并不会被展示。请填写标记为必须的字段。 <span class="required">*</span></p>
<form id="new_comment" class="page__comments-form js-form form" method="post" action="https://api.staticman.net/v1/entry/apache/incubator-servicecomb-website/master">
<div class="form__spinner">
<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
<span class="sr-only">正在加载...</span>
</div>
<fieldset>
<label for="comment-form-message">评论 <small class="required">*</small></label>
<textarea type="text" rows="3" id="comment-form-message" name="fields[message]" tabindex="1"></textarea>
<div class="small help-block"><a href="https://daringfireball.net/projects/markdown/">Markdown语法已支持。</a></div>
</fieldset>
<fieldset>
<label for="comment-form-name">姓名 <small class="required">*</small></label>
<input type="text" id="comment-form-name" name="fields[name]" tabindex="2" />
</fieldset>
<fieldset>
<label for="comment-form-email">电子邮箱 <small class="required">*</small></label>
<input type="email" id="comment-form-email" name="fields[email]" tabindex="3" />
</fieldset>
<fieldset>
<label for="comment-form-url">网站(可选)</label>
<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="consul-servicemesh">
<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>
<!-- Start comment form alert messaging -->
<p class="hidden js-notice">
<strong class="js-notice-text"></strong>
</p>
<!-- End comment form alert messaging -->
<fieldset>
<button type="submit" id="comment-form-submit" tabindex="5" class="btn btn--large">提交评论</button>
</fieldset>
</form>
<!-- End new comment form -->
</section>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">猜您还喜欢</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/cn/docs/playing-on-the-open-source-community-with-Apache-ServiceComb-BUPT/" rel="permalink">与Apache ServiceComb一起玩开源-北邮站 (PPT Download)
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">与Apache ServiceComb一起玩开源-北邮站 (PPT Download)
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
少于 1 分钟 阅读
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/docs/servicecomb-accept-newcapec-institute-code-donation/" rel="permalink">Apache ServiceComb Accept Code Donation From NewCapec Institute
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">Apache ServiceComb Accept Code Donation From NewCapec Institute
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
少于 1 分钟 阅读
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/cn/docs/servicecomb-accept-newcapec-institute-code-donation/" rel="permalink">Apache ServiceComb社区接受新开普软件研究院的代码捐赠
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">Apache Servicecomb社区接受新开普软件研究院的代码捐赠
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
少于 1 分钟 阅读
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/cn/docs/use-oas-validator-help-standardize-oas-spec/" rel="permalink">使用OAS Validator帮助你规范OpenAPI Spec文档
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">本文将介绍如何规范你的OpenAPI Spec文档
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
1 分钟 阅读
</p>
</article>
</div>
</div>
</div>
</div>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<div align="center" style="margin: 0 0;">
<ins class="adsbygoogle"
style="display:block; border-bottom: initial;"
data-ad-client="ca-pub-7328585512091257"
data-ad-slot="3049671934"
data-ad-format="auto"></ins>
</div>
<div class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="container">
<div class="row justify-content-md-center">
<div class="col">
<ul>
<p class="header">资源</p>
<li><a href="/cn/docs/quick-start/">入门指南</a></li>
<li><a href="/cn/users/">用户指南</a></li>
<li><a href="/cn/slides/">资料</a></li>
<li><a href="/cn/users/faq/">常见问题</a></li>
</ul>
</div>
<div class="col">
<ul>
<p class="header">ASF</p>
<li><a href="http://www.apache.org">基金会</a></li>
<li><a href="http://www.apache.org/licenses/">许可证</a></li>
<li><a href="http://www.apache.org/events/current-event">活动</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">赞助</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">鸣谢</a></li>
</ul>
</div>
<div class="col">
<ul>
<p class="header">贡献</p>
<li><a href="http://issues.apache.org/jira/browse/SCB">报告本网页问题</a></li>
<li><a href="https://github.com/apache/servicecomb-website/edit/master/_posts/cn/2018-07-21-consul-servicemesh.md">在Github上编辑此页</a></li>
<li><a href="/cn/developers/submit-codes/">代码提交指南</a></li>
<li><a href="/cn/security">安全</a></li>
</ul>
</div>
<div class="col">
<ul class="social-icons">
<p class="header">社区</p>
<li>
<a href="mailto:dev-subscribe@servicecomb.incubator.apache.org" rel="nofollow"><span class="mail">邮件列表</span></a>
</li>
<li>
<a href="https://github.com/apache?q=ServiceComb" target="_blank"><span class="github">Github</span></a>
</li>
<li>
<a href="https://twitter.com/ServiceComb" target="_blank"><span class="twitter">Twitter</span></a>
</li>
<li>
<a href="/feed.xml" target="_blank"><span class="rss">Feed</span></a>
</li>
</ul>
</div>
</div>
</div>
<div class="page__footer-bottom">
<div>&copy; 2019 Apache ServiceComb. 技术来自于 <a href="http://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div>All other marks mentioned may be trademarks or registered trademarks of their respective owners.</div>
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-101622733-1', 'auto');
ga('send', 'pageview');
</script>
<script>
(function ($) {
var $comments = $('.js-comments');
$('#new_comment').submit(function () {
var form = this;
$(form).addClass('disabled');
$('#comment-form-submit').html('<i class="fa fa-spinner fa-spin fa-fw"></i> 正在加载...');
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
contentType: 'application/x-www-form-urlencoded',
success: function (data) {
$('#comment-form-submit').html('已提交');
$('.page__comments-form .js-notice').removeClass('notice--danger');
$('.page__comments-form .js-notice').addClass('notice--success');
showAlert('感谢您的评论!被批准后它会立即在此站点展示。');
},
error: function (err) {
console.log(err);
$('#comment-form-submit').html('提交评论');
$('.page__comments-form .js-notice').removeClass('notice--success');
$('.page__comments-form .js-notice').addClass('notice--danger');
showAlert('很抱歉,您的提交存在错误。请确保所有必填字段都已填写正确,然后再试一次。');
$(form).removeClass('disabled');
}
});
return false;
});
function showAlert(message) {
$('.page__comments-form .js-notice').removeClass('hidden');
$('.page__comments-form .js-notice-text').html(message);
}
})(jQuery);
</script>
</body>
</html>