您的位置:首页 > 编程语言 > Java开发

Spring Cloud构建微服务架构(六)高可用服务注册中心

2016-11-29 10:51 597 查看
<article id="post-springcloud6" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-inner">

<header class="article-header">

<h1 class="article-title" itemprop="name">
Spring Cloud构建微服务架构(六)高可用服务注册中心
</h1>

<div class="article-meta">

<div class="article-date">
<i class="fa fa-calendar"></i>
<a href="/springcloud6/">
<time datetime="2016-09-05T14:34:31.000Z" itemprop="datePublished">2016-09-05</time>
</a>
</div>

<div class="article-category" style="text-transform: none;">
<i class="fa fa-folder"></i>
<a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
</div>

<span id="busuanzi_container_page_pv" style="display: inline;">被围观 <span id="busuanzi_value_page_pv">2353</span> 次</span>
</div>

</header>

<div class="article-entry" itemprop="articleBody" lg-uid="lg0" lg-event-uid="">

<p>近期因工作原因减缓了更新频率,同时为了把<a href="http://bbs.springcloud.com.cn" target="_blank" rel="external">Spring Cloud中文社区</a>搭建起来也费了不少时间,几乎每天都在挤牙膏般的凑时间出来做一些有意义的事。未能按原计划更新博文,在此对持续关注我博客的朋友们深表歉意。</p>
<p>之前在写Spring Cloud系列文章的时候,列过一个较粗的计划,现在由于收到不少反馈和问题,因此准备做一些调整,先将一些大家关注较为集中的点拉出来写一些内容。</p>
<p>今天这篇主要就说说Eureka Server的高可用问题。</p>
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在<a href="http://blog.didispace.com/tag/spring-cloud/">Spring Cloud</a>系列文章的开始,我们就介绍了<a href="http://blog.didispace.com/springcloud1/">服务注册与发现</a>,其中,主要演示了如何构建和启动服务注册中心Eureka Server,以及如何将服务注册到Eureka Server中,但是在之前的示例中,这个服务注册中心是单点的,显然这并不适合应用于线上生产环境,那么下面在前文的基础上,我们来看看该如何构建高可用的Eureka Server集群。</p>
<p>单点Eureka Server的样例:</p>
<ul>
<li><a href="https://github.com/dyc87112/SpringCloud-Learning/tree/master/Chapter1-1-1" target="_blank" rel="external">GitHub</a></li>
<li><a href="http://git.oschina.net/didispace/SpringCloud-Learning/tree/master/Chapter1-1-1" target="_blank" rel="external">开源中国</a></li>
</ul>
<h2 id="Eureka-Server的高可用"><a href="#Eureka-Server的高可用" class="headerlink" title="Eureka Server的高可用"></a>Eureka Server的高可用</h2><p>Eureka Server除了单点运行之外,还可以通过运行多个实例,并进行互相注册的方式来实现高可用的部署,所以我们只需要将Eureke Server配置其他可用的serviceUrl就能实现高可用部署。</p>
<p>下面以<a href="https://github.com/dyc87112/SpringCloud-Learning/tree/master/Chapter1-1-1" target="_blank" rel="external">Chapter1-1-1</a>中的eureka-server为基础,对其改造,构建双节点的服务注册中心。</p>
<ul>
<li>创建<code>application-peer1.properties</code>,作为peer1服务中心的配置,并将serviceUrl指向peer2</li>
</ul>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">spring.application.name=eureka-server</div><div class="line">server.port=1111</div><div class="line">eureka.instance.hostname=peer1</div><div class="line"></div><div class="line">eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/</div></pre></td></tr></tbody></table></figure>
<ul>
<li>创建<code>application-peer2.properties</code>,作为peer2服务中心的配置,并将serviceUrl指向peer1</li>
</ul>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">spring.application.name=eureka-server</div><div class="line">server.port=1112</div><div class="line">eureka.instance.hostname=peer2</div><div class="line"></div><div class="line">eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/</div></pre></td></tr></tbody></table></figure>
<ul>
<li>在<code>/etc/hosts</code>文件中添加对peer1和peer2的转换</li>
</ul>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">127.0.0.1 peer1</div><div class="line">127.0.0.1 peer2</div></pre></td></tr></tbody></table></figure>
<ul>
<li>通过<code>spring.profiles.active</code>属性来分别启动peer1和peer2</li>
</ul>
<figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer1</div><div class="line">java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer2</div></pre></td></tr></tbody></table></figure>
<ul>
<li>此时访问peer1的注册中心:<code>http://localhost:1111/</code>,如下图所示,我们可以看到<code>registered-replicas</code>中已经有peer2节点的eureka-server了。同样地,访问peer2的注册中心:<code>http://localhost:1112/</code>,能看到<code>registered-replicas</code>中已经有peer1节点,并且这些节点在可用分片(available-replicase)之中。我们也可以尝试关闭peer1,刷新<code>http://localhost:1112/</code>,可以看到peer1的节点变为了不可用分片(unavailable-replicas)。</li>
</ul>
<p><a href="http://blog.didispace.com/content/images/2016/09/QQ--20160906132517.png" title="" class="gallery-item" lg-event-uid="&1"><img src="/content/images/2016/09/QQ--20160906132517.png" alt=""></a></p>
<h2 id="服务注册与发现"><a href="#服务注册与发现" class="headerlink" title="服务注册与发现"></a>服务注册与发现</h2><p>在设置了多节点的服务注册中心之后,我们主需要简单需求服务配置,就能将服务注册到Eureka Server集群中。我们以<a href="https://github.com/dyc87112/SpringCloud-Learning/tree/master/Chapter1-1-1" target="_blank" rel="external">Chapter1-1-1</a>中的compute-service为基础,修改<code>application.properties</code>配置文件:</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">spring.application.name=compute-service</div><div class="line">server.port=2222</div><div class="line"></div><div class="line">eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/</div></pre></td></tr></tbody></table></figure>
<p>上面的配置主要对<code>eureka.client.serviceUrl.defaultZone</code>属性做了改动,将注册中心指向了之前我们搭建的peer1与peer2。</p>
<p>下面,我们启动该服务,通过访问<code>http://localhost:1111/</code>和<code>http://localhost:1112/</code>,可以观察到compute-service同时被注册到了peer1和peer2上。若此时断开peer1,由于compute-service同时也向peer2注册,因此在peer2上其他服务依然能访问到compute-service,从而实现了高可用的服务注册中心。</p>
<h2 id="深入理解"><a href="#深入理解" class="headerlink" title="深入理解"></a>深入理解</h2><p>虽然上面我们以双节点作为例子,但是实际上因负载等原因,我们往往可能需要在生产环境构建多于两个的Eureka Server节点。那么对于如何配置serviceUrl来让集群中的服务进行同步,需要我们更深入的理解节点间的同步机制来做出决策。</p>
<p>Eureka Server的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。什么意思呢?不妨我们通过下面的实验来看看会发生什么。</p>
<ul>
<li>场景一:假设我们有3个注册中心,我们将peer1、peer2、peer3各自都将serviceUrl指向另外两个节点。换言之,peer1、peer2、peer3是两两互相注册的。启动三个服务注册中心,并将compute-service的serviceUrl指向peer1并启动,可以获得如下图所示的集群效果。</li>
</ul>
<p><a href="http://blog.didispace.com/content/images/2016/09/s1.png" title="" class="gallery-item" lg-event-uid="&2"><img src="/content/images/2016/09/s1.png" alt=""></a></p>
<p>访问<code>http://localhost:1112/</code>,可以看到3个注册中心组成了集群,compute-service服务通过peer1同步给了与之互相注册的peer2和peer3。</p>
<p><a href="http://blog.didispace.com/content/images/2016/09/QQ--20160906171357.png" title="" class="gallery-item" lg-event-uid="&3"><img src="/content/images/2016/09/QQ--20160906171357.png" alt=""></a></p>
<ul>
<li>场景二:依然假设我们有3个注册中心,我们将peer1的serviceUrl指向peer2,peer2的指向peer3,peer3的指向peer1,此时peer1、peer2、peer3通过单向边形成环。分别启动peer1、peer2、peer3,并访问信息页面,我们可以找到下面的规律,peer1成为了peer2的分片节点,peer2成为了peer3的分片节点,peer3则成为了peer1的分片节点,再将compute-service的serviceUrl指向peer1并启动。放别访问peer1、peer2、peer3的信息页面,可以发现compute-service均被peer2和peer3同步过去了,所以单向边也能进行服务的传播与同步。此时,我们断开peer2,可以看到peer3中的compute-service消失了。重新开启peer2并断开peer3,可以看到peer2依然能同步到compute-service。所以我们可以得出结论,Eureka Server的传播与同步是具备方向性的。</li>
</ul>
<p><a href="http://blog.didispace.com/content/images/2016/09/s2.png" title="" class="gallery-item" lg-event-uid="&4"><img src="/content/images/2016/09/s2.png" alt=""></a></p>
<p>通过上面的实验,我们可以得出下面的两点结论来指导我们搭建服务注册中心的高可用集群:</p>
<ul>
<li>两两注册的方式可以实现集群中节点完全对等的效果,实现最高可用性集群,任何一台注册中心故障都不会影响服务的注册与发现</li>
<li>Eureka Server具备单方面有指向的服务传播与同步机制,在一些对服务发现有限制的情况下,可以利用这样的机制进行服务注册与发现的的单向控制</li>
</ul>
<p>更多讨论可前往:<a href="http://bbs.springcloud.com.cn" target="_blank" rel="external">Spring Cloud中文社区</a></p>
<p>本文完整示例可参考</p>
<ul>
<li><a href="https://github.com/dyc87112/SpringCloud-Learning/tree/master/Chapter1-1-6" target="_blank" rel="external">GitHub</a></li>
<li><a href="http://git.oschina.net/didispace/SpringCloud-Learning/tree/master/Chapter1-1-6" target="_blank" rel="external">开源中国</a></li>
</ul>
<p>【转载请注明出处】:<a href="http://blog.didispace.com/springcloud6/">http://blog.didispace.com/springcloud6/</a></p>

<div class="alert alert-success"><i class="fa fa-lightbulb-o"></i>
本文由 <a href="http://blog.didispace.com/">程序猿DD-翟永超</a> 创作,采用
<a href="http://creativecommons.org/licenses/by/3.0/cn" target="_blank" rel="external">CC BY 3.0 CN协议</a> 进行许可。
可自由转载、引用,但需署名作者且注明文章出处。
</div>

<!-- css -->
<style type="text/css">
.center {
text-align: center;
}
.hidden {
display: none;
}
.donate_bar a.btn_donate{
display: inline-block;
width: 82px;
height: 82px;
background: url("http://7xsl28.com1.z0.glb.clouddn.com/btn_reward.gif") no-repeat;
_background: url("http://7xsl28.com1.z0.glb.clouddn.com/btn_reward.gif") no-repeat;
-webkit-transition: background 0s;
-moz-transition: background 0s;
-o-transition: background 0s;
-ms-transition: background 0s;
transition: background 0s;
}

.donate_bar a.btn_donate:hover{ background-position: 0px -82px;}
.donate_bar .donate_txt {
display: block;
color: #9d9d9d;
font: 14px/2 "Microsoft Yahei";
}
.bold{ font-weight: bold; }
</style>
<!-- /css -->

<!-- Donate Module -->
<div id="donate_module">

<!-- btn_donate & tips -->
<div id="donate_board" class="donate_bar center">
<br>
------------------------------------------------------------------------------------------------------------------------------
<br>
<a id="btn_donate" class="btn_donate" target="_self" href="javascript:;" title="Donate 打赏"></a>
<span class="donate_txt">
如您觉得文章不错,对您有所帮助,可以通过“支付宝”或“微信支付”请我喝咖啡。
</span>

</div>
<!-- /btn_donate & tips -->

<!-- donate guide -->

<div id="donate_guide" class="donate_bar center hidden">
<br>
------------------------------------------------------------------------------------------------------------------------------
<br>

<a href="/content/images/2016/08/zhifubao.png" title="用微信扫一扫哦~" class="fancybox" rel="article0">
<a href="http://blog.didispace.com/content/images/2016/08/zhifubao.png" title="" class="gallery-item" lg-event-uid="&5"><img src="/content/images/2016/08/zhifubao.png" title="微信打赏 Colin" height="190px" width="auto"></a>
</a>

<a href="/content/images/2016/08/weixinzhifu.png" title="用支付宝扫一扫即可~" class="fancybox" rel="article0">
<a href="http://blog.didispace.com/content/images/2016/08/weixinzhifu.png" title="" class="gallery-item" lg-event-uid="&6"><img src="/content/images/2016/08/weixinzhifu.png" title="支付宝打赏 Colin" height="190px" width="auto"></a>
</a>

<span class="donate_txt">
如您觉得文章不错,对您有所帮助,可以通过“支付宝”或“微信支付”请我喝咖啡。
</span>

</div>
<!-- /donate guide -->

<!-- donate script -->
<script type="text/javascript">
document.getElementById('btn_donate').onclick = function() {
$('#donate_board').addClass('hidden');
$('#donate_guide').removeClass('hidden');
}

function donate_on_web(){
$('#donate').submit();
}

var original_window_onload = window.onload;
window.onload = function () {
if (original_window_onload) {
original_window_onload();
}
document.getElementById('donate_board_wdg').className = 'hidden';
}
</script>
<!-- /donate script -->
</div>
<!-- /Donate Module -->

</div>
<footer class="article-footer">

<div class="share-container" style="text-transform: none;">
<i class="fa fa-tag"></i>
<a class="tag-link" href="/tags/Eureka/">Eureka</a>, <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
</div>

<!--<div class="share-container">

</div>

<a data-url="http://blog.didispace.com/springcloud6/" data-id="civu5uu60003u3c211elcvjvd" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
(function ($) {
// Prevent duplicate binding
if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
__SHARE_BUTTON_BINDED__ = true;
} else {
return;
}
$('body').on('click', function() {
$('.article-share-box.on').removeClass('on');
}).on('click', '.article-share-link', function(e) {
e.stopPropagation();

var $this = $(this),
url = $this.attr('data-url'),
encodedUrl = encodeURIComponent(url),
id = 'article-share-box-' + $this.attr('data-id'),
offset = $this.offset(),
box;

if ($('#' + id).length) {
box = $('#' + id);

if (box.hasClass('on')){
box.removeClass('on');
return;
}
} else {
var html = [
'<div id="' + id + '" class="article-share-box">',
'<input class="article-share-input" value="' + url + '">',
'<div class="article-share-links">',
'<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
'<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
'<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
'<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
'</div>',
'</div>'
].join('');

box = $(html);

$('body').append(box);
}

$('.article-share-box.on').hide();

box.css({
top: offset.top + 25,
left: offset.left
}).addClass('on');

}).on('click', '.article-share-box', function (e) {
e.stopPropagation();
}).on('click', '.article-share-box-input', function () {
$(this).select();
}).on('click', '.article-share-box-link', function (e) {
e.preventDefault();
e.stopPropagation();

window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
});
})(jQuery);
</script>
-->

<a href="http://blog.didispace.com/springcloud6/#comments" class="article-comment-link ds-thread-count" data-thread-key="springcloud6">21条评论</a>

</footer>
</div>

<nav id="article-nav">

<a href="/springcloud-version/" id="article-nav-newer" class="article-nav-link-wrap">
<strong class="article-nav-caption">上一篇</strong>
<div class="article-nav-title">

聊聊Spring Cloud版本的那些事儿

</div>
</a>

<a href="/spring_cloud_community/" id="article-nav-older" class="article-nav-link-wrap">
<strong class="article-nav-caption">下一篇</strong>
<div class="article-nav-title">【Spring Cloud中文社区】正式启动</div>
</a>

</nav>

</article>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  架构 spring