﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-一杯清茶-文章分类-微服务实战</title><link>http://www.blogjava.net/huyi0616/category/55003.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 17 Mar 2016 10:33:36 GMT</lastBuildDate><pubDate>Thu, 17 Mar 2016 10:33:36 GMT</pubDate><ttl>60</ttl><item><title>微服务实战（二）：使用API Gateway</title><link>http://www.blogjava.net/huyi0616/articles/429705.html</link><dc:creator>一杯清茶</dc:creator><author>一杯清茶</author><pubDate>Thu, 17 Mar 2016 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/huyi0616/articles/429705.html</guid><wfw:comment>http://www.blogjava.net/huyi0616/comments/429705.html</wfw:comment><comments>http://www.blogjava.net/huyi0616/articles/429705.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi0616/comments/commentRss/429705.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi0616/services/trackbacks/429705.html</trackback:ping><description><![CDATA[<h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">【编者的话】本系列的第一篇介绍了微服务架构模式。它讨论了采用微服务的优点和缺点，除了一些复杂的微服务，这种模式还是复杂应用的理想选择。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">当你决定将应用作为一组微服务时，需要决定应用客户端如何与微服务交互。在单体式程序中，通常只有一组冗余的或者负载均衡的服务提供点。在微服务架构中，每一个微服务暴露一组细粒度的服务提供点。在本篇文章中，我们来看它如何影响客户端到服务端通信，同时提出一种API Gateway的方法。</span></div></h1><h3 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #333333; margin: 16px 0px; font-size: 1.5em; background-color: #ffffff;">介绍</h3><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">假定你正在为在线购物应用开发一个原生手机客户端。你需要实现一个产品最终页来展示商品信息。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">例如，下面的图展示了你在亚马逊Android客户端上滑动产品最终页时看到的信息。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><div class="aw-upload-img-list active" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150701/815d48350a8d3a4b11df4a62e6df077d.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150701/815d48350a8d3a4b11df4a62e6df077d.png" class="img-polaroid" title="01.png" alt="01.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">虽然这是一个智能手机应用，这个产品最终页展示了非常多的信息。例如，不仅这里有产品基本信息（名字、描述和价格），还有以下内容：</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><ul style="box-sizing: border-box; margin: 0px; padding: 0px 0px 0px 32px; line-height: 30px; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; background-color: #ffffff;"><li style="box-sizing: border-box; line-height: 25px;">购物车中的物品数</li><li style="box-sizing: border-box; line-height: 25px;">下单历史</li><li style="box-sizing: border-box; line-height: 25px;">用户评论</li><li style="box-sizing: border-box; line-height: 25px;">低库存警告</li><li style="box-sizing: border-box; line-height: 25px;">快递选项</li><li style="box-sizing: border-box; line-height: 25px;">各式各样的推荐，包括经常跟这个物品一起被购买的产品、购买该物品的其他顾客购买的产品以及购买该产品的顾客还浏览了哪些产品。</li><li style="box-sizing: border-box; line-height: 25px;">可选的购物选项</li></ul><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">当采用一个单体式应用架构，一个移动客户端将会通过一个REST请求（GET api.company.com/productdetails/productId）来获取这些数据。一个负载均衡将请求分发到多个应用实例之一。应用将查询各种数据库并返回请求给客户端。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">相对的，若是采用微服务架构，最终页上的数据会分布在不同的微服务上。下面列举了可能与产品最终页数据有关的一些微服务：</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><ul style="box-sizing: border-box; margin: 0px; padding: 0px 0px 0px 32px; line-height: 30px; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; background-color: #ffffff;"><li style="box-sizing: border-box; line-height: 25px;">购物车服务 -- 购物车中的物品数</li><li style="box-sizing: border-box; line-height: 25px;">下单服务 -- 下单历史</li><li style="box-sizing: border-box; line-height: 25px;">分类服务 -- 基本产品信息，如名字、图片和价格</li><li style="box-sizing: border-box; line-height: 25px;">评论服务 -- 用户评论</li><li style="box-sizing: border-box; line-height: 25px;">库存服务 -- 低库存警告</li><li style="box-sizing: border-box; line-height: 25px;">快递服务 -- 快递选项、截止时间、来自不同快递API的成本计算</li><li style="box-sizing: border-box; line-height: 25px;">推荐服务 -- 推荐产品</li></ul><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><div class="aw-upload-img-list active" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150701/dd914aa3f02ef4e8e820ce0238d2dbab.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150701/dd914aa3f02ef4e8e820ce0238d2dbab.png" class="img-polaroid" title="02.png" alt="02.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">我们需要决定移动客户端如何访问这些服务。请看下面这几种方式</span></div></h1><h3 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #333333; margin: 16px 0px; font-size: 1.5em; background-color: #ffffff;">客户端到微服务直接通信</h3><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">理论上说，一个客户端可以直接给多个微服务中的任何一个发起请求。每一个微服务都会有一个对外服务端(</span><a href="https://servicename.api.company.nam/" rel="nofollow" target="_blank" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">https://serviceName.api.company.nam</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">e)。这个URL可能会映射到微服务的负载均衡上，它再转发请求到具体节点上。为了搜索产品细节，移动端需要向上述微服务逐个发请求。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">不幸的是，这个方案有很多困难和限制。其中一个问题是客户端的需求量与每个微服务暴露的细粒度API数量的不匹配。如图中，客户端需要7次单独请求。在更复杂的场景中，可能会需要更多次请求。例如，亚马逊的产品最终页要请求数百个微服务。虽然一个客户端可以通过LAN发起很多个请求，但是在公网上这样会很没有效率，这个问题在移动互联网上尤为突出。这个方案同时会导致客户端代码非常复杂。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">另一个存在的问题是客户端直接请求微服务的协议可能并不是web友好型。一个服务可能是用Thrift的RPC协议，而另一个服务可能是用AMQP消息协议。它们都不是浏览或防火墙友好的，并且最好是内部使用。应用应该在防火墙外采用类似HTTP或者WEBSocket协议。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">这个方案的另一个缺点是它很难重构微服务。随着时间的推移，我们可能需要改变系统微服务目前的切分方案。例如，我们可能需要将两个服务合并或者将一个服务拆分为多个。但是，如果客户端直接与微服务交互，那么这种重构就很难实施。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">由于上述三种问题的原因，客户端直接与服务器端通信的方式很少在实际中使用。</span></div></h1><h3 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #333333; margin: 16px 0px; font-size: 1.5em; background-color: #ffffff;">采用一个API Gateway</h3><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">通常来说，一个更好的解决办法是采用API Gateway的方式。API Gateway是一个服务器，也可以说是进入系统的唯一节点。这跟面向对象设计模式中的Facade模式很像。API Gateway封装内部系统的架构，并且提供API给各个客户端。它还可能有其他功能，如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理等。下图展示了一个适应当前架构的API Gateway。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><div class="aw-upload-img-list active" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150701/e3af5a60b71f3d3fef53c1a5ccbfad78.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150701/e3af5a60b71f3d3fef53c1a5ccbfad78.png" class="img-polaroid" title="03.png" alt="03.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">API Gateway负责请求转发、合成和协议转换。所有来自客户端的请求都要先经过API Gateway，然后路由这些请求到对应的微服务。API Gateway将经常通过调用多个微服务来处理一个请求以及聚合多个服务的结果。它可以在web协议与内部使用的非Web友好型协议间进行转换，如HTTP协议、WebSocket协议。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">API Gateway可以提供给客户端一个定制化的API。它暴露一个粗粒度API给移动客户端。以产品最终页这个使用场景为例。API Gateway提供一个服务提供点（/productdetails?productid=xxx）使得移动客户端可以在一个请求中检索到产品最终页的全部数据。API Gateway通过调用多个服务来处理这一个请求并返回结果，涉及产品信息、推荐、评论等。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">一个很好的API Gateway例子是</span><a href="http://techblog.netflix.com/2013/02/rxjava-netflix-api.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Netfix API Gateway</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">。Netflix流服务提供数百个不同的微服务，包括电视、机顶盒、智能手机、游戏系统、平板电脑等。起初，Netflix视图提供一个</span><a href="http://www.programmableweb.com/news/why-rest-keeps-me-night/2012/05/15" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">适用全场景</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">的API。但是，他们发现这种形式不好用，因为涉及到各式各样的设备以及它们独特的需求。现在，他们采用一个API Gateway来提供容错性高的API，针对不同类型设备有相应代码。事实上，一个适配器处理一个请求平均要调用6到8个后端服务。Netflix API Gateway每天处理数十亿的请求。</span></div></h1><h3 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #333333; margin: 16px 0px; font-size: 1.5em; background-color: #ffffff;">API Gateway的优点和缺点</h3><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">如你所料，采用API Gateway也是优缺点并存的。API Gateway的一个最大好处是封装应用内部结构。相比起来调用指定的服务，客户端直接跟gatway交互更简单点。API Gateway提供给每一个客户端一个特定API，这样减少了客户端与服务器端的通信次数，也简化了客户端代码。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">API Gateway也有一些缺点。它是一个高可用的组件，必须要开发、部署和管理。还有一个问题，它可能成为开发的一个瓶颈。开发者必须更新API Gateway来提供新服务提供点来支持新暴露的微服务。更新API Gateway时必须越轻量级越好。否则，开发者将因为更新Gateway而排队列。但是，除了这些缺点，对于大部分的应用，采用API Gateway的方式都是有效的。</span></div></h1><h3 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #333333; margin: 16px 0px; font-size: 1.5em; background-color: #ffffff;">实现一个API Gateway</h3><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">既然我们已经知道了采用API Gateway的动机和优缺点，下面来看在设计它时需要考虑哪些事情。</span></div></h1><h4 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #666666; margin: 16px 0px; font-size: 1.25em; background-color: #ffffff;">性能和可扩展性</h4><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">只有少数公司需要处理像Netflix那样的规模，每天需要处理数十亿的请求。但是，对于大多数应用，API Gateway的性能和可扩展性也是非常重要的。因此，创建一个支持同步、非阻塞I/O的API Gateway是有意义的。已经有不同的技术可以用来实现一个可扩展的API Gateway。在JVM上，采用基于NIO技术的框架，如Netty，Vertx，Spring Reactor或者JBoss Undertow。Node.js是一个非JVM的流行平台，它是一个在Chrome的JavaScript引擎基础上建立的平台。一个可选的方案是</span><a href="http://nginx.com/solutions/get-apis/" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">NGINX Plus</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">。NGINX Plus提供一个成熟的、可扩展的、高性能web服务器和反向代理，它们均容易部署、配置和二次开发。NGINX Plus可以管理授权、权限控制、负载均衡、缓存并提供应用健康检查和监控。</span></div></h1><h4 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #666666; margin: 16px 0px; font-size: 1.25em; background-color: #ffffff;">采用反应性编程模型</h4><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">对于有些请求，API Gateway可以通过直接路由请求到对应的后端服务上的方式来处理。对于另外一些请求，它需要调用多个后端服务并合并结果来处理。对于一些请求，例如产品最终页面请求，发给后端服务的请求是相互独立的。为了最小化响应时间，API Gateway应该并发的处理相互独立的请求。但是，有时候请求之间是有依赖的。API Gateway可能需要先通过授权服务来验证请求，然后在路由到后端服务。类似的，为了获得客户的产品愿望清单，需要先获取该用户的资料，然后返回清单上产品的信息。这样的一个API 组件是</span><a href="http://techblog.netflix.com/2013/02/rxjava-netflix-api.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Netflix Video Grid</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">利用传统的同步回调方法来实现API合并的代码会使得你进入回调函数的噩梦中。这种代码将非常难度且难以维护。一个优雅的解决方案是采用反应性编程模式来实现。类似的反应抽象实现有Scala的</span><a href="http://docs.scala-lang.org/overviews/core/futures.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Future</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">，Java8的</span><a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">CompletableFuture</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">和JavaScript的</span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Promise</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">。基于微软.Net平台的有</span><a href="http://reactivex.io/" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Reactive Extensions(Rx)</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">。Netflix为JVM环境创建了RxJava来使用他们的API Gateway。同样地，JavaScript平台有RxJS，可以在浏览器和Node.js平台上运行。采用反应编程方法可以帮助快速实现一个高效的API Gateway代码。</span></div></h1><h4 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #666666; margin: 16px 0px; font-size: 1.25em; background-color: #ffffff;">服务调用</h4><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">一个基于微服务的应用是一个分布式系统，并且必须采用线程间通信的机制。有两种线程间通信的方法。一种是采用异步机制，基于消息的方法。这类的实现方法有JMS和AMQP。另外的，例如Zeromq属于服务间直接通信。还有一种线程间通信采用同步机制，例如Thrift和HTTP。事实上一个系统会同时采用同步和异步两种机制。由于它的实现方式有很多种，因此API Gateway就需要支持多种通信方式。</span></div></h1><h4 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #666666; margin: 16px 0px; font-size: 1.25em; background-color: #ffffff;">服务发现</h4><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">API Gateway需要知道每一个微服务的IP和端口。在传统应用中，你可能会硬编码这些地址，但是在现在云基础的微服务应用中，这将是个简单的问题。基础服务通常会采用静态地址，可以采用操作系统环境变量来指定。但是，探测应用服务的地址就没那么容易了。应用服务通常动态分配地址和端口。同样的，由于扩展或者升级，服务的实例也会动态的改变。因此，API Gateway需要采用系统的服务发现机制，要么采用</span><a href="http://microservices.io/patterns/server-side-discovery.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">服务端发现</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">，要么是</span><a href="http://microservices.io/patterns/client-side-discovery.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">客户端发现</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">。后续的一篇文章将会更详细的介绍这部分。如果采用客户端发现服务，API Gateway必须要去查询</span><a href="http://microservices.io/patterns/service-registry.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">服务注册处</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">，也就是微服务实例地址的数据库。</span></div></h1><h4 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #666666; margin: 16px 0px; font-size: 1.25em; background-color: #ffffff;">处理部分失败</h4><h1><div style="display: inline-block;"><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">在实现API Gateway过程中，另外一个需要考虑的问题就是部分失败。这个问题发生在分布式系统中当一个服务调用另外一个服务超时或者不可用的情况。API Gateway不应该被阻断并处于无限期等待下游服务的状态。但是，如何处理这种失败依赖于特定的场景和具体服务。例如，如果是在产品详情页的推荐服务模块无响应，那么API Gateway应该返回剩下的其他信息给用户，因为这些信息也是有用的。推荐部分可以返回空，也可以返回固定的顶部10个给用户。但是，如果是产品信息服务无响应，那么API Gateway就应该给客户端返回一个错误。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">在缓存有效的时候，API Gateway应该能够返回缓存。例如，由于产品价格变化并不频繁，API Gateway在价格服务不可用时应该返回缓存中的数值。这类数据可以由API Gateway自身来缓存，也可以由Redis或Memcached这类外部缓存实现。通过返回缓存数据或者默认数据，API Gateway来确保系统错误不影响到用户体验。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><a href="https://github.com/Netflix/Hystrix" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Netflix Hystrix</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">对于实现远程服务调用代码来说是一个非常好用的库。Hystrix记录那些超过预设定的极限值的调用。它实现了</span><em style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">circuit break</em><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">模式，使得可以将客户端从无响应服务的无尽等待中停止。如果一个服务的错误率超过预设值，Hystrix将中断服务，并且在一段时间内所有请求立刻失效。Hystrix可以为请求失败定义一个fallback操作，例如读取缓存或者返回默认值。如果你在用JVM，就应该考虑使用Hystrix。如果你采用的非JVM环境，那么应该考虑采用类似功能的库。</span></div></h1><h3 style="box-sizing: border-box; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.7; color: #333333; margin: 16px 0px; font-size: 1.5em; background-color: #ffffff;">总结</h3><h1><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">对于大多数微服务基础的应用，实现一个API Gateway都是有意义的，它就像是进入系统的一个服务提供点。API Gateway负责请求转发、请求合成和协议转换。它提供给应用客户端一个自定义的API。API Gateway可以通过返回缓存或者默认值的方式来掩盖后端服务的错误。在本系列的下一篇文章中，我们将讨论服务间的通信问题。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 25.2000007629395px; background-color: #ffffff;">原文链接：<a href="http://nginx.com/blog/building-microservices-using-an-api-gateway/" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;">Building Microservices: Using an API Gateway</a>&nbsp;(翻译：陈杰；审校：杨峰)</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">===============================================</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 25.2000007629395px; background-color: #ffffff;">译者介绍</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 25.2000007629395px; background-color: #ffffff;">陈杰</span><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 25.2000007629395px; background-color: #ffffff;">，北京理工大学计算机学院在读博士，研究方向是自然语言处理在企业网络信誉评价方面的应用，平时也乐于去实现一些突发的想法。在疲于配置系统环境时发现了Docker，跟大家一起学习、使用和研究Docker。</span></h1><img src ="http://www.blogjava.net/huyi0616/aggbug/429705.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi0616/" target="_blank">一杯清茶</a> 2016-03-17 17:55 <a href="http://www.blogjava.net/huyi0616/articles/429705.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微服务实战（一）：微服务架构的优势与不足</title><link>http://www.blogjava.net/huyi0616/articles/429704.html</link><dc:creator>一杯清茶</dc:creator><author>一杯清茶</author><pubDate>Thu, 17 Mar 2016 09:54:00 GMT</pubDate><guid>http://www.blogjava.net/huyi0616/articles/429704.html</guid><wfw:comment>http://www.blogjava.net/huyi0616/comments/429704.html</wfw:comment><comments>http://www.blogjava.net/huyi0616/articles/429704.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi0616/comments/commentRss/429704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi0616/services/trackbacks/429704.html</trackback:ping><description><![CDATA[<span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">【编者的话】本文来自Nginx官方博客，是微服务系列文章的第一篇，主要探讨了传统的单体式应用的不足，以及微服务架构的优势与挑战。正如作者所说，微服务架构更适合用于构建复杂的应用，尽管它也有自己的不足。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">这篇文章作者是Chris Richardson，他是早期基于Java的Amazonite EC2 PaaS平台CloudFoundry.com的创始人。现在他为企业提供如何开发和部署应用的咨询服务。他也经常在</span><a href="http://microservices.io/" rel="nofollow" target="_blank" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">http://microservices.io</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">上发表有关微服务的文章。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">微服务正在博客、社交媒体讨论组和会议演讲中获得越来越多的关注，在Gartner的2014 Hype Cycle上它的排名非常靠前。同时，软件社区中也有不少持怀疑论者，认为微服务不是什么新东西。Naysayers认为这就是SOA架构的重新包装。然而，尽管存在着不同的争论，微服务架构模式却正在为敏捷部署以及复杂企业应用实施提供巨大的帮助。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="box-sizing: border-box; font-weight: 700; color: #333333; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">这篇博客是关于如何设计、开发和部署微服务的七篇系列文章中的第一篇。</span><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">读者将会从中学到方法，并且和</span><a href="http://microservices.io/patterns/monolithic.html" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">单体式架构模式</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">（译者注：本文中会将 Monolithic翻译为单体）进行对比。这一系列文章将描述微服务架构中不同元素。你将了解到微服务架构模式的优缺点，以便决定是否更好的将微服务架构应用到自己的项目中，以及如何应用这一模式。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">首先我们看看为什么要考虑使用微服务。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><h4>开发单体式应用</h4><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">假设你正准备开发一款与Uber和Hailo竞争的出租车调度软件，经过初步会议和需求分析，你可能会手动或者使用基于Rails、Spring Boot、Play或者Maven的生成器开始这个新项目，它的六边形架构是模块化的 ，架构图如下：</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><div active"="" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150524/89d9bfed11ff35943269b24b23b866b1.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150524/89d9bfed11ff35943269b24b23b866b1.png" title="1.png" alt="1.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">应用核心是业务逻辑，由定义服务、域对象和事件的模块完成。围绕着核心的是与外界打交道的适配器。适配器包括数据库访问组件、生产和处理消息的消息组件，以及提供API或者UI访问支持的web模块等。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">尽管也是模块化逻辑，但是最终它还是会打包并部署为单体式应用。具体的格式依赖于应用语言和框架。例如，许多Java应用会被打包为WAR格式，部署在Tomcat或者Jetty上，而另外一些Java应用会被打包成自包含的JAR格式，同样，Rails和Node.js会被打包成层级目录。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">这种应用开发风格很常见，因为IDE和其它工具都擅长开发一个简单应用，这类应用也很易于调试，只需要简单运行此应用，用Selenium链接UI就可以完成端到端测试。单体式应用也易于部署，只需要把打包应用拷贝到服务器端，通过在负载均衡器后端运行多个拷贝就可以轻松实现应用扩展。在早期这类应用运行的很好。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><h4>单体式应用的不足</h4><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">不幸的是，这种简单方法却有很大的局限性。一个简单的应用会随着时间推移逐渐变大。在每次的</span><a href="http://techblog.youdao.com/?p=373" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">sprint</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">中，开发团队都会面对新&#8220;故事&#8221;，然后开发许多新代码。几年后，这个小而简单的应用会变成了一个巨大的怪物。这儿有一个例子，我最近和一个开发者讨论，他正在写一个工具，用来分析他们一个拥有数百万行代码的应用中JAR文件之间的依赖关系。我很确信这个代码正是很多开发者经过多年努力开发出来的一个怪物。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">一旦你的应用变成一个又大又复杂的怪物，那开发团队肯定很痛苦。敏捷开发和部署举步维艰，其中最主要问题就是这个应用太复杂，以至于任何单个开发者都不可能搞懂它。因此，修正bug和正确的添加新功能变的非常困难，并且很耗时。另外，团队士气也会走下坡路。如果代码难于理解，就不可能被正确的修改。最终会走向巨大的、不可理解的泥潭。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">单体式应用也会降低开发速度。应用越大，启动时间会越长。比如，最近的一个调查表明，有时候应用的启动时间居然超过了12分钟。我还听说某些应用需要40分钟启动时间。如果开发者需要经常重启应用，那么大部分时间就要在等待中渡过，生产效率受到极大影响。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">另外，复杂而巨大的单体式应用也不利于持续性开发。今天，SaaS应用常态就是每天会改变很多次，而这对于单体式应用模式非常困难。另外，这种变化带来的影响并没有很好的被理解，所以不得不做很多手工测试。那么接下来，持续部署也会很艰难。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">单体式应用在不同模块发生资源冲突时，扩展将会非常困难。比如，一个模块完成一个CPU敏感逻辑，应该部署在AWS EC2 Compute Optimized instances，而另外一个内存数据库模块更合适于EC2 Memory-optimized instances。然而，由于这些模块部署在一起，因此不得不在硬件选择上做一个妥协。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">单体式应用另外一个问题是可靠性。因为所有模块都运行在一个进程中，任何一个模块中的一个bug，比如内存泄露，将会有可能弄垮整个进程。除此之外，因为所有应用实例都是唯一的，这个bug将会影响到整个应用的可靠性。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">最后，单体式应用使得采用新架构和语言非常困难。比如，设想你有两百万行采用XYZ框架写的代码。如果想改成ABC框架，无论是时间还是成本都是非常昂贵的，即使ABC框架更好。因此，这是一个无法逾越的鸿沟。你不得不在最初选择面前低头。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">总结一下：一开始你有一个很成功的关键业务应用，后来就变成了一个巨大的，无法理解的怪物。因为采用过时的，效率低的技术，使得雇佣有潜力的开发者很困难。应用无法扩展，可靠性很低，最终，敏捷性开发和部署变的无法完成。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">那么如何应对呢？</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><h4>微处理架构&#8212;&#8212;处理复杂事物</h4><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">许多公司，比如Amazon、eBay和NetFlix，通过采用微处理结构模式解决了上述问题。其思路不是开发一个巨大的单体式的应用，而是将应用分解为小的、互相连接的微服务。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">一个微服务一般完成某个特定的功能，比如下单管理、客户管理等等。每一个微服务都是微型六角形应用，都有自己的业务逻辑和适配器。一些微服务还会发布API给其它微服务和应用客户端使用。其它微服务完成一个Web UI，运行时，每一个实例可能是一个云VM或者是Docker容器。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">比如，一个前面描述系统可能的分解如下：</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><div active"="" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150524/858f9ae6c861c8c93cd5379be54f9fc1.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150524/858f9ae6c861c8c93cd5379be54f9fc1.png" title="2.png" alt="2.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">每一个应用功能区都使用微服务完成，另外，Web应用会被拆分成一系列简单的Web应用（比如一个对乘客，一个对出租车驾驶员）。这样的拆分对于不同用户、设备和特殊应用场景部署都更容易。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">每一个后台服务开放一个REST API，许多服务本身也采用了其它服务提供的API。比如，驾驶员管理使用了告知驾驶员一个潜在需求的通知服务。UI服务激活其它服务来更新Web页面。所有服务都是采用异步的，基于消息的通讯。微服务内部机制将会在后续系列中讨论。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">一些REST API也对乘客和驾驶员采用的移动应用开放。这些应用并不直接访问后台服务，而是通过API Gateway来传递中间消息。API Gateway负责负载均衡、缓存、访问控制、API 计费监控等等任务，可以通过NGINX方便实现，后续文章将会介绍到API Gateway。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><div active"="" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150524/0714fcab4f6d5951014e5613657c8289.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150524/0714fcab4f6d5951014e5613657c8289.png" title="3.png" alt="3.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">微服务架构模式在上图中对应于代表可扩展Scale Cube的Y轴，这是一个在《The Art of Scalability》书中描述过的三维扩展模型。另外两个可扩展轴，X轴由负载均衡器后端运行的多个应用副本组成，Z轴是将需求路由到相关服务。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">应用基本可以用以上三个维度来表示，Y轴代表将应用分解为微服务。运行时，X轴代表运行多个隐藏在负载均衡器之后的实例，提供吞吐能力。一些应用可能还是用Z轴将服务分区。下面的图演示行程管理服务如何部署在运行于AWS EC2上的Docker上。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><div active"="" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150524/ca6ddafaa8b506ae4d45dde53ee5efb6.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150524/ca6ddafaa8b506ae4d45dde53ee5efb6.png" title="4.png" alt="4.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">运行时，行程管理服务由多个服务实例构成。每一个服务实例都是一个Docker容器。为了保证高可用，这些容器一般都运行在多个云VM上。服务实例前是一层诸如NGINX的负载均衡器，他们负责在各个实例间分发请求。负载均衡器也同时处理其它请求，例如缓存、权限控制、API统计和监控。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">这种微服务架构模式深刻影响了应用和数据库之间的关系，</span><span style="box-sizing: border-box; font-weight: 700; color: #333333; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">不像传统多个服务共享一个数据库，微服务架构每个服务都有自己的数据库</span><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">。另外，这种思路也影响到了企业级数据模式。同时，这种模式意味着多份数据，但是，如果你想获得微服务带来的好处，每个服务独有一个数据库是必须的，因为这种架构需要这种松耦合。下面的图演示示例应用数据库架构。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><div active"="" style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;"><a href="http://dockerone.com/uploads/article/20150524/384781ccf56d3057df5acd198e8d1f3d.png" target="_blank" data-fancybox-group="thumb" rel="lightbox" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; background: 0px 0px;"><img src="http://dockerone.com/uploads/article/20150524/384781ccf56d3057df5acd198e8d1f3d.png" title="5.png" alt="5.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 625px; margin-bottom: 15px;" /></a></div><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">每种服务都有自己的数据库，另外，每种服务可以用更适合自己的数据库类型，也被称作多语言一致性架构。比如，驾驶员管理（发现哪个驾驶员更靠近乘客），必须使用支持地理信息查询的数据库。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">表面上看来，微服务架构模式有点像SOA，他们都由多个服务构成。但是，可以从另外一个角度看此问题，微服务架构模式是一个不包含Web服务（WS-）和ESB服务的SOA。微服务应用乐于采用简单轻量级协议，比如REST，而不是WS-，在微服务内部避免使用ESB以及ESB类似功能。微服务架构模式也拒绝使用canonical schema等SOA概念。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><h4>微服务架构的好处</h4><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">微服务架构模式有很多好处。首先，通过分解巨大单体式应用为多个服务方法解决了复杂性问题。在功能不变的情况下，应用被分解为多个可管理的分支或服务。每个服务都有一个用RPC-或者消息驱动API定义清楚的边界。微服务架构模式给采用单体式编码方式很难实现的功能提供了模块化的解决方案，由此，单个服务很容易开发、理解和维护。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">第二，这种架构使得每个服务都可以有专门开发团队来开发。开发者可以自由选择开发技术，提供API服务。当然，许多公司试图避免混乱，只提供某些技术选择。然后，这种自由意味着开发者不需要被迫使用某项目开始时采用的过时技术，他们可以选择现在的技术。甚至于，因为服务都是相对简单，即使用现在技术重写以前代码也不是很困难的事情。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">第三，微服务架构模式是每个微服务独立的部署。开发者不再需要协调其它服务部署对本服务的影响。这种改变可以加快部署速度。UI团队可以采用AB测试，快速的部署变化。微服务架构模式使得持续化部署成为可能。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">最后，微服务架构模式使得每个服务独立扩展。你可以根据每个服务的规模来部署满足需求的规模。甚至于，你可以使用更适合于服务资源需求的硬件。比如，你可以在EC2 Compute Optimized instances上部署CPU敏感的服务，而在EC2 memory-optimized instances上部署内存数据库。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><h4>微服务架构的不足</h4><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">Fred Brooks在30年前写道，&#8220;there are no silver bullets&#8221;，像任何其它科技一样，微服务架构也有不足。其中一个跟他的名字类似，『微服务』强调了服务大小，实际上，有一些开发者鼓吹建立稍微大一些的，10-100 LOC服务组。尽管小服务更乐于被采用，但是不要忘了这只是终端的选择而不是最终的目的。微服务的目的是有效的拆分应用，实现敏捷开发和部署。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">另外一个主要的不足是，微服务应用是分布式系统，由此会带来固有的复杂性。开发者需要在RPC或者消息传递之间选择并完成进程间通讯机制。更甚于，他们必须写代码来处理消息传递中速度过慢或者不可用等局部失效问题。当然这并不是什么难事，但相对于单体式应用中通过语言层级的方法或者进程调用，微服务下这种技术显得更复杂一些。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">另外一个关于微服务的挑战来自于分区的数据库架构。商业交易中同时给多个业务分主体更新消息很普遍。这种交易对于单体式应用来说很容易，因为只有一个数据库。在微服务架构应用中，需要更新不同服务所使用的不同的数据库。使用分布式交易并不一定是好的选择，不仅仅是因为CAP理论，还因为今天高扩展性的NoSQL数据库和消息传递中间件并不支持这一需求。最终你不得不使用一个最终一致性的方法，从而对开发者提出了更高的要求和挑战。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">测试一个基于微服务架构的应用也是很复杂的任务。比如，采用流行的Spring Boot架构，对一个单体式web应用，测试它的REST API，是很容易的事情。反过来，同样的服务测试需要启动和它有关的所有服务（至少需要这些服务的stubs）。再重申一次，不能低估了采用微服务架构带来的复杂性。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">另外一个挑战在于，微服务架构模式应用的改变将会波及多个服务。比如，假设你在完成一个案例，需要修改服务A、B、C，而A依赖B，B依赖C。在单体式应用中，你只需要改变相关模块，整合变化，部署就好了。对比之下，微服务架构模式就需要考虑相关改变对不同服务的影响。比如，你需要更新服务C，然后是B，最后才是A，幸运的是，许多改变一般只影响一个服务，而需要协调多服务的改变很少。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">部署一个微服务应用也很复杂，一个分布式应用只需要简单在复杂均衡器后面部署各自的服务器就好了。每个应用实例是需要配置诸如数据库和消息中间件等基础服务。相对比，一个微服务应用一般由大批服务构成。例如，根据Adrian Cockcroft，</span><a href="https://sudo.hailoapp.com/services/2015/03/09/journey-into-a-microservice-world-part-3/" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Hailo有160个不同服务构成</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">，NetFlix有大约600个服务。每个服务都有多个实例。这就造成许多需要配置、部署、扩展和监控的部分，除此之外，你还需要完成一个服务发现机制（后续文章中发表），以用来发现与它通讯服务的地址（包括服务器地址和端口）。传统的解决问题办法不能用于解决这么复杂的问题。接续而来，成功部署一个微服务应用需要开发者有足够的控制部署方法，并高度自动化。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">一种自动化方法是使用PaaS服务，例如</span><a href="http://www.cloudfoundry.org/" style="box-sizing: border-box; color: #155faa; text-decoration: none; cursor: pointer; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background: 0px 0px #ffffff;">Cloud Foundry</a><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">。PaaS给开发者提供一个部署和管理微服务的简单方法，它把所有这些问题都打包内置解决了。同时，配置PaaS的系统和网络专家可以采用最佳实践和策略来简化这些问题。另外一个自动部署微服务应用的方法是开发对于你来说最基础的PaaS系统。一个典型的开始点是使用一个集群化方案，比如配合Docker使用Mesos或者Kubernetes。后面的系列我们会看看如何基于软件部署方法例如NGINX，可以方便的在微服务层面提供缓存、权限控制、API统计和监控。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><h4>总结</h4><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">构建复杂的应用真的是非常困难。单体式的架构更适合轻量级的简单应用。如果你用它来开发复杂应用，那真的会很糟糕。微服务架构模式可以用来构建复杂应用，当然，这种架构模型也有自己的缺点和挑战。</span><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><br style="box-sizing: border-box; color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;" /><span style="color: #666666; font-family: 'Helvetica Neue', STHeiti, 'Microsoft YaHei', Helvetica, Arial, sans-serif; line-height: 25.2000007629395px; background-color: #ffffff;">在后续的博客中，我会深入探索微服务架构模式，并讨论诸如服务发现、服务部署选择和如何分解一个分布式应用为多个服务的策略。</span><img src ="http://www.blogjava.net/huyi0616/aggbug/429704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi0616/" target="_blank">一杯清茶</a> 2016-03-17 17:54 <a href="http://www.blogjava.net/huyi0616/articles/429704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>