﻿<?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-xiaomage234-随笔分类-分布式</title><link>http://www.blogjava.net/xiaomage234/category/53535.html</link><description>生命本就是一次凄美的漂流，记忆中放不下的，永远是孩提时代的那一份浪漫与纯真！</description><language>zh-cn</language><lastBuildDate>Thu, 26 Nov 2020 09:51:31 GMT</lastBuildDate><pubDate>Thu, 26 Nov 2020 09:51:31 GMT</pubDate><ttl>60</ttl><item><title>如何系统性地学习分布式系统？[转]</title><link>http://www.blogjava.net/xiaomage234/archive/2020/11/26/435735.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 26 Nov 2020 08:20:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2020/11/26/435735.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/435735.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2020/11/26/435735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/435735.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/435735.html</trackback:ping><description><![CDATA[<h2>from：https://www.infoq.cn/article/orvjbfycnrito5qiyfhf<br />前言</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">学习一个知识之前，我觉得比较好的方式是先理解它的来龙去脉：即这个知识产生的过程，它解决了什么问题，它是怎么样解决的，还有它引入了哪些新的问题（没有银弹），这样我们才能比较好的抓到它的脉络和关键点，不会一开始就迷失在细节中。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">所以，在学习分布式系统之前，我们需要解决的第一个问题是：分布式系统解决了什么问题？</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>分布式系统解决了什么问题？</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">第一个是单机性能瓶颈导致的成本问题，由于摩尔定律失效，廉价 PC 机性能的瓶颈无法继续突破，小型机和大型机能提高更高的单机性能，但是成本太大高，一般的公司很难承受；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">第二个是用户量和数据量爆炸性的增大导致的成本问题，进入互联网时代，用户量爆炸性的增大，用户产生的数据量也在爆炸性的增大，但是单个用户或者单条数据的价值其实比软件时代（比如银行用户）的价值是只低不高，所以必须寻找更经济的方案；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">第三个是业务高可用的要求，对于互联网的产品来说，都要求 7 * 24 小时提供服务，无法容忍停止服务等故障，而要提供高可用的服务，唯一的方式就是增加冗余来完成，这样就算单机系统可以支撑的服务，因为高可用的要求，也会变成一个分布式系统。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">基于上面的三个原因可以看出，在互联网时代，单机系统是无法解决成本和高可用问题的，但是这两个问题对几乎对所有的公司来说都是非常关键的问题，所以，从单机系统到分布式系统是无法避免的技术大潮流。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>分布式系统是怎么来解决问题的？</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">那么，分布式系统是怎么来解决单机系统面临的成本和高可用问题呢？</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">其实思路很简单，就是将一些廉价的 PC 机通过网络连接起来，共同完成工作，并且在系统中提供冗余来解决高可用的问题。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>分布式系统引入了哪些新的问题？</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">我们来看分布式系统的定义：分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。在定义中，我们可用看出，分布式系统它通过多工作节点来解决单机系统面临的成本和可用性问题，但是它引入了对分布式系统内部工作节点的协调问题。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">我们经常说掌握一个知识需要理解它的前因后果，对于分布式系统来说，前因是「分布式系统解决了什么问题」，后果是「它是怎么做内部工作节点的协调」，所以我们要解决的第二个问题是：分布式系统是怎么做内部工作节点协调的？</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>分布式计算引入了哪些新的问题？</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">先从简单的情况入手，对于分布式计算（无状态）的情况，系统内部的协调需要做哪些工作：</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>1.怎么样找到服务？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">在分布式系统内部，会有不同的服务（角色），服务 A 怎么找到服务 B 是需要解决的问题，一般来说服务注册与发现机制是常用的思路，所以可以了解一下服务注册发现机制实现原理，并且可以思考服务注册发现是选择做成 AP 还是 CP 系统更合理（严格按 CAP 理论说，我们目前使用的大部分系统很难满足 C 或者 A 的，所以这里只是通常意义上的 AP 或者 CP）；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>2.怎么样找到实例？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">找到服务后，当前的请求应该选择发往服务的哪一个实例呢？一般来说，如果同一个服务的实例都是完全对等的（无状态），那么按负载均衡策略来处理就足够（轮询、权重、hash、一致性 hash，fair 等各种策略的适用场景）；如果同一个服务的实例不是对等的（有状态），那么需要通过路由服务（元数据服务等）先确定当前要访问的请求数据做哪一个实例上，然后再进行访问。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>3.怎么样避免雪崩？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">系统雪崩是指故障的由于正反馈循序导致不断扩大规则的故障。一次雪崩通常是由于整个系统中一个很小的部分出现故障于引发，进而导致系统其它部分也出现故障。比如系统中某一个服务的一个实例出现故障，导致负载均衡将该实例摘除而引起其它实例负载升高，最终导致该服务的所有实例像多米诺骨牌一样一个一个全部出现故障。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">避免雪崩总体的策略比较简单，只要是两个思路，一个是快速失败和降级机制（熔断、降级、限流等），通过快速减少系统负载来避免雪崩的发生；另一个为弹性扩容机制，通过快速增加系统的服务能力来避免雪崩的发生。这个根据不同的场景可以做不同的选择，或者两个策略都使用。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">一般来说，快速失败会导致部分的请求失败，如果分布式系统内部对一致性要求很高的话，快速失败会带来系统数据不一致的问题，弹性扩容会是一个比较好的选择，但是弹性扩容的实现成本和响应时间比快速失败要大得多。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>4.怎么样监控告警？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">对于一个分布式系统，如果我们不能很清楚地了解内部的状态，那么高可用是没有办法完全保障的，所以对分布式系统的监控（比如接口的时延和可用性等信息），分布式追踪 Trace，模拟故障的混沌工程，以及相关的告警等机制是一定要完善的；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>分布式存储引入了哪些新的问题？</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">接下来我们再来看分布式存储（有状态）的内部的协调是怎么做的，同时，前面介绍的分布式计算的协调方式在分布式存储中同样适用，就不再重复了：</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>1.分布式系统的理论与衡权</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">ACID、BASE 和 CAP 理论，了解这三个主题，推荐这一篇文章以及文章后面相关的参考文献：</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">英文版本：<a href="https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/" title="" data-type="link" target="_blank" style="transition: all 0.3s ease 0s; text-decoration-line: none; overflow-wrap: break-word; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); color: #1458d4;">https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/</a><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">中文版本：<a href="https://www.infoq.cn/article/cap-twelve-years-later-how-the-rules-have-changed/" title="" data-type="link" target="_blank" style="transition: all 0.3s ease 0s; text-decoration-line: none; overflow-wrap: break-word; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); color: #1458d4;">https://www.infoq.cn/article/cap-twelve-years-later-how-the-rules-have-changed/</a><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>2.怎么样做数据分片？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">单机的存储能力是不可能存储所有的数据的，所以需要解决怎么将数据按一定的规则分别存储到不同的机器上，目前使用比较多的方案为：Hash、Consistent Hash 和 Range Based 分片策略，可以了解一下它们的优缺点和各自的应用场景；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>3.怎么样做数据复制？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">为什么满足系统的高可用要求，需要对数据做冗余处理，目前的方案主要为：中心化方案（主从复制、一致性协议比如 Raft 和 Paxos 等）和 去中心化的方案（Quorum 和 Vector Clock）了解一下它们的优缺点和各自的应用场景，以及对系统外部表现出来的数据一致性级别（线性一致性、顺序一致性、最终一致性等）；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>4.怎么样做分布式事务？</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">对于分布式系统来说，要实现事务，首先需要有对并发事务进行排序的能力，这样在事务冲突的时候，确认哪个事务提供成功，哪个事务提交失败。对于单机系统来说这个完全不是问题，简单通过时间戳加序号的方式就可以实现，但是对于分布式系统来说，系统中机器的时间不能完全同步，并且单台机器序号也没用全局意义，按上面的方式说行不通的。不过整个系统选一台机器按单机的模式生产事务 ID 是可以的，同城多中心和短距离的异地多中心都没有问题，不过想做成全球分布式系统的话，那么每一次事务都要去一个节点去获取事务 ID 的成本太高（比如中国杭州到美国东部的 RTT 为 200 + ms ），Google 的 Spanner 是通过 GPS 和原子钟实现 TrueTime API 来解决这个问题从而实现全球分布式数据库的。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">有了事务 ID 后，通过 2PC 或者 3PC 协议来实现分布式事务的原子性，其他部分和单机事务差别不大，就不再细说来。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>进阶学习阶段</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">到这里，对分布式系统脉络上有了基本的概念，接下来开始进入细节学习阶段，这也是非常幸苦的阶段，对于分布式系统的理解深入与否，对细节的深入度是很重要的评价指标，毕竟魔鬼在细节。这里可以往两个方面进行系统的学习：</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>1.从实践出发</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">研究目前比较常用的分布式系统的设计，HDFS 或者 GFS（分布式文件系统）、Kafka 和 Pulsar（分布式消息队列），Redis Cluster 和 Codis（分布式缓存），MySQL 的分库分表（传统关系型数据库的分布式方案），MongoDB 的 Replica Set 和 Sharing 机制集以及去中心化的 Cassandra（NoSQL 数据库），中心化的 TiDB 和去中心化的 CockroachDB（NewSQL），以及一些微服务框架等；</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h3>2.从理论出发</h3><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">从理论出发，研究分布式相关的论文，这里推荐一本书「Designing Data-Intensive Applications」（中文版本：数据密集型应用系统设计），先整体看书，对比较感兴趣的章节，再读一读该章节中涉及到的相关参考文献。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><h2>总结</h2><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;">本文从分布式系统解决的问题开始，再讨论它是怎么样来解决问题的，最后讨论了它引入了哪些新的问题，并且讨论这些新问题的解决办法，这个就是分布式系统大概的知识脉络。掌握这个知识脉络后，那么就可以从实践和理论两个角度结合起来深入细节研究分布式系统了。</p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><span data-type="strong" style="font-weight: 700;">参考</span></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><a href="https://www.zhihu.com/question/320812569/answer/1386491563" title="" data-type="link" target="_blank" style="transition: all 0.3s ease 0s; text-decoration-line: none; overflow-wrap: break-word; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); color: #1458d4;">知乎 | 如何系统性的学习分布式系统</a><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><a href="https://book.douban.com/subject/26197294/" title="" data-type="link" target="_blank" style="transition: all 0.3s ease 0s; text-decoration-line: none; overflow-wrap: break-word; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); color: #1458d4;">Martin Kleppmann.Designing Data-Intensive Applications</a><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><br /></p><p data-type="paragraph" style="margin: 0px; padding: 0px; line-height: 1.875; font-size: 16px; min-height: 30px; white-space: pre-wrap; color: #303030; font-family: &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, Verdana, &quot;Microsoft Yahei&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft Sans Serif&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-color: #ffffff;"><a href="https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/" title="" data-type="link" target="_blank" style="transition: all 0.3s ease 0s; text-decoration-line: none; overflow-wrap: break-word; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); color: #1458d4;">CAP Twelve Years Later: How the &#8220;Rules&#8221; Have Changed</a></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/435735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2020-11-26 16:20 <a href="http://www.blogjava.net/xiaomage234/archive/2020/11/26/435735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样打造一个分布式数据库</title><link>http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 23 Aug 2016 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431664.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431664.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431664.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">在技术方面，我自己热衷于 Open Source，写了很多 Open Source 的东西，擅长的是 Infrastructure 领域。Infrastructure 领域现在范围很广，比如说很典型的分布式 Scheduler、Mesos、Kubernetes，另外它和 Microservices 所结合的东西也特别多。Infrastructure 领域还有比如 Database 有分 AP（分析型）和 TP（事务型），比如说很典型的大家知道的 Spark、Greenplum、Apache Phoenix 等等，这些都属于在 AP 的，它们也会去尝试支持有限的 TP。另外，还有一个比较有意思的就是 Kudu&#8212;&#8212;Cloudera Open Source 的那个项目，它的目标很有意思：我不做最强的 AP 系统，也不做最强的 TP 系统，我选择一个相对折中的方案。从文化哲学上看，它比较符合中国的中庸思想。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，我先后创建了 Codis、TiDB。去年12月份创建了 TiKV 这个 project，TiKV 在所有的 rust 项目里目前排名前三。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">首先我们聊聊 Database 的历史，在已经有这么多种数据库的背景下我们为什么要创建另外一个数据库；以及说一下现在方案遇到的困境，说一下 Google Spanner 和 F1、TiKV 和 TiDB，说一下架构的事情，在这里我们会重点聊一下 TiKV。因为我们产品的很多特性是 TiKV 提供的，比如说跨数据中心的复制、Transaction、auto-scale。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">接下来聊一下为什么 TiKV 用 Raft 能实现所有这些重要的特性，以及 scale、MVCC 和事务模型。东西非常多，我今天不太可能把里面的技术细节都描述得特别细，因为几乎每一个话题都可以找到一篇或者是多篇论文，所以详细的技术问题大家可以单独来找我聊。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">后面再说一下我们现在遇到的窘境，就是大家常规遇到的分布式方案有哪些问题，比如 MySQL Sharding。我们创建了无数 MySQL Proxy，比如官方的 MySQL proxy、Youtube 的 Vitess、淘宝的 Cobar、TDDL以及基于 Cobar 的 MyCAT、金山的 Kingshard、360 的 Atlas、京东的 JProxy，我在豌豆荚也写了一个。可以说，随便一个大公司都会造一个 MySQL Sharding 的方案。</p><h2>为什么我们要创建另外一个数据库？</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">昨天晚上我还跟一个同学聊到，基于 MySQL 的方案它的天花板在哪里，它的天花板特别明显。有一个思路是能不能通过 MySQL 的 server 把 InnoDB 变成一个分布式数据库，听起来这个方案很完美，但是很快就会遇到天花板。因为 MySQL 生成的执行计划是个单机的，它认为整个计划的 cost 也是单机的，我读取一行和读取下一行之间的开销是很小的，比如迭代 next row 可以立刻拿到下一行。实际上在一个分布式系统里面，这是不一定的。</p><div id="lowerFullwidthVCR" style="margin: 0px; border: 0px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; line-height: 25.2px; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，你把数据都拿回来计算这个太慢了，很多时候我们需要把我们的 expression 或者计算过程等等运算推下去，向上返回一个最终的计算结果，这个一定要用分布式的 plan，前面控制执行计划的节点，它必须要理解下面是分布式的东西，才能生成最好的 plan，这样才能实现最高的执行效率。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说你做一个 sum，你是一条条拿回来加，还是让一堆机器一起算，最后给我一个结果。 例如我有 100 亿条数据分布在 10 台机器上，并行在这 10台机器我可能只拿到 10 个结果，如果把所有的数据每一条都拿回来，这就太慢了，完全丧失了分布式的价值。聊到 MySQL 想实现分布式，另外一个实现分布式的方案就是 Proxy。但是 Proxy 本身的天花板在那里，就是它不支持分布式的 transaction，它不支持跨节点的 join，它无法理解复杂的 plan，一个复杂的 plan 打到 Proxy 上面，Proxy 就傻了，我到底应该往哪一个节点上转发呢，如果我涉及到 subquery sql 怎么办？所以这个天花板是瞬间会到，在传统模型下面的修改，很快会达不到我们的要求。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外一个很重要的是，MySQL 支持的复制方式是半同步或者是异步，但是半同步可以降级成异步，也就是说任何时候数据出了问题你不敢切换，因为有可能是异步复制，有一部分数据还没有同步过来，这时候切换数据就不一致了。前一阵子出现过某公司突然不能支付了这种事件，今年有很多这种类似的 case，所以微博上大家都在说&#8220;说好的异地多活呢？&#8221;&#8230;&#8230;</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">为什么传统的方案在这上面解决起来特别的困难，天花板马上到了，基本上不可能解决这个问题。另外是多数据中心的复制和数据中心的容灾，MySQL 在这上面是做不好的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/10.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">在前面三十年基本上是关系数据库的时代，那个时代创建了很多伟大的公司，比如说 IBM、Oracle、微软也有自己的数据库，早期还有一个公司叫 Sybase，有一部分特别老的程序员同学在当年的教程里面还可以找到这些东西，但是现在基本上看不到了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外是 NoSQL。NoSQL 也是一度非常火，像 Cassandra、MongoDB 等等，这些都属于在互联网快速发展的时候创建这些能够 scale 的方案，但 Redis scale 出来比较晚，所以很多时候大家把 Redis 当成一个 Cache，现在慢慢大家把它当成存储不那么重要的数据的数据库。因为它有了 scale 支持以后，大家会把更多的数据放在里面。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">然后到了 2015，严格来讲是到 2014 年到 2015 年之间，Raft 论文发表以后，真正的 NewSQL 的理论基础终于完成了。我觉得 NewSQL 这个理论基础，最重要的划时代的几篇论文，一个是谷歌的 Spanner，是在 2013 年初发布的；再就是 Raft 是在 2014 年上半年发布的。这几篇相当于打下了分布式数据库 NewSQL 的理论基础，这个模型是非常重要的，如果没有模型在上面是堆不起来东西的。说到现在，大家可能对于模型还是可以理解的，但是对于它的实现难度很难想象。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">前面我大概提到了我们为什么需要另外一个数据库，说到 Scalability 数据的伸缩，然后我们讲到需要 SQL，比如你给我一个纯粹的 key-velue 系统的 API，比如我要查找年龄在 10 岁到 20 岁之间的 email 要满足一个什么要求的。如果只有 KV 的 API 这是会写死人的，要写很多代码，但是实际上用 SQL 写一句话就可以了，而且 SQL 的优化器对整个数据的分布是知道的，它可以很快理解你这个 SQL，然后会得到一个最优的 plan，他得到这个最优的 plan 基本上等价于一个真正理解 KV 每一步操作的人写出来的程序。通常情况下，SQL 的优化器是为了更加了解或者做出更好的选择。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外一个就是 ACID 的事务，这是传统数据库必须要提供的基础。以前你不提供 ACID 就不能叫数据库，但是近些年大家写一个内存的 map 也可以叫自己是数据库。大家写一个 append-only 文件，我们也可以叫只读数据库，数据库的概念比以前极大的泛化了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外就是高可用和自动恢复，他们的概念是什么呢？有些人会有一些误解，因为今天还有朋友在现场问到，出了故障，比如说一个机房挂掉以后我应该怎么做切换，怎么操作。这个实际上相当于还是上一代的概念，还需要人去干预，这种不算是高可用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">未来的高可用一定是系统出了问题马上可以自动恢复，马上可以变成可用。比如说一个机房挂掉了，十秒钟不能支付，十秒钟之后系统自动恢复了变得可以支付，即使这个数据中心再也不起来我整个系统仍然是可以支付的。Auto-Failover 的重要性就在这里。大家不希望在睡觉的时候被一个报警给拉起来，我相信大家以后具备这样一个能力，5 分钟以内的报警不用理会，挂掉一个机房，又挂掉一个机房，这种连续报警才会理。我们内部开玩笑说，希望大家都能睡个好觉，很重要的事情就是这个。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">说完应用层的事情，现在很有很多业务，在应用层自己去分片，比如说我按照 user ID在代码里面分片，还有一部分是更高级一点我会用到一致性哈希。问题在于它的复杂度，到一定程度之后我自动的分库，自动的分表，我觉得下一代数据库是不需要理解这些东西的，不需要了解什么叫做分库，不需要了解什么叫做分表，因为系统是全部自动搞定的。同时复杂度，如果一个应用不支持事务，那么在应用层去做，通常的做法是引入一个外部队列，引入大量的程序机制和状态转换，A 状态的时候允许转换到 B 状态，B 状态允许转换到 C 状态。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">举一个简单的例子，比如说在京东上买东西，先下订单，支付状态之后这个商品才能出库，如果不是支付状态一定不能出库，每一步都有严格的流程。</p><h2>Google Spanner / F1</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">说一下 Google 的 Spanner 和 F1，这是我非常喜欢的论文，也是我最近几年看过很多遍的论文。 Google Spanner 已经强大到什么程度呢？Google Spanner 是全球分布的数据库，在国内目前普遍做法叫做同城两地三中心，它们的差别是什么呢？以 Google 的数据来讲，谷歌比较高的级别是他们有 7 个副本，通常是美国保存 3 个副本，再在另外 2 个国家可以保存 2 个副本，这样的好处是万一美国两个数据中心出了问题，那整个系统还能继续可用，这个概念就是比如美国 3 个副本全挂了，整个数据都还在，这个数据安全级别比很多国家的安全级别还要高，这是 Google 目前做到的，这是全球分布的好处。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">现在国内主流的做法是两地三中心，但现在基本上都不能自动切换。大家可以看到很多号称实现了两地三中心或者异地多活，但是一出现问题都说不好意思这段时间我不能提供服务了。大家无数次的见到这种 case， 我就不列举了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Spanner 现在也提供一部分 SQL 特性。在以前，大部分 SQL 特性是在 F1 里面提供的，现在 Spanner 也在逐步丰富它的功能，Google 是全球第一个做到这个规模或者是做到这个级别的数据库。事务支持里面 Google 有点黑科技（其实也没有那么黑），就是它有<span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">GPS 时钟和原子钟</span>。大家知道在分布式系统里面，比如说数千台机器，两个事务启动先后顺序，这个顺序怎么界定(事务外部一致性)。这个时候 Google 内部使用了 GPS 时钟和原子钟，正常情况下它会使用一个GPS 时钟的一个集群，就是说我拿的一个时间戳，并不是从一个 GPS 上来拿的时间戳，因为大家知道所有的硬件都会有误差。如果这时候我从一个上拿到的 GPS 本身有点问题，那么你拿到的这个时钟是不精确的。而 Google 它实际上是在一批 GPS 时钟上去拿了能够满足 majority 的精度，再用时间的算法，得到一个比较精确的时间。大家知道 GPS 也不太安全，因为它是美国军方的，对于 Google 来讲要实现比国家安全级别更高的数据库，而 GPS 是可能受到干扰的，因为 GPS 信号是可以调整的，这在军事用途上面很典型的，大家知道导弹的制导需要依赖 GPS，如果调整了 GPS 精度，那么导弹精度就废了。所以他们还<span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">用原子钟去校正 GPS</span>，如果 GPS 突然跳跃了，原子钟上是可以检测到 GPS 跳跃的，这部分相对有一点黑科技，但是从原理上来讲还是比较简单，比较好理解的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">最开始它 Spanner 最大的用户就是 Google 的 Adwords，这是 Google 最赚钱的业务，Google 就是靠广告生存的，我们一直觉得 Google 是科技公司，但是他的钱是从广告那来的，所以一定程度来讲 Google 是一个广告公司。Google 内部的方向先有了 Big table ，然后有了 MegaStore ，MegaStore 的下一代是 Spanner ，F1 是在 Spanner 上面构建的。</p><h2>TiDB and TiKV</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">TiKV 和 TiDB 基本上对应 Google Spanner 和 Google F1，用 Open Source 方式重建。目前这两个项目都开放在 GitHub 上面，两个项目都比较火爆，TiDB 是更早一点开源的， 目前 TiDB 在 GitHub 上 有 4300 多个 Star，每天都在增长。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，对于现在的社会来讲，我们觉得 Infrastructure 领域闭源的东西是没有任何生存机会的。没有任何一家公司，愿意把自己的身家性命压在一个闭源的项目上。举一个很典型的例子，在美国有一个数据库叫 FoundationDB，去年被苹果收购了。FoundationDB 之前和用户签的合约都是一年的合约。比如说，我给你服务周期是一年，现在我被另外一个公司收购了，我今年服务到期之后，我是满足合约的。但是其他公司再也不能找它服务了，因为它现在不叫 FoundationDB 了，它叫 Apple了，你不能找 Apple 给你提供一个 Enterprise service。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/11.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">TiDB 和 TiKV 为什么是两个项目，因为它和 Google 的内部架构对比差不多是这样的：TiKV 对应的是 Spanner，TiDB 对应的是 F1 。F1 里面更强调上层的分布式的 SQL 层到底怎么做，分布式的 Plan 应该怎么做，分布式的 Plan 应该怎么去做优化。同时 TiDB 有一点做的比较好的是，它兼容了 MySQL 协议，当你出现了一个新型的数据库的时候，用户使用它是有成本的。大家都知道作为开发很讨厌的一个事情就是，我要每个语言都写一个 Driver，比如说你要支持 C++、你要支持 Java、你要支持 Go 等等，这个太累了，而且用户还得改他的程序，所以我们选择了一个更加好的东西兼容 MySQL 协议，让用户可以不用改。一会我会用一个视频来演示一下，为什么一行代码不改就可以用，用户就能体会到 TiDB 带来的所有的好处。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/12.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这个图实际上是整个协议栈或者是整个软件栈的实现。大家可以看到整个系统是高度分层的，从最底下开始是 RocksDB ，然后再上面用 Raft 构建一层可以被复制的 RocksDB ，在这一层的时候它还没有 Transaction，但是整个系统现在的状态是所有写入的数据一定要保证它复制到了足够多的副本。也就是说只要我写进来的数据一定有足够多的副本去 cover 它，这样才比较安全，在一个比较安全的 Key-value store 上面， 再去构建它的多版本，再去构建它的分布式事务，然后在分布式事务构建完成之后，就可以轻松的加上 SQL 层，再轻松的加上MySQL 协议的支持。然后，这两天我比较好奇，自己写了 MongoDB 协议的支持，然后我们可以用 MongoDB 的客户端来玩，就是说协议这一层是高度可插拔的。TiDB 上可以在上面构建一个 MongoDB 的协议，相当于这个是构建一个 SQL 的协议，可以构建一个 NoSQL 的协议。这一点主要是用来验证 TiKV 在模型上面的支持能力。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/13.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是整个 TiKV 的架构图，从这个看来，整个集群里面有很多 Node，比如这里画了四个 Node ，分别对应了四个机器。每一个 Node 上可以有多个 Store，每个 Store 里面又会有很多小的 Region，就是说一小片数据，就是一个 Region 。从全局来看所有的数据被划分成很多小片，每个小片默认配置是 64M，它已经足够小，可以很轻松的从一个节点移到另外一个节点，Region 1 有三个副本，它分别在 Node1、Node 2 和 Node4 上面， 类似的Region 2，Region 3 也是有三个副本。每个 Region 的所有副本组成一个 Raft Group，整个系统可以看到很多这样的 Raft groups。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Raft 细节我不展开了，大家有兴趣可以找我私聊或者看一下相应的资料。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">因为整个系统里面我们可以看到上一张图里面有很多 Raft group 给我们，不同 Raft group 之间的通讯都是有开销的。所以我们有一个类似于 MySQL 的 group commit 机制 ，你发消息的时候实际上可以 share 同一个 connection ， 然后 pipeline + batch 发送，很大程度上可以省掉大量 syscall 的开销。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，其实在一定程度上后面我们在支持压缩的时候，也有非常大的帮助，就是可以减少数据的传输。对于整个系统而言，可能有数百万的 Region，它的大小可以调整，比如说 64M、128M、256M，这个实际上依赖于整个系统里面当前的状况。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说我们曾经在有一个用户的机房里面做过测试，这个测试有一个香港机房和新加坡的机房。结果我们在做复制的时候，新加坡的机房大于 256M 就复制不过去，因为机房很不稳定，必须要保证数据切的足够小，这样才能复制过去。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">如果一个 Region 太大以后我们会自动做 SPLIT，这是非常好玩的过程，有点像细胞的分裂。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">然后 TiKV 的 Raft 实现，是从 etcd 里面 port 过来的，为什么要从 etcd 里面 port 过来呢？首先 TiKV 的 Raft 实现是用 Rust 写的。作为第一个做到生产级别的 Raft 实现，所以我们从 etcd 里面把它用 Go 语言写的 port 到这边。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/14.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这个是 Raft 官网上面列出来的 TiKV在里面的状态，大家可以看到 TiKV 把所有 Raft 的 feature 都实现了。 比如说 Leader Election、Membership Changes，这个是非常重要的，整个系统的 scale 过程高度依赖 Membership Changes，后面我用一个图来讲这个过程。后面这个是 Log Compaction，这个用户不太关心。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/15.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是很典型的细胞分裂的图，实际上 Region 的分裂过程和这个是类似的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">我们看一下扩容是怎么做的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/16.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说以现在的系统假设，我们刚开始说只有三个节点，有 Region1 分别是在 1 、2、4，我用虚线连接起来代表它是一个 Raft group ，大家可以看到整个系统里面有三个 Raft group ，在每一个 Node 上面数据的分布是比较均匀的，在这个假设每一个 Region 是 64M ，相当于只有一个 Node 上面负载比其他的稍微大一点点。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">一个在线视频默认我们都是推荐 3 个副本或者 5 个副本的配置。Raft 本身有一个特点，如果一个 leader down 掉之后，其它的节点会选一个新的 leader ，那么这个新的 leader 会把它还没有 commit 但已经 reply 过去的 log 做一个 commit ，然后会再做 apply ，这个有点偏 Raft 协议，细节我不讲了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">复制数据的小的 Region，它实际上是跨多个数据中心做的复制。这里面最重要的一点是永远不丢失数据，无论如何我保证我的复制一定是复制到 majority ，任何时候我只要对外提供服务，允许外面写入数据一定要复制到 majority 。很重要的一点就是恢复的过程一定要是自动化的，我前面已经强调过，如果不能自动化恢复，那么中间的宕机时间或者对外不可服务的时间，便不是由整个系统决定的，这是相对回到了几十年前的状态。</p><h2>MVCC</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">MVCC 我稍微仔细讲一下这一块。MVCC 的好处，它很好支持 Lock-free 的 snapshot read ，一会儿我有一个图会展示 MVCC 是怎么做的。isolation level 就不讲了， MySQL 里面的级别是可以调的，我们的 TiKV 有 SI，还有 SI+lock，默认是支持 SI 的这种隔离级别，然后你写一个 select for update 语句，这个会自动的调整到 SI 加上 lock 这个隔离级别。这个隔离级别基本上和 SSI 是一致的。还有一个就是 GC 的问题，如果你的系统里面的数据产生了很多版本，你需要把这个比较老的数据给 GC 掉，比如说正常情况下我们是不删除数据的， 你写入一行，然后再写入一行，不断去 update 同一行的时候，每一次 update 会产生新的版本，新的版本就会在系统里存在，所以我们需要一个 GC 的模块把比较老的数据给 GC 掉，实际上这个 GC 不是 Go 里面的GC，不是 Java 的 GC，而是数据的 GC。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/17.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是一个数据版本，大家可以看到我们的数据分成两块，一个是 meta，一个是 data。meta 相对于描述我的数据当前有多少个版本。大家可以看到绿色的部分，比如说我们的 meta key 是 A ，keyA 有三个版本，是 A1 、A2、A3，我们把 key 自己和 version 拼到一起。那我们用 A1、A2、A3 分别描述 A 的三个版本，那么就是 version 1/2/3。meta 里面描述，就是我的整个 key 相对应哪个版本，我想找到那个版本。比如说我现在要读取 key A 的版本10，但显然现在版本 10 是没有的，那么小于版本 10 最大的版本是 3，所以这时我就能读取到 3，这是它的隔离级别决定的。关于 data，我刚才已经讲过了。</p><h2>分布式事务模型</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">接下来是分布式事务模型，其实是基于 Google Percolator，这是 Google 在 2006 发表的一篇论文，是 Google 在做内部增量处理的时候发现了这个方法，本质上还是二阶段提交的。这使用的是一个乐观锁，比如说我提供一个 transaction ，我去改一个东西，改的时候是发布在本地的，并没有马上 commit 到数据存储那一端，这个模型就是说，我修改的东西我马上去 Lock 住，这个基本就是一个悲观锁。但如果到最后一刻我才提交出去，那么锁住的这一小段的时间，这个时候实现的是乐观锁。乐观锁的好处就是当你冲突很小的时候可以得到非常好的性能，因为冲突特别小，所以我本地修改通常都是有效的，所以我不需要去 Lock ，不需要去 roll back 。本质上分布式事务就是 2PC (两阶段提交) 或者是 2+x PC，基本上没有 1PC，除非你在别人的级别上做弱化。比如说我允许你读到当前最新的版本，也允许你读到前面的版本，书里面把这个叫做幻读。如果你调到这个程度是比较容易做 1PC 的，这个实际上还是依赖用户设定的隔离级别的，如果用户需要更高的隔离级别，这个 1PC就不太好做了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是一个路由，正常来讲，大家可能会好奇一个 SQL 语句怎么最后会落到存储层，然后能很好的运行，最后怎么能映射到 KV 上面，又怎么能路由到正确的节点，因为整个系统可能有上千个节点，你怎么能正确路由到那一个的节点。我们在 TiDB 有一个 TiKV driver ， 另外 TiKV 对外使用的是 Google Protocol Buffer 来作为通讯的编码格式。</p><h2>Placement Driver</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">来说一下 Placement Driver 。Placement Driver 是什么呢？整个系统里面有一个节点，它会时刻知道现在整个系统的状态。比如说每个机器的负载，每个机器的容量，是否有新加的机器，新加机器的容量到底是怎么样的，是不是可以把一部分数据挪过去，是不是也是一样下线， 如果一个节点在十分钟之内无法被其他节点探测到，我认为它已经挂了，不管它实际上是不是真的挂了，但是我也认为它挂了。因为这个时候是有风险的，如果这个机器万一真的挂了，意味着你现在机器的副本数只有两个，有一部分数据的副本数只有两个。那么现在你必须马上要在系统里面重新选一台机器出来，它上面有足够的空间，让我现在只有两个副本的数据重新再做一份新的复制，系统始终维持在三个副本。整个系统里面如果机器挂掉了，副本数少了，这个时候应该会被自动发现，马上补充新的副本，这样会维持整个系统的副本数。这是很重要的 ，为了避免数据丢失，必须维持足够的副本数，因为副本数每少一个，你的风险就会再增加。这就是 Placement Driver 做的事情。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">同时，Placement Driver 还会根据性能负载，不断去 move 这个 data 。比如说你这边负载已经很高了，一个磁盘假设有 100G，现在已经用了 80G，另外一个机器上也是 100G，但是他只用了 20G，所以这上面还可以有几十 G 的数据，比如 40G 的数据，你可以 move 过去，这样可以保证系统有很好的负载，不会出现一个磁盘巨忙无比，数据已经多的装不下了，另外一个上面还没有东西，这是 Placement Driver 要做的东西。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Raft 协议还提供一个很高级的特性叫 leader transfer。leader transfer 就是说在我不移动数据的时候，我把我的 leadership 给你，相当于从这个角度来讲，我把流量分给你，因为我是 leader，所以数据会到我这来，但我现在把 leader给你，我让你来当 leader，原来打给我的请求会被打给你，这样我的负载就降下来。这就可以很好的动态调整整个系统的负载，同时又不搬移数据。不搬移数据的好处就是，不会形成一个抖动。</p><h2>MySQL Sharding</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">MySQL Sharding 我前面已经提到了它的各种天花板，MySQL Sharding 的方案很典型的就是解决基本问题以后，业务稍微复杂一点，你在 sharding 这一层根本搞不定。它永远需要一个 sharding key，你必须要告诉我的 proxy，我的数据要到哪里找，对用户来说是极不友好的，比如我现在是一个单机的，现在我要切入到一个分布式的环境，这时我必须要改我的代码，我必须要知道我这个 key ，我的 row 应该往哪里 Sharding。如果是用 ORM ，这个基本上就没法做这个事情了。有很多 ORM 它本身假设我后面只有一个 MySQL。但 TiDB 就可以很好的支持，因为我所有的角色都是对的，我不需要关注 Sharding 、分库、分表这类的事情。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这里面有一个很重要的问题没有提，我怎么做 DDL。如果这个表非常大的话，比如说我们有一百亿吧，横跨了四台机器，这个时候你要给它做一个新的 Index，就是我要添加一个新的索引，这个时候你必须要不影响任何现有的业务，实际上这是多阶段提交的算法，这个是 Google 和 F1 一起发出来那篇论文。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">简单来讲是这样的，先把状态标记成 delete only ，delete only 是什么意思呢？因为在分布式系统里面，所有的系统对于 schema 的视野不是一致的，比如说我现在改了一个值，有一部分人发现这个值被改了，但是还有一部分人还没有开始访问这个，所以根本不知道它被改了。然后在一个分布系统里，你也不可能实时通知到所有人在同一时刻发现它改变了。比如说从有索引到没有索引，你不能一步切过去，因为有的人认为它有索引，所以他给它建了一个索引，但是另外一个机器他认为它没有索引，所以他就把数据给删了，索引就留在里面了。这样遇到一个问题，我通过索引找的时候告诉我有， 实际数据却没有了，这个时候一致性出了问题。比如说我 count 一个 email 等于多少的，我通过 email 建了一个索引，我认为它是在，但是 UID 再转过去的时候可能已经不存在了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说我先标记成 delete only，我删除它的时候不管它现在有没有索引，我都会尝试删除索引，所以我的数据是干净的。如果我删除掉的话，我不管结果是什么样的，我尝试去删一下，可能这个索引还没 build 出来，但是我仍然删除，如果数据没有了，索引一定没有了，所以这可以很好的保持它的一致性。后面再类似于前面，先标记成 write only 这种方式，连续再迭代这个状态，就可以迭代到一个最终可以对外公开的状态。比如说当我迭代到一定程度的时候，我可以从后台 build index ，比如说我一百亿，正在操作的 index 会马上 build，但是还有很多没有 build index ，这个时候后台不断的跑 map-reduce 去 build index ，直到整个都 build 完成之后，再对外 public ，就是说我这个索引已经可用了，你可以直接拿索引来找，这个是非常经典的。在这个 Online，Asynchronous Schema Change in F1 paper之前，大家都不知道这事该怎么做。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Proxy Sharding 的方案不支持分布式事务，更不用说跨数据中心的一致性事务了。 TiKV 很好的支持 transaction，刚才提到的 Raft 除了增加副本之外，还有 leader transfer，这是一个传统的方案都无法提供的特性。以及它带来的好处，当我瞬间平衡整个系统负载的时候，对外是透明的， 做 leader transfer 的时候并不需要移动数据，只是个简单的 leader transfer 消息。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">然后说一下如果大家想参与我们项目的话是怎样的过程，因为整个系统是完全开源的，如果大家想参与其中任何一部分都可以，比如说我想参与到分布式 KV，可以直接贡献到 TiKV。TiKV 需要写 Rust，如果大家对这块特别有激情可以体验写 Rust 的感觉 。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">TiDB 是用 Go 写的，Go 在中国的群众基础是非常多的，目前也有很多人在贡献。整个 TiDB 和TiKV 是高度协作的项目，因为 TiDB 目前还用到了 etcd ，我们在和 CoreOS 在密切的合作，也特别感谢 CoreOS 帮我们做了很多的支持，我们也为 CoreOS 的 etcd 提了一些 patch。同时，TiKV 使用 RocksDB ，所以我们也为 RocksDB 提了一些 patch 和 test，我们也非常感谢 Facebook RocksDB team 对我们项目的支持。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外一个是 PD，就是我们前面提的 Placement Driver，它负责监控整个系统。这部分的算法比较好玩，大家如果有兴趣的话，可以去自己控制整个集群的调度，它和 Kubernetes 或者是Mesos 的调度算法是不一样的，因为它调度的维度实际上比那个要更多。比如说磁盘的容量，你的 leader 的数量，你的网络当前的使用情况，你的 IO 的负载和 CPU 的负载都可以放进去。同时你还可以让它调度不要跨一个机房里面建多个副本。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/431664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-08-23 15:12 <a href="http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>12306火车票订票系统的伸缩扩展</title><link>http://www.blogjava.net/xiaomage234/archive/2016/08/17/431613.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 17 Aug 2016 08:40:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/08/17/431613.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431613.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/08/17/431613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431613.html</trackback:ping><description><![CDATA[<h3>from:<span style="font-size: 14px;">http://www.jdon.com/46111<br /><br /><br /></span></h3><h1 class="tpc_content" id="body_23144388" style="font-family: 微软雅黑, 宋体; font-size: 14px; letter-spacing: 0.5px; line-height: 25px; font-weight: normal; margin: 5px; background-color: #ffffff;">本文来自Pivotal，分析了中国铁路总公司12306这个世界上最大的铁路系统的火车票预订系统。<br /><br />在这个星球上人类最大的年度运动大概算是中国农历新年，又称春节。有3488万人次通过航空和235万人次通过铁路踏上他们的旅途。从历史上看，铁路旅行意味着排长龙队伍买票，中国铁路总公司（CRC）现在开始在网上卖火车票，提供比车站售票处或通过电话购买更方便的方法。<br /><br />随着越来越多人的使用车票预订系统，12306铁路订票系统打破了其传统的RDBMS关系数据库系统，需要重新开始了一个新的项目，以改善原有系统性能和可<a href="http://www.jdon.com/scalable.html" class="hotkeys ajax_query=伸缩性" id="id_http://www.jdon.com/scalable.html" style="text-decoration: none; color: #666666; font-weight: lighter;"><strong>伸缩性</strong></a>的问题，能够承受像春节度假旅游期间的尖峰的压力。目前该网站成为中国最受欢迎网站的之一。在这样严苛的访问条件下，系统出现以下很差用户体验：使用中断，性能差，预订错误，支付失败，票务确认出现问题等等。<br /><br />中国铁道科学研究院的副主任朱剑圣首先解决性能问题，早在2011年，朱博士确保新系统解决基于下面两个性能瓶颈：<br /><br />1.关系型数据库超负载，以至于不能处理传入的请求，无论是规模扩展性还是可靠性，都不能满足SLA要求的水平。&nbsp;<br /><br />2.UNIX服务器的计算能力不足以解决容量需求。<br /><br />朱博士说：&#8220;传统关系型数据库和大型机的计算模式并不具有扩展性，系统不能基于内存扩展跨多个节点上运行。我们的网站证明了这一点，而试图扩展我们的遗留系统将变得非常昂贵&#8221;。<br /><br /><strong>使用In-memory内存数据网格解决扩展性和可靠性</strong><br />朱博士的团队开始寻找新的解决方案，大型机被发现和关系数据库有同样的瓶颈，在内存数据网格(IMDG)领域，他们发现了<a href="http://www.gopivotal.com/products/pivotal-gemfire" class="body_href" style="text-decoration: none; color: #666666; font-weight: lighter;">Pivotal GemFire</a>，在海运货物系统 金融服务，航空，电子商务等多个行业都拥有成功解决最具挑战性的数据问题的良好记录。为了执行评估，朱博士和他的团队选择了国际综合系统公司（IISI）。IISI拥有强大为政府机构工作的跟踪记录，包括在开发交通运输解决方案，迁移遗留系统到<a href="http://www.jdon.com/cloudcompute.html" class="hotkeys ajax_query=云计算" id="id_http://www.jdon.com/cloudcompute.html" style="text-decoration: none; color: #666666; font-weight: lighter;"><strong>云计算</strong></a>架构等方面经历，有与Pivotal GemFire合作经验。他们开始试点，相信了GemFire&#8203;&#8203;将满足性能，可扩展性和可用性的要求，包括能够在低成本硬件上运行。<br /><br />IISI创造了一个概念证明和展示了GemFire几个优点&#8203;&#8203;。售票计算速度提高50到100倍。当负载增加时，响应时间保持10-100毫秒的延迟。他们可以看到，通过增加容量，能实现近乎线性增长的可扩展性和高可用性的能力。项目组在短短两个月内建立了一个试点，四个月后，新的在线系统全面部署，跨越5700火车站。<br /><br />该小组负责铁路网上预订系统每年增长高达50％。他们的网站每天的平均水平预订250万票。<br /><br />72台UNIX系统和关系数据库换成了10台初始和10个备份的x86服务器，这是一个更具成本效益的模式，能在内存中处理2TB或一个月的的火车票数据。<br /><br />朱博士认为：&#8220;首先，Pivotal GemFire&#8203;&#8203;提供了一个在真实的测试环境的证明。然后，在生产环境面对意想不到的尖峰也是成功的，具体采取了一个迭代的方法来部署，克服了一系列大规模的挑战。在最近的2013春运期间，该系统具备了运行稳定的性能和正常运行时间。现在，我们有一个可靠，经济合理的生产体系&#8203;&#8203;，支持记录容量增长的空间。这个规模实现10-100毫秒的延迟。&#8221;<br /><br />基于高可用性，冗余和故障切换机制上的GemFire&#8203;&#8203;提供了连续正常运行，它已超出了所有在该领域的CRC校验的指标，并帮助他们维护他们的SLA。<br /><br /><a href="http://gopivotal.com/sites/default/files/China_Railway_Corporation_CS_GemFire_2014.pdf" class="body_href" style="text-decoration: none; color: #666666; font-weight: lighter;">具体PDF下载</a></h1><img src ="http://www.blogjava.net/xiaomage234/aggbug/431613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-08-17 16:40 <a href="http://www.blogjava.net/xiaomage234/archive/2016/08/17/431613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Kubernetes系统架构简介</title><link>http://www.blogjava.net/xiaomage234/archive/2016/04/23/430213.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Sat, 23 Apr 2016 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/04/23/430213.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/430213.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/04/23/430213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/430213.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/430213.html</trackback:ping><description><![CDATA[from:http://www.infoq.com/cn/articles/Kubernetes-system-architecture-introduction<br /><br /><h2>1. 前言</h2><blockquote style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding-top: 10px; padding-bottom: 10px; padding-left: 45px; border-width: 1px; border-color: #e8e8e8; clear: both; width: 553px; color: #000000; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; line-height: 25.2px; float: none !important; background-image: url(&quot;i/gg.jpg&quot;); background-color: #f4f4f4; background-position: 0% 0%; background-repeat: no-repeat;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 553px; word-wrap: break-word !important;"><span style="margin: 0px; border: 0px; padding: 0px;">Together we will ensure that Kubernetes is a strong and open container management framework for any application and in any environment, whether in a private, public or hybrid cloud.</span></p></blockquote><p align="right" style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="margin: 0px; border: 0px; padding: 0px;">Urs H&#246;lzle, Google</span></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Kubernetes作为Docker生态圈中重要一员，是Google多年大规模容器管理技术的开源版本，<a style="color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">是产线实践经验的最佳表现</a><a href="http://www.infoq.com/cn/articles/Kubernetes-system-architecture-introduction#_msocom_1" name="_msoanchor_1" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">[G1]</a>&nbsp;。如Urs H&#246;lzle所说，无论是公有云还是私有云甚至混合云，Kubernetes将作为一个为任何应用，任何环境的容器管理框架无处不在。正因为如此， 目前受到各大巨头及初创公司的青睐，如Microsoft、VMWare、Red Hat、CoreOS、Mesos等，纷纷加入给Kubernetes贡献代码。随着Kubernetes社区及各大厂商的不断改进、发展，Kuberentes将成为容器管理领域的领导者。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">接下来我们会用一系列文章逐一探索Kubernetes是什么、能做什么以及怎么做。</p><h2>2. 什么是Kubernetes</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Kubernetes是Google开源的容器集群管理系统，其提供应用部署、维护、 扩展机制等功能，利用Kubernetes能方便地管理跨机器运行容器化的应用，其主要功能如下：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">1) 使用Docker对应用程序包装(package)、实例化(instantiate)、运行(run)。</p><div id="lowerFullwidthVCR" style="margin: 0px; border: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; line-height: 25.2px; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2) 以集群的方式运行、管理跨机器的容器。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">3) 解决Docker跨机器容器之间的通讯问题。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">4) Kubernetes的自我修复机制使得容器集群总是运行在用户期望的状态。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">当前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平台，除此之外，也可以直接运行在物理机上。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">接下来本文主要从以下几方面阐述Kubernetes：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">1) Kubernetes的主要概念。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2) Kubernetes的构件，包括Master组件、Kubelet、Proxy的详细介绍。</p><h4>3. Kubernetes主要概念</h4><h3>3.1. Pods</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Pod是Kubernetes的基本操作单元，把相关的一个或多个容器构成一个Pod，通常Pod里的容器运行相同的应用。Pod包含的容器运行在同一个Minion(Host)上，看作一个统一管理单元，共享相同的volumes和network namespace/IP和Port空间。</p><h3>3.2. Services</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Services也是Kubernetes的基本操作单元，是真实应用服务的抽象，每一个服务后面都有很多对应的容器来支持，通过Proxy的port和服务selector决定服务请求传递给后端提供服务的容器，对外表现为一个单一访问接口，外部不需要了解后端如何运行，这给扩展或维护后端带来很大的好处。</p><h3>3.3. Replication Controllers</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Replication Controller确保任何时候Kubernetes集群中有指定数量的pod<a name="OLE_LINK4" style="color: rgb(40, 106, 178); margin: 0px; border: 0px; padding: 0px; outline: none !important;"></a><a name="OLE_LINK3" style="color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">副本(replicas)</a>在运行， 如果少于指定数量的pod副本(replicas)，Replication Controller会启动新的Container，反之会杀死多余的以保证数量不变。Replication Controller使用预先定义的pod模板创建pods，一旦创建成功，pod 模板和创建的pods没有任何关联，可以修改pod 模板而不会对已创建pods有任何影响，也可以直接更新通过Replication Controller创建的pods。对于利用pod 模板创建的pods，Replication Controller根据label selector来关联，通过修改pods的label可以删除对应的pods。Replication Controller主要有如下用法：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">1) Rescheduling</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">如上所述，Replication Controller会确保Kubernetes集群中指定的pod副本(replicas)在运行， 即使在节点出错时。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2) Scaling</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">通过修改Replication Controller的副本(replicas)数量来水平扩展或者缩小运行的pods。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">3) Rolling updates</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Replication Controller的设计原则使得可以一个一个地替换pods来rolling updates服务。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">4) Multiple release tracks</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">如果需要在系统中运行multiple release的服务，Replication Controller使用labels来区分multiple release tracks。</p><h3>3.4. Labels</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Labels是用于区分Pod、Service、Replication Controller的key/value键值对，Pod、Service、 Replication Controller可以有多个label，但是每个label的key只能对应一个value。Labels是Service和Replication Controller运行的基础，为了将访问Service的请求转发给后端提供服务的多个容器，正是通过标识容器的labels来选择正确的容器。同样，Replication Controller也使用labels来管理通过pod 模板创建的一组容器，这样Replication Controller可以更加容易，方便地管理多个容器，无论有多少容器。</p><h2>4. Kubernetes构件</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Kubenetes整体框架如下图3-1，主要包括kubecfg、Master API Server、Kubelet、Minion(Host)以及Proxy。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn4.infoqstatic.com/statics_s1_20160414-0116/resource/articles/Kubernetes-system-architecture-introduction/zh/resources/1026000.png" width="500" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">图3-1 Kubernetes High Level构件</p><h3>4.1. Master</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Master定义了Kubernetes 集群Master/API Server的主要声明，包括Pod Registry、Controller Registry、Service Registry、Endpoint Registry、Minion Registry、Binding Registry、RESTStorage以及Client, 是client(Kubecfg)调用Kubernetes API，管理Kubernetes主要构件Pods、Services、Minions、容器的入口。Master由API Server、Scheduler以及Registry等组成。从下图3-2可知Master的工作流主要分以下步骤：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">1) Kubecfg将特定的请求，比如创建Pod，发送给Kubernetes Client。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2) Kubernetes Client将请求发送给API server。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">3) API Server根据请求的类型，比如创建Pod时storage类型是pods，然后依此选择何种REST Storage API对请求作出处理。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">4) REST Storage API对的请求作相应的处理。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">5) 将处理的结果存入高可用键值存储系统Etcd中。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">6) 在API Server响应Kubecfg的请求后，Scheduler会根据Kubernetes Client获取集群中运行Pod及Minion信息。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">7) 依据从Kubernetes Client获取的信息，Scheduler将未分发的Pod分发到可用的Minion节点上。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">下面是Master的主要构件的详细介绍：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn4.infoqstatic.com/statics_s1_20160414-0116/resource/articles/Kubernetes-system-architecture-introduction/zh/resources/1026001.png" width="500" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">图3-2 Master主要构件及工作流</p><h4>3.1.1. Minion Registry</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Minion Registry负责跟踪Kubernetes 集群中有多少Minion(Host)。Kubernetes封装Minion Registry成实现Kubernetes API Server的RESTful API接口REST，通过这些API，我们可以对Minion Registry做<a name="OLE_LINK2" style="color: rgb(40, 106, 178); margin: 0px; border: 0px; padding: 0px; outline: none !important;"></a><a name="OLE_LINK1" style="color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">Create</a>、Get、List、Delete操作，由于Minon只能被创建或删除，所以不支持Update操作，并把Minion的相关配置信息存储到etcd。除此之外，Scheduler算法根据Minion的资源容量来确定是否将新建Pod分发到该Minion节点。</p><h4>3.1.2. Pod Registry</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Pod Registry负责跟踪Kubernetes集群中有多少Pod在运行，以及这些Pod跟Minion是如何的映射关系。将Pod Registry和Cloud Provider信息及其他相关信息封装成实现Kubernetes API Server的RESTful API接口REST。通过这些API，我们可以对Pod进行Create、Get、List、Update、Delete操作，并将Pod的信息存储到etcd中，而且可以通过Watch接口监视Pod的变化情况，比如一个Pod被新建、删除或者更新。</p><h4>3.1.3. Service Registry</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Service Registry负责跟踪Kubernetes集群中运行的所有服务。根据提供的Cloud Provider及Minion Registry信息把Service Registry封装成实现Kubernetes API Server需要的RESTful API接口REST。利用这些接口，我们可以对Service进行Create、Get、List、Update、Delete操作，以及监视Service变化情况的watch操作，并把Service信息存储到etcd。</p><h4>3.1.4. Controller Registry</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Controller Registry负责跟踪Kubernetes集群中所有的Replication Controller，Replication Controller维护着指定数量的pod 副本(replicas)拷贝，如果其中的一个容器死掉，Replication Controller会自动启动一个新的容器，如果死掉的容器恢复，其会杀死多出的容器以保证指定的拷贝不变。通过封装Controller Registry为实现Kubernetes API Server的RESTful API接口REST， 利用这些接口，我们可以对Replication Controller进行Create、Get、List、Update、Delete操作，以及监视Replication Controller变化情况的watch操作，并把Replication Controller信息存储到etcd。</p><h4>3.1.5. Endpoints Registry</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Endpoints Registry负责收集Service的endpoint，比如Name："mysql"，Endpoints: ["10.10.1.1:1909"，"10.10.2.2:8834"]，同Pod Registry，Controller Registry也实现了Kubernetes API Server的RESTful API接口，可以做Create、Get、List、Update、Delete以及watch操作。</p><h4>3.1.6. Binding Registry</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Binding包括一个需要绑定Pod的ID和Pod被绑定的Host，Scheduler写Binding Registry后，需绑定的Pod被绑定到一个host。Binding Registry也实现了Kubernetes API Server的RESTful API接口，但Binding Registry是一个write-only对象，所有只有Create操作可以使用， 否则会引起错误。</p><h4>3.1.7. Scheduler</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Scheduler收集和分析当前Kubernetes集群中所有Minion节点的资源(内存、CPU)负载情况，然后依此分发新建的Pod到Kubernetes集群中可用的节点。由于一旦Minion节点的资源被分配给Pod，那这些资源就不能再分配给其他Pod， 除非这些Pod被删除或者退出， 因此，Kubernetes需要分析集群中所有Minion的资源使用情况，保证分发的工作负载不会超出当前该Minion节点的可用资源范围。具体来说，Scheduler做以下工作：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">1) 实时监测Kubernetes集群中未分发的Pod。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2) 实时监测Kubernetes集群中所有运行的Pod，Scheduler需要根据这些Pod的资源状况安全地将未分发的Pod分发到指定的Minion节点上。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">3) Scheduler也监测Minion节点信息，由于会频繁查找Minion节点，Scheduler会缓存一份最新的信息在本地。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">4) 最后，Scheduler在分发Pod到指定的Minion节点后，会把Pod相关的信息Binding写回API Server。</p><h3>4.2. Kubelet</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn4.infoqstatic.com/statics_s1_20160414-0116/resource/articles/Kubernetes-system-architecture-introduction/zh/resources/1026002.png" width="500" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">图3-3 Kubernetes详细构件</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">根据上图3-3可知Kubelet是Kubernetes集群中每个Minion和Master API Server的连接点，Kubelet运行在每个Minion上，是Master API Server和Minion之间的桥梁，接收Master API Server分配给它的commands和work，与持久性键值存储etcd、file、server和http进行交互，读取配置信息。Kubelet的主要工作是管理Pod和容器的生命周期，其包括Docker Client、Root Directory、Pod Workers、Etcd Client、Cadvisor Client以及Health Checker组件，具体工作如下：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">1) 通过Worker给Pod异步运行特定的Action。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2) 设置容器的环境变量。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">3) 给容器绑定Volume。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">4) 给容器绑定Port。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">5) 根据指定的Pod运行一个单一容器。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">6) 杀死容器。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">7) 给指定的Pod创建network 容器。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">8) 删除Pod的所有容器。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">9) 同步Pod的状态。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">10) 从Cadvisor获取container info、 pod info、root info、machine info。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">11) 检测Pod的容器健康状态信息。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">12) 在容器中运行命令。</p><h3>4.3. Proxy</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Proxy是为了解决外部网络能够访问跨机器集群中容器提供的应用服务而设计的，从上图3-3可知Proxy服务也运行在每个Minion上。Proxy提供TCP/UDP sockets的proxy，每创建一种Service，Proxy主要从etcd获取Services和Endpoints的配置信息，或者也可以从file获取，然后根据配置信息在Minion上启动一个Proxy的进程并监听相应的服务端口，当外部请求发生时，Proxy会根据Load Balancer将请求分发到后端正确的容器处理。</p><h2>5. 下篇主题</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">下篇讲述在CentOS7上用Kubernetes来管理容器。</p><h2>6. 个人简介</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">杨章显，现就职于Cisco，主要从事WebEx SaaS服务运维，系统性能分析等工作。特别关注云计算，自动化运维，部署等技术，尤其是Go、OpenvSwitch、Docker及其生态圈技术，如Kubernetes、Flocker等Docker相关开源项目。Email:&nbsp;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#121;&#97;&#110;&#103;&#122;&#104;&#97;&#110;&#103;&#120;&#105;&#97;&#110;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">yangzhangxian@gmail.com</a></p><h2>7. 参考资料</h2><ol style="margin: 10px 0px 10px 10px; padding: 0px 0px 0px 20px; border: 0px; width: 549px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; line-height: 25.2px; background-color: #ffffff;"><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;"><a href="https://github.com/GoogleCloudPlatform/kubernetes/tree/master/docs" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">https://github.com/GoogleCloudPlatform/kubernetes/tree/master/docs</a></li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;"><a href="http://www.slideshare.net/rajdeep" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">http://www.slideshare.net/rajdeep</a></li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;"><a href="http://www.docker.com/" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">http://www.docker.com</a></li></ol><hr style="margin: 0px; border: 0px; padding: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; line-height: 25.2px; background-color: #ffffff;" /><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">感谢<a href="http://www.infoq.com/cn/author/%E9%83%AD%E8%95%BE" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">郭蕾</a>对本文的策划和审校。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">给InfoQ中文站投稿或者参与内容翻译工作，请邮件至<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#101;&#100;&#105;&#116;&#111;&#114;&#115;&#64;&#99;&#110;&#46;&#105;&#110;&#102;&#111;&#113;&#46;&#99;&#111;&#109;" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">editors@cn.infoq.com</a>。也欢迎大家通过新浪微博（<a href="http://www.weibo.com/infoqchina" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@InfoQ</a>）或者腾讯微博（<a href="http://t.qq.com/infoqchina" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@InfoQ</a>）关注我们，并与我们的编辑和其他读者朋友交流。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><div style="margin: 0px 0px 5px; border: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; line-height: 25.2px; background-color: #ffffff;"><span style="margin: 0px; border: 0px; padding: 0px; font-weight: 600;">【<a href="http://2016.qconbeijing.com/?utm_source=article&amp;utm_medium=infoq&amp;utm_campaign=textads" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">QCon北京2016</a>】近日，极客邦科技经常被热门大片儿《QCon的后裔》攻陷，不少Q迷们都直呼膜拜美国硅谷 Airbnb 美女工程师朱赟的&#8220;撩汉&#8221;技能，女神已放话要美美的来QCon啦！男神阿里巴巴资深总监庄卓然也将在此邂逅。4月21~23日，3天的约会，等你来见证。再不行动，神都帮不了你了。<a target="_blank" href="http://2016.qconbeijing.com/schedule?utm_source=infoq&amp;utm_medium=textads" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">约约约</a>。</span></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/430213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-04-23 11:14 <a href="http://www.blogjava.net/xiaomage234/archive/2016/04/23/430213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访 </title><link>http://www.blogjava.net/xiaomage234/archive/2016/03/24/429793.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 24 Mar 2016 05:21:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/03/24/429793.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/429793.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/03/24/429793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/429793.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/429793.html</trackback:ping><description><![CDATA[<div id="news_content" style="line-height: 1.8em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo是阿里巴巴内部的SOA服务化治理方案的核心框架，每天为2000+ 个服务提供3,000,000,000+ 次访问量支持，并被广泛应用于阿里巴巴集团的各成员站点。Dubbo自2011年开源后，已被许多非阿里系公司使用。&nbsp;<br /><br />项目主页：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Home-zh.htm" style="color: #006699;">http://alibaba.github.io/dubbo-doc-static/Home-zh.htm</a>&nbsp;<br /><br />为了使大家对该框架有一个深入的了解，本期我们采访了Dubbo团队主要开发人员之一<a target="_blank" href="http://javatar.iteye.com/" style="color: #006699;">梁飞</a>。&nbsp;<br /><br /><strong>ITeye期待并致力于为国内优秀的开源项目提供一个免费的推广平台，如果你和你的团队希望将自己的开源项目介绍给更多的开发者，或者你希望我们对哪些开源项目进行专访，请告诉我们，发站内短信给<a target="_blank" href="http://webmaster.iteye.com/" style="color: #006699;">ITeye管理员</a>或者发邮件到webmaster@iteye.com即可。</strong></div><div id="interview_menu" style="border: 1px solid #cccccc; margin: 10px; padding: 5px; width: 300px; font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5f5f5;"><h4>目 录&nbsp;<a href="http://www.iteye.com/magazines/103#" title="隐藏/显示目录" style="color: #006699; text-decoration: none;"><small>[ - ]</small></a></h4><ol style="font-size: 1em; line-height: 1.4em; margin: 0px 0px 1.5em; padding: 0px;"><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#241" style="color: #006699; text-decoration: none;">先来个自我介绍吧！</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#242" style="color: #006699; text-decoration: none;">Dubbo是什么？能做什么？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#243" style="color: #006699; text-decoration: none;">Dubbo适用于哪些场景？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#244" style="color: #006699; text-decoration: none;">Dubbo的设计思路是什么？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#245" style="color: #006699; text-decoration: none;">Dubbo的需求和依赖情况？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#246" style="color: #006699; text-decoration: none;">Dubbo的性能如何？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#248" style="color: #006699; text-decoration: none;">和淘宝HSF相比，Dubbo的特点是什么？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#247" style="color: #006699; text-decoration: none;">Dubbo在安全机制方面是如何解决的？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#249" style="color: #006699; text-decoration: none;">Dubbo在阿里巴巴内部以及外部的应用情况？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#250" style="color: #006699; text-decoration: none;">在分布式事务、多语言支持方面，Dubbo的计划是什么？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#251" style="color: #006699; text-decoration: none;">Dubbo采用的开源协议？商业应用应该注意哪些事项？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#252" style="color: #006699; text-decoration: none;">Dubbo开发团队情况？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#253" style="color: #006699; text-decoration: none;">其他开发者如何参与？可以做哪些工作？</a></li><li style="font-size: 1em; margin: 0px 0px 0.25em 30px; padding: 0px;"><a href="http://www.iteye.com/magazines/103#254" style="color: #006699; text-decoration: none;">Dubbo未来的发展计划？</a></li></ol></div><h2>先来个自我介绍吧！<span style="float: right; padding: 0px 0px 5px 5px;"><a name="241" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">我叫梁飞，花名虚极，之前负责Dubbo服务框架，现已调到天猫。&nbsp;<br /><br />我的博客：<a target="_blank" href="http://javatar.iteye.com/" style="color: #006699; text-decoration: none;">http://javatar.iteye.com</a></div><h2>Dubbo是什么？能做什么？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="242" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo是一个分布式服务框架，以及SOA治理方案。其功能主要包括：高性能NIO通讯及多协议集成，服务动态寻址与路由，软负载均衡与容错，依赖分析与降级等。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Home-zh.htm" style="color: #006699; text-decoration: none;">http://alibaba.github.io/dubbo-doc-static/Home-zh.htm</a></div><h2>Dubbo适用于哪些场景？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="243" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">当网站变大后，不可避免的需要拆分应用进行服务化，以提高开发效率，调优性能，节省关键竞争资源等。&nbsp;<br /><br />当服务越来越多时，服务的URL地址信息就会爆炸式增长，配置管理变得非常困难，F5硬件负载均衡器的单点压力也越来越大。&nbsp;<br /><br />当进一步发展，服务间依赖关系变得错踪复杂，甚至分不清哪个应用要在哪个应用之前启动，架构师都不能完整的描述应用的架构关系。&nbsp;<br /><br />接着，服务的调用量越来越大，服务的容量问题就暴露出来，这个服务需要多少机器支撑？什么时候该加机器？等等&#8230;&#8230;&nbsp;<br /><br />在遇到这些问题时，都可以用Dubbo来解决。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm#UserGuide-zh-%E5%85%A5%E9%97%A8" style="color: #006699; text-decoration: none;">Dubbo的背景及需求</a></div><h2>Dubbo的设计思路是什么？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="244" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">该框架具有极高的扩展性，采用微核+插件体系，并且文档齐全，很方便二次开发，适应性极强。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Developer+Guide-zh.htm#DeveloperGuide-zh-%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1" style="color: #006699; text-decoration: none;">开发者指南 - 框架设计</a></div><h2>Dubbo的需求和依赖情况？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="245" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo运行JDK1.5之上，缺省依赖javassist、netty、spring等包，但不是必须依赖，通过配置Dubbo可不依赖任何三方库运行。&nbsp;<br /><br />可参见：<a target="_blank" href="http://code.alibabatech.com/wiki/display/dubbo/User+Guide#UserGuide-Dependency" style="color: #006699; text-decoration: none;">用户指南 - 依赖</a></div><h2>Dubbo的性能如何？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="246" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo通过长连接减少握手，通过NIO及线程池在单连接上并发拼包处理消息，通过二进制流压缩数据，比常规HTTP等短连接协议更快。在阿里巴巴内部，每天支撑2000多个服务，30多亿访问量，最大单机支撑每天近1亿访问量。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm#UserGuide-zh-%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95%E6%8A%A5%E5%91%8A" style="color: #006699; text-decoration: none;">Dubbo性能测试报告</a></div><h2>和淘宝HSF相比，Dubbo的特点是什么？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="248" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">1.&nbsp;&nbsp;<strong>Dubbo比HSF的部署方式更轻量</strong>，HSF要求使用指定的JBoss等容器，还需要在JBoss等容器中加入sar包扩展，对用户运行环境的侵入性大，如果你要运行在Weblogic或Websphere等其它容器上，需要自行扩展容器以兼容HSF的ClassLoader加载，而Dubbo没有任何要求，可运行在任何Java环境中。&nbsp;<br /><br />2.&nbsp;&nbsp;<strong>Dubbo比HSF的扩展性更好，很方便二次开发</strong>，一个框架不可能覆盖所有需求，Dubbo始终保持平等对待第三方理念，即所有功能，都可以在不修改Dubbo原生代码的情况下，在外围扩展，包括Dubbo自己内置的功能，也和第三方一样，是通过扩展的方式实现的，而HSF如果你要加功能或替换某部分实现是很困难的，比如支付宝和淘宝用的就是不同的HSF分支，因为加功能时改了核心代码，不得不拷一个分支单独发展，HSF现阶段就算开源出来，也很难复用，除非对架构重写。&nbsp;<br /><br />3.&nbsp;&nbsp;<strong>HSF依赖比较多内部系统</strong>，比如配置中心，通知中心，监控中心，单点登录等等，如果要开源还需要做很多剥离工作，而Dubbo为每个系统的集成都留出了扩展点，并已梳理干清所有依赖，同时为开源社区提供了替代方案，用户可以直接使用。&nbsp;<br /><br />4.&nbsp;&nbsp;<strong>Dubbo比HSF的功能更多</strong>，除了ClassLoader隔离，Dubbo基本上是HSF的超集，Dubbo也支持更多协议，更多注册中心的集成，以适应更多的网站架构。</div><h2>Dubbo在安全机制方面是如何解决的？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="247" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo主要针对内部服务，对外的服务，阿里有开放平台来处理安全和流控，所以Dubbo在安全方面实现的功能较少，基本上只防君子不防小人，只防止误调用。&nbsp;<br /><br />Dubbo通过Token令牌防止用户绕过注册中心直连，然后在注册中心上管理授权。Dubbo还提供服务黑白名单，来控制服务所允许的调用方。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm#UserGuide-zh-%E4%BB%A4%E7%89%8C%E9%AA%8C%E8%AF%81" style="color: #006699; text-decoration: none;">Dubbo的令牌验证</a></div><h2>Dubbo在阿里巴巴内部以及外部的应用情况？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="249" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">在阿里内部，除淘系以外的其它阿里子公司，都在使用Dubbo，包括：中文主站，国际主站，AliExpress，阿里云，阿里金融，阿里学院，良无限，来往等等。&nbsp;<br /><br />开源后，已被：去哪儿，京东，吉利汽车，方正证劵，海尔，焦点科技，中润四方，华新水泥，海康威视，等公司广泛使用，并不停的有新公司加入，社区讨论及贡献活跃，得到用户很高的评价。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Community-zh.htm#Community-zh-%E5%B7%B2%E7%9F%A5%E7%94%A8%E6%88%B7" style="color: #006699; text-decoration: none;">Dubbo的已知用户</a></div><h2>在分布式事务、多语言支持方面，Dubbo的计划是什么？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="250" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">分布式事务可能暂不会支持，因为如果只是支持简单的XA/JTA两阶段提交事务，实用性并不强。用户可以自行实现业务补偿的事件，或更复杂的分布式事务，Dubbo有很多扩展点可以集成。&nbsp;<br /><br />在多语言方面，Dubbo实现了C++版本，但在内部使用面极窄，没有得到很强的验证，并且C++开发资源紧张，没有精力准备C++开源事项。</div><h2>Dubbo采用的开源协议？商业应用应该注意哪些事项？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="251" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo采用Apache License 2.0开源协议，它是一个商业友好的协议，你可以免费用于非开源的商业软件中。&nbsp;<br /><br />你可以对它进行改造和二次发布，只要求保留阿里的著作权，并在再发布时保留原始许可声明。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Download-zh.htm#Download-zh-%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF" style="color: #006699; text-decoration: none;">Dubbo的开源许可证</a></div><h2>Dubbo开发团队情况？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="252" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo共有六个开发人员参与开发和测试，每一个开发人员都是很有经验，团队合作很默契，开发过程也很有节奏，有完善质量保障流程。团队组成：&nbsp;<br /><br /><ul style="margin: 0px 0px 1.5em; padding: 0px;"><li style="margin: 0px 0px 0.25em 30px; padding: 0px;">梁飞 （开发人员/产品管理）</li><li style="margin: 0px 0px 0.25em 30px; padding: 0px;">刘昊旻 （开发人员/过程管理）</li><li style="margin: 0px 0px 0.25em 30px; padding: 0px;">刘超 （开发人员/用户支持）</li><li style="margin: 0px 0px 0.25em 30px; padding: 0px;">李鼎 （开发人员/用户支持）</li><li style="margin: 0px 0px 0.25em 30px; padding: 0px;">陈雷 （开发人员/质量保障）</li><li style="margin: 0px 0px 0.25em 30px; padding: 0px;">闾刚 （开发人员/开源运维）</li></ul><div><img src="http://dl.iteye.com/upload/attachment/0076/4588/a376775f-1550-3746-aad6-808c5989d96e.jpg" style="border: 0px;"  alt="" />&nbsp;<br />从左至右：刘超，梁飞，闾刚，陈雷，刘昊旻，李鼎</div><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Community-zh.htm#Community-zh-%E5%9B%A2%E9%98%9F" style="color: #006699; text-decoration: none;">Dubbo的团队成员</a></div><h2>其他开发者如何参与？可以做哪些工作？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="253" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">开发者可以在Github上fork分支，然后将修改push过来，我们审核并测试后，会合并到主干中。&nbsp;<br /><br />Github地址：<a target="_blank" href="https://github.com/alibaba/dubbo" style="color: #006699; text-decoration: none;">https://github.com/alibaba/dubbo</a>&nbsp;<br /><br />开发者可以在JIRA上认领小的BUG修复，也可以在开发者指南页面领取大的功能模块。&nbsp;<br /><br />JIRA：<a target="_blank" href="http://code.alibabatech.com/jira/browse/DUBBO" style="color: #006699; text-decoration: none;">http://code.alibabatech.com/jira/browse/DUBBO</a>（暂不可用）&nbsp;<br /><br />开发者指南：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Developer+Guide-zh.htm" style="color: #006699; text-decoration: none;">http://alibaba.github.io/dubbo-doc-static/Developer+Guide-zh.htm</a></div><h2>Dubbo未来的发展计划？<span style="float: right; padding: 0px 0px 5px 5px;"><a name="254" href="http://www.iteye.com/magazines/103#top" style="color: #006699; text-decoration: none;"><img alt="Top" src="http://www.iteye.com/images/wiki/top.gif?1448702469" style="border: 0px; margin-right: 8px;" /></a></span></h2><div style="padding: 5px 8px; margin-bottom: 12px; line-height: 1.6em; font-family: Helvetica, Tahoma, Arial, sans-serif; background-color: #ffffff;">Dubbo的RPC框架已基本稳定，未来的重心会放在服务治理上，包括架构分析、监控统计、降级控制、流程协作等等。&nbsp;<br /><br />可参见：<a target="_blank" href="http://alibaba.github.io/dubbo-doc-static/Roadmap-zh.htm" style="color: #006699; text-decoration: none;">http://alibaba.github.io/dubbo-doc-static/Roadmap-zh.htm</a></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/429793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-03-24 13:21 <a href="http://www.blogjava.net/xiaomage234/archive/2016/03/24/429793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>快的打车架构实践</title><link>http://www.blogjava.net/xiaomage234/archive/2016/03/11/429621.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 11 Mar 2016 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/03/11/429621.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/429621.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/03/11/429621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/429621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/429621.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 快的打车从2013年年底到2014年下半年，系统访问量迅速膨胀，很多复杂的问题要在短时间内解决，且不能影响线上业务，这是比较大的挑战，本文将会阐述快的打车架构演变过程遇到的一些有代表性的问题和解决方案。LBS的瓶颈和方案先看看基本的系统模型，如图1所示。图1 系统模型示意图司机每隔几秒钟上报一次经纬度，存储在MongoDB里；乘客发单时，通过MongoDB圈选出附近司机；将订单通过长连接服务推送给...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2016/03/11/429621.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/429621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-03-11 14:57 <a href="http://www.blogjava.net/xiaomage234/archive/2016/03/11/429621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决dubbo问题：forbid consumer 【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2016/02/29/429480.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 29 Feb 2016 08:24:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/02/29/429480.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/429480.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/02/29/429480.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/429480.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/429480.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 20px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; background-color: #ffffff;">from:<span style="font-family: verdana, 'courier new'; line-height: 21px;">http://www.jameswxx.com/%E4%B8%AD%E9%97%B4%E4%BB%B6/%E8%A7%A3%E5%86%B3dubbo%E9%97%AE%E9%A2%98%EF%BC%9Aforbid-consumer/</span></p><p style="margin: 0px 0px 20px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; background-color: #ffffff;"><br />线下环境经常出现类似这种异常：</p><blockquote style="margin: 0px 0px 24px; padding: 24px; border-width: 0px 4px; border-right-color: #d6d6d6; border-left-color: #d6d6d6; vertical-align: baseline; quotes: none; border-radius: 14px; font-style: italic; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-image: initial; background-color: #fafafa;"><div style="margin: 0px; border: 0px; vertical-align: baseline;">com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.0.53.69 access service com.kuaidadi.op.api.pay.service.PayChannelConfigRemoteService from registry 10.0.50.150:2181 use dubbo version 2.5.3, Please check registry access list (whitelist/blacklist).</div></blockquote><div style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;">大致意思是当前调用者被禁止访问某个服务，请检查下注册中心访问列表，还有黑名单和白名单。</div><div style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"></div><div style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"></div><div style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;">其实线下环境根本没有对服务做白名单和黑名单机制，因为线下环境给开发人员的账号是guest，没有权限做黑白名单。今天有好几个人问我这个问题，我仔细看了源码，找出了根源所在。</div><div style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;">根据异常栈，抛出这个异常的代码在RegistryDirectory的第579行，如下：</div><blockquote style="margin: 0px 0px 24px; padding: 24px; border-width: 0px 4px; border-right-color: #d6d6d6; border-left-color: #d6d6d6; vertical-align: baseline; quotes: none; border-radius: 14px; font-style: italic; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-image: initial; background-color: #fafafa;"><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">public</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">List&lt;Invoker&lt;T&gt;&gt; doList(Invocation invocation) {</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;">&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">(</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">forbidden</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">) {</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">throw</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">RpcException(RpcException.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">FORBIDDEN_EXCEPTION</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">,</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #2a00ff; font-family: Consolas;">&#8221;&nbsp;Forbid consumer&nbsp;&#8220;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">+&nbsp; NetUtils.&nbsp;<em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">getLocalHost</em>() +</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #2a00ff; font-family: Consolas;">&#8221; access service &#8220;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">+ &nbsp; &nbsp; &nbsp; &nbsp;getInterface().getName() +</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #2a00ff; font-family: Consolas;">&#8221; from registry &#8220;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">+ getUrl().getAddress() +</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #2a00ff; font-family: Consolas;">&#8221; use dubbo version &#8220;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">+ Version.<em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">getVersion</em>() +</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #2a00ff; font-family: Consolas;">&#8220;, Please check registry access list (whitelist/blacklist).&#8221;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">);</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">}</span></div></blockquote><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">如果forbidden变量为true，则抛出该异常。forbidden变量默认为false，那么什么时候变成true了呢？看</span>RegistryDirectory的这段代码：</div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: Ubuntu, Helvetica, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"><blockquote style="margin: 0px 0px 24px; padding: 24px; border-width: 0px 4px; border-right-color: #d6d6d6; border-left-color: #d6d6d6; vertical-align: baseline; quotes: none; border-radius: 14px; font-style: italic; background-image: initial; background-color: #fafafa;"><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">private</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">void</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">refreshInvoker(List&lt;URL&gt; invokerUrls){</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">(invokerUrls !=</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">null</strong></span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&amp;&amp; invokerUrls.size() == 1 &amp;&amp; invokerUrls.get(0) !=</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">null&nbsp;</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&amp;&amp; Constants.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">EMPTY_PROTOCOL</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">.equals(invokerUrls.get(0).getProtocol())) {</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">forbidden</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">=</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">true</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #3f7f5f; font-family: Consolas;">// 禁止访问</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">methodInvokerMap</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">=</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">null</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #3f7f5f; font-family: Consolas;">// 置空列表</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; destroyAllInvokers();</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #3f7f5f; font-family: Consolas;">// 关闭所有Invoker</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp; &nbsp;}</span></div></blockquote><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">意思是如果</span>invokerUrls的size为1，并且url的协议头是<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">Constants.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">EMPTY_PROTOCOL时，则设置forbidden为false，</em></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">Constants.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">EMPTY_PROTOCOL的值是empty。</em></span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;</em></span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;</em></span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><div style="margin: 0px; border: 0px; vertical-align: baseline;">refreshInvoker方法什么时候被调用呢？当某个服务的provider有变化时就会被调用，例如zookeeper上某个服务的provider目录里的内容发生变化，则zk监听器会被触发，由于provider的数量会发生变化，例如有一个新的provider启动了，有一个provider下线了，所以必须刷新本地的对provider的连接，具体逻辑就在refreshInvoker方法里，这个方法的调用栈如下：</div><div style="margin: 0px; border: 0px; vertical-align: baseline;"></div></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><a href="http://www.jameswxx.com/wp-content/uploads/2015/06/image_1.png" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #0b91ea; text-decoration: none;"><img wp-image-245=""  size-full"="" src="http://www.jameswxx.com/wp-content/uploads/2015/06/image_1.png" alt="image_1" width="1066" height="185" style="margin: 0px 0px 10px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; height: auto; box-shadow: rgba(0, 0, 0, 0.0980392) 0px 1px 4px;" /></a></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;">可以确定的是，zookeeper推送的URL的protocol部分不可能无缘无故变成了empty，肯定是由某个地方更改了，于是看一下<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">Constants.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">EMPTY_PROTOCOL到底有哪些地方调用了，如下：</em></span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><a href="http://www.jameswxx.com/wp-content/uploads/2015/06/image_2.png" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #0b91ea; text-decoration: none;"><img wp-image-247=""  size-full"="" src="http://www.jameswxx.com/wp-content/uploads/2015/06/image_2.png" alt="image_2" width="948" height="309" style="margin: 0px 0px 10px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; height: auto; box-shadow: rgba(0, 0, 0, 0.0980392) 0px 1px 4px;" /></a></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;">见图中红色圈圈部分，当zookeeper初次订阅或者订阅的信息有变更时，都会触发toUrlsChanged方法，看看这个方法内部都做了什么，完整代码如下：</div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><div style="margin: 0px; border: 0px; vertical-align: baseline;"><blockquote style="margin: 0px 0px 24px; padding: 24px; border-width: 0px 4px; border-right-color: #d6d6d6; border-left-color: #d6d6d6; vertical-align: baseline; quotes: none; border-radius: 14px; font-style: italic; background-image: initial; background-color: #fafafa;"><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp; &nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;">&nbsp;<strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">private</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;List&lt;URL&gt; toUrlsWithEmpty(URL consumer, String path, List&lt;String&gt; providers) {</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;URL&gt; urls = toUrlsWithoutEmpty(consumer, providers);</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;(urls ==&nbsp;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">null</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;|| urls.isEmpty()) {</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">int</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;i = path.lastIndexOf(</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #2a00ff; font-family: Consolas;">&#8216;/&#8217;</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">);</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;String category = i &lt; 0 ? path : path.substring(i + 1);</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;URL empty = consumer.setProtocol(Constants.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">EMPTY_PROTOCOL</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">).addParameter(Constants.</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000c0; font-family: Consolas;">&nbsp;<em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">CATEGORY_KEY</em></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">, category);</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; urls.add(empty);</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #7f0055; font-family: Consolas;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">return</strong></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;urls;</span></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas;">&nbsp;&nbsp;&nbsp; }</span></div></blockquote></div></div><div align="left" style="margin: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: large; vertical-align: baseline; font-family: Consolas;">可见如果</span>toUrlsWithoutEmpty的结果是空或者size为0，则强制返回一个protocol为empty的url，看来源头就在这里了。传入的List&lt;String&gt; providers实际上就是最新的服务提供者信息，当某个服务没有任何provider时，providers就变为一个size为o的List了，导致返回一个协议头为empty的url，进而导致forbidden为true，屏蔽了consumer调用。</div></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/429480.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-02-29 16:24 <a href="http://www.blogjava.net/xiaomage234/archive/2016/02/29/429480.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Dubbo学习过程、使用经验分享及实现原理简单介绍</title><link>http://www.blogjava.net/xiaomage234/archive/2016/01/26/429219.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 26 Jan 2016 09:58:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/01/26/429219.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/429219.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/01/26/429219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/429219.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/429219.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文见：http://blog.csdn.net/hzzhoushaoyu/article/details/43273099一、前言部门去年年中开始各种改造，第一步是模块服务化，这边初选dubbo试用在一些非重要模块上，慢慢引入到一些稍微重要的功能上，半年时间，学习过程及线上使用遇到的些问题在此总结下。整理这篇文章差不多花了两天半时间，请尊重劳动成果，如转载请注明出处http://blog.csd...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2016/01/26/429219.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/429219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-01-26 17:58 <a href="http://www.blogjava.net/xiaomage234/archive/2016/01/26/429219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解读2015之大数据篇：大数据的黄金时代</title><link>http://www.blogjava.net/xiaomage234/archive/2016/01/15/429064.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 15 Jan 2016 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/01/15/429064.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/429064.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/01/15/429064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/429064.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/429064.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">编者按</span></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2015年，整个IT技术领域发生了许多深刻而又复杂的变化，InfoQ策划了&#8220;解读2015&#8221;年终技术盘点系列文章，希望能够给读者清晰地梳理出技术领域在这一年的发展变化，回顾过去，继续前行。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">本文是大数据解读篇，在这篇文章里我们将回顾2015展望2016，看看过去的一年里广受关注的技术有哪些进展，了解下数据科学家这个职业的火热。&nbsp;在关键技术进展部分我们在大数据生态圈众多技术中选取了Hadoop、Spark、Elasticsearch和Apache&nbsp;Kylin四个点，分别请了四位专家：Hulu的董西成、明略数据的梁堰波、<span style="margin: 0px; border: 0px; padding: 0px; line-height: 20.8px;">精硕科技</span>的卢亿雷、eBay的韩卿，来为大家解读2015里的进展。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><div visible=""  stacked"="" style="margin: 20px 0px 20px 20px; border: 1px solid #dfdfdf; float: right; width: 315px; overflow: hidden; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><div only1=""  fullwidth"="" style="margin: 0px; border-width: 0px 1px 0px 0px; border-right-style: dotted; border-right-color: #dfdfdf; float: left; width: 315px; background: none 50% 0% repeat-y #f7f7f7;"><div sponsored=""  only2"="" style="margin: 0px; padding-top: 10px; padding-left: 10px; border: 0px; float: left; width: 315px; min-height: 150px;"><p style="margin: 0px 0px 8px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: both; width: 315px; font-weight: 600;">相关厂商内容</p><div style="margin: 0px; padding-top: 5px; border: 0px; float: left; width: 311.84375px; min-height: 100px;"><h3><a href="http://www.infoq.com/infoq/url.action?i=8955&amp;t=f" target="_blank" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">Twitter Messaging的架构演化之路</a></h3><h3><a href="http://www.infoq.com/infoq/url.action?i=8956&amp;t=f" target="_blank" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">业务核心架构，根据业务需求设计合理架构</a></h3><h3><a href="http://www.infoq.com/infoq/url.action?i=8957&amp;t=f" target="_blank" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">QCon北京2016大会，4月21-23日，与您相约北京国际会议中心，2月21前报名享8折优惠！</a></h3><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px;"></div></div></div></div><div only2"="" style="margin: 0px; padding-top: 10px; border: 0px; float: left; width: 315px; clear: left;"><p style="margin: 0px 0px 8px; padding: 0px 0px 0px 10px; border: 0px; float: none; line-height: 1.8; clear: both; width: 315px; font-weight: 600;">相关赞助商</p><a href="http://www.infoq.com/infoq/url.action?i=8959&amp;t=f" target="_blank" style="margin: 0px; border: 0px; padding: 0px; color: #000000 !important; outline: none !important;"><img src="http://cdn.infoqstatic.com/statics_s2_20160105-0313u5/resource/sponsorship/featuredcategory/6555/QConSHlogo.jpg" border="0" style="border: 0px; margin: 0px 0px 5px 5px; padding: 0px; float: right;" alt="" /></a><div style="margin: 0px; padding-right: 10px; padding-left: 10px; border: 0px;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 295px;"><span style="margin: 0px; border: 0px; padding: 0px; line-height: 20.8px;">QCon北京2016大会，4月21-23日，北京&#183;国际会议中心，<a href="http://www.infoq.com/infoq/url.action?i=8958&amp;t=f" target="_blank" style="margin: 0px; border: 0px; padding: 0px 0px 2px; width: auto; display: inline; clear: both; text-decoration: none !important; color: #286ab2 !important; outline: none !important;">精彩内容</a>邀您参与！</span></p></div></div><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px;"></div></div><h2>回顾2015年的关键技术进展：</h2><h3><span style="margin: 0px; border: 0px; padding: 0px;">Hadoop：</span></h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Hadoop作为大数据平台中最基础与重要的系统，在2015年提高稳定性的同时，发布了多个重要功能与特性，这使得Hadoop朝着多类型存储介质和异构集群的方向迈进了一大步。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">HDFS&nbsp;</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">HDFS&nbsp;之前是一个以磁盘单存储介质为主的分布式文件系统。但随着近几年新存储介质的兴起，支持多存储介质早就提上了日程。如今，HDFS&nbsp;已经对多存储介质有了良好的支持，包括&nbsp;Disk、Memory&nbsp;和&nbsp;SSD&nbsp;等，对异构存储介质的支持，使得&nbsp;HDFS&nbsp;朝着异构混合存储方向发展。目前HDFS支持的存储介质如下：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">ARCHIVE：高存储密度但耗电较少的存储介质，通常用来存储冷数据。</p><div id="lowerFullwidthVCR" style="margin: 0px; border: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">DISK：磁盘介质，这是HDFS最早支持的存储介质。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">SSD：固态硬盘，是一种新型存储介质，目前被不少互联网公司使用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">RAM_DISK&nbsp;：数据被写入内存中，同时会往该存储介质中再（异步）写一份。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">YARN</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">YARN作为一个分布式数据操作系统，主要作用是资源管理和资源调度。在过去一年，YARN新增了包括基于标签的调度、对长服务的支持、对&nbsp;Docker&nbsp;的支持等多项重大功能。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">&nbsp;基于标签的调度，使得&nbsp;YARN&nbsp;能够更好地支持异构集群调度。它的基本思想是，通过打标签的方式为不同的节点赋予不同的属性，这样，一个大的Hadoop集群按照节点类型被分成了若干个逻辑上相互独立（可能交叉）的集群。这种集群跟物理上独立的集群很不一样，用户可以很容易地通过动态调整&nbsp;label，实现不同类型节点数目的增减，这具有很好的灵活性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">对长服务的支持，使得YARN逐渐变为一个通用资源管理和调度系统。目前，YARN既支持像类似&nbsp;MapReduce，Spark&nbsp;的短作业，也支持类似&nbsp;Web&nbsp;Service，MySQL&nbsp;这样的长服务。&nbsp;支持长服务是非常难的一件事情，YARN&nbsp;需要解决以下问题：服务注册、日志滚动、ResourceManager&nbsp;HA、NodeManager&nbsp;HA（NM&nbsp;重启过程中，不影响&nbsp;Container）和&nbsp;ApplicationMaster&nbsp;永不停止，重启后接管之前的&nbsp;Container。截止2.7.0版本，以上问题都已经得到了比较完整的解决。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">对Docker的支持，使得YARN能够为上层应用提供更好的打包、隔离和运行方式。YARN通过引入一种新的ContainerExecutor，即DockerContainerExecutor，实现了对Docker的支持，但目前仍然是alpha版本，不建议在生产环境中使用。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">HBase</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">在&nbsp;2015&nbsp;年，HBase&nbsp;迎来了一个里程碑&#8212;&#8212;HBase&nbsp;1.0&nbsp;release，这也代表着&nbsp;HBase&nbsp;走向了稳定。&nbsp;HBase新增特性包括：更加清晰的接口定义，多&nbsp;Region&nbsp;副本以支持高可用读，Family&nbsp;粒度的&nbsp;Flush以及RPC&nbsp;读写队列分离等。</p><h3><span style="margin: 0px; border: 0px; padding: 0px;">Spark：</span></h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">2015年的Spark发展很快，JIRA数目和PR数目都突破了10000，contributors数目超过了1000，可以说是目前最火的开源大数据项目。这一年Spark发布了多个版本，每个版本都有一些亮点：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2014年12月，<a href="http://www.infoq.com/cn/news/2014/12/spark-1.2-release-mllib-sql" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Spark&nbsp;1.2发布</a>引入ML&nbsp;pipeline作为机器学习的接口。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年3月，<a href="http://www.infoq.com/cn/news/2015/03/apache-1.3-released" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Spark&nbsp;1.3发布</a>引入了DataFrame作为Spark的一个核心组件。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年6月，Spark&nbsp;1.4发布引入R语言作为Spark的接口。R语言接口在问世一个多月之后的调查中就有18%的用户使用。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年9月，<a href="http://www.infoq.com/cn/news/2015/09/apache-spark-1-5" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Spark&nbsp;1.5发布</a>。Tungsten项目第一阶段的产出合并入DataFrame的执行后端，DataFrame的执行效率得到大幅提升。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2016年1月，<a href="http://www.infoq.com/cn/news/2016/01/spark-16-release" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Spark&nbsp;1.6发布</a>引入Dataset接口。</li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Spark目前支持四种语言的接口，除了上面提到的R语言的使用率以外，Python的使用率也有很大提升，从2014年的38%提升到2015年的58%；而Scala接口的使用率有所下降，从84%下降到71%。同时Spark的部署环境也有所变化，51%的部署在公有云上，48%&nbsp;使用standalone方式部署，而在YARN上的只有40%了。可见Spark已经超越Hadoop，形成了自己的生态系统。而在形成Spark生态系统中起到关键作用的一个feature就是外部数据源支持，Spark可以接入各种数据源的数据，然后把数据导入Spark中进行计算、分析、挖掘和机器学习，然后可以把结果在写出到各种各样的数据源。到目前为止Spark已经支持非常多的外部数据源，像Parquet/JSON/CSV/JDBC/ORC/HBase/Cassandra/Mongodb等等。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">上面这些调查数据来自美国，中国的情况有所区别，但是还是有一定的借鉴意义的。国内的Spark应用也越来越多：腾讯的Spark规模到了8000+节点，日处理数据1PB+。阿里巴巴运行着目前最长时间的Spark&nbsp;Job：1PB+数据规模的Spark&nbsp;Job长达1周的时间。百度的硅谷研究院也在探索Spark+Tachyon的应用场景。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Spark&nbsp;MLlib的ALS算法已经在很多互联网公司用于其推荐系统中。基本上主流的互联网公司都已经部署了Spark平台并运行了自己的业务。上面说的更多的互联网的应用，实际上Spark的应用场景有很多。在Databricks公司的调查中显示主要应用依次是：商务智能、数据仓库、推荐系统、日志处理、欺诈检测等。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">除了互联网公司以外，传统IT企业也把Spark作为其产品的一个重要组成。IBM在今年6月的Spark&nbsp;summit期间宣布重点支持Spark这个开源项目，同时还开源了自己的机器学习系统SystemML并推进其与Spark的更好合作。美国大数据巨头Cloudera，Hortonworks和MapR都表示Spark是其大数据整体解决方案的核心产品。可以预见Spark是未来若干年最火的大数据项目。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">在深度学习方面2015年可谓非常热闹，如Google开源其第二代机器学习系统TensorFlow，Facebook开源Torch和人工智能硬件服务器Big Sur等等。Spark社区也不甘落后，在1.5版本中发布了一个神经网络分类器MultiplayerPerceptronClassifier作为其深度学习的雏形。虽然这个模型还有很多地方需要优化，大家不妨尝试下，毕竟它是唯一一个基于通用计算引擎的分布式深度学习系统。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">除了现在非常火的深度学习，在传统统计和机器学习领域，Spark这一年也有非常大的变化，包括GLM的全面支持，SparkR&nbsp;GLM的支持，A/B&nbsp;test，以及像WeightesLeastSquares这样的底层优化算法等。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">具体内容可以看梁堰波在InfoQ上的年终回顾：《<a href="http://www.infoq.com/cn/articles/2015-Review-Spark" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">解读2015之Spark篇：新生态系统的形成</span></a>》。</p><h3><span style="margin: 0px; border: 0px; padding: 0px;">Elasticsearch：</span></h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Elasticsearch&nbsp;是一个可伸缩的开源全文搜索和分析引擎。它可以快速地存储、搜索和分析海量数据。Elasticsearch&nbsp;基于成熟的&nbsp;Apache&nbsp;Lucene&nbsp;构建，在设计时就是为大数据而生，能够轻松的进行大规模的横向扩展，以支撑PB级的结构化和非结构化海量数据的处理。Elasticsearch生态圈发展状态良好，整合了众多外围辅助系统，如监控Marvel，分析Logstash，安全Shield等。近年来不断发展受到广泛应用，如Github、StackOverflow、维基百科等，是数据库技术中倍受关注的一匹黑马。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Elasticsearch在今年下半年发布了2.0版本，性能提升不少，主要改变为：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Pipeline&nbsp;Aggregation</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">流式聚合，像管道一样，对聚合的结果进行再次聚合。原来client端需要做的计算工作，下推到ES，简化&nbsp;client代码，更容易构建强大的查询。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Query/Filter&nbsp;合并</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">取消filters，所有的filter语句自动转换为query语句。在上下文语义是query时，进行相关性计算；上下文语&nbsp;义是filter时，简单排除b不匹配的doc，像现在的filter所做的一样。这个重构以为着所有的query执行会以最&nbsp;有效的顺序自动优化。例如，子查询和地理查询会首先执行一个快速的模糊步骤，然后用一个稍慢的精确&nbsp;步骤截断结果。在filter上下文中，cache有意义时，经常使用的语句会被自动缓存。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">可配置的store&nbsp;compression</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">存储的field，例如_source字段，可以使用默认的LZ4算法快速压缩，或者使用DEFLATE算法减少index&nbsp;size。对于日志类的应用尤其有用，旧的索引库在优化前可以切换到best_compression。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Hardening</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Elasticsearch运行于&nbsp;Java&nbsp;Security&nbsp;Manager之下，在安全性上标志着一个巨大的飞跃。Elasticsearch难于探测，黑客在系统上&nbsp;的影响也被严格限制。在索引方面也有加强：&nbsp;indexing请求ack前，doc会被fsync，默认写持久化&nbsp;所有的文件都计算checksum，提前检测文件损坏&nbsp;所有的文件rename操作都是原子的（atomic），避免部分写文件&nbsp;对于系统管理员来讲，一个需求较多的变化是，可以避免一个未配置的node意外加入Elasticsearch集群网络：默认绑&nbsp;定localhost&nbsp;only，&nbsp;multicast也被移除，鼓励使用unicast。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Performance&nbsp;and&nbsp;Resilience</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">除上所述，Elasticsearch和Lucene还有很多小的变化，使其更加稳定可靠，易于配置，例如：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">默认doc&nbsp;value，带来更少的heap&nbsp;usage，filter&nbsp;caching&nbsp;更多使用&nbsp;bitsets&nbsp;type&nbsp;mappings&nbsp;大清理，更安全可靠，无二义性&nbsp;cluster&nbsp;stat&nbsp;使用diff进行快速变化传播，带来更稳定的大规模集群</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Core&nbsp;plugins</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">官方支持的core&nbsp;plugins同时发布，和Elasticsearch核心使用相同的版本号。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Marvel&nbsp;2.0.0&nbsp;free&nbsp;to&nbsp;use&nbsp;in&nbsp;production</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Marvel免费。</p><h3><span style="margin: 0px; border: 0px; padding: 0px;">Apache&nbsp;Kylin：</span></h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Apache&nbsp;Kylin是一个开源的分布式分析引擎，提供Hadoop之上的SQL查询接口及多维分析（OLAP）能力以支持超大规模数据，最初由eBay&nbsp;Inc.&nbsp;开发并贡献至开源社区。最初于2014年10月1日开源，并于同年11月加入Aapche孵化器项目，并在一年后的2015年11月顺利毕业成为Apache顶级项目，是eBay全球贡献至Apache软件基金会（ASF）的第一个项目，也是全部由在中国的华人团队整体贡献至Apache的第一个项目。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">在eBay，已经上线两个生产环境平台，有着诸多的应用，包括用户行为分析、点击分析、商户分析、交易分析等应用，最新的Streaming分析项目也已经上线。目前在eBay平台上最大的单个cube包含了超过1000亿的数据，90%查询响应时间小于1.5秒，95%的查询响应时间小于5秒。同时Apache&nbsp;Kylin在eBay外部也有很多的用户，包括京东、美团、百度地图、网易、唯品会、Expedia、Expotional等很多国内外公司也已经在实际环境中使用起来，把Apache&nbsp;Kylin作为他们大数据分析的基础之一。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">过去的一年多是Apache&nbsp;Kylin发展的重要的一年：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2014年10月1日，Kylin&nbsp;代码在github.com上正式开源</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2014年11月25日，正式加入Apache孵化器并正式启用Apache&nbsp;Kylin作为项目名称</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年6月10日，Apache&nbsp;Kylin&nbsp;v0.7.1-incubating发布，这是加入Apache后的第一个版本，依据Apache的规范作了很多修改，特别是依赖包，license等方面，同时简化了安装，设置等，并同时提供二进制安装包</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年9月6日，Apache&nbsp;Kylin&nbsp;v1.0-incubating正式发布，增强了SQL处理，提升了HBase&nbsp;coprocessor&nbsp;的性能，同时提供了Zeppelin&nbsp;Interpreter等</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年9月16日，Apache&nbsp;Kylin与Spark，Kafka，Storm，H2O，Flink，Elasticsearch，Mesos等一起荣获InfoWorld&nbsp;Bossie&nbsp;Awards&nbsp;2015：最佳开源大数据工具奖，这是业界对Kylin的认可</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年11月18日，Apache&nbsp;Kylin正式毕业成为Apache顶级项目</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年12月15日，Apache&nbsp;Kylin&nbsp;v1.2正式发布，这是升级为顶级项目后的第一个版本，提供了对Excel，PowerBI，Tableau&nbsp;9等的支持，对高基维度增强了支持，修复了多个关键Bug等</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2016年，Apache&nbsp;Kylin将迎来重要的2.x版本，该版本对底层架构和设计作了重大重构，提供可插拔的设计及Lambda架构，同时提供对历史数据查询，Streaming及Realtime查询等，同时在性能，任务管理，UI等各个方面提供增强。</li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">同时，过去一年也是社区发展的重要一年，在过去一年内发展了来自eBay，美团，京东，明略数据，网易等众多committer，社区每天的讨论也是非常热闹。社区提交了很多新特性和Bug修复，包括来自美团的不同HBase写入，来自京东的明细数据查询，来自网易的多Hive源等多个重大特性为Apache&nbsp;Kylin带来了巨大的增强。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">社区合作</span></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">在开源后的一年时间内，Apache&nbsp;Kylin也和其他社区建立了良好的合作关系，Apache&nbsp;Calcite作为Kylin&nbsp;的SQL引擎被深入的整合进来，我们也向Calcite提交了很多改进和修复，Calcite的作者，Julian&nbsp;Hyde也是Kylin的mentor。HBase是Kylin的存储层，在实际运维中，我们碰到过无数问题，从可靠性到性能到其他各个方面，Kylin社区和HBase社区积极合作解决了绝大部分关键问题。另外，现在越来越多的用户考虑使用Apache&nbsp;Zeppelin作为前端查询和展现的工具，为此我们开发了Kylin&nbsp;Interperter并贡献给了Zeppelin，目前可以直接从最新版的Zeppelin代码库中看到这块。同样，我们也和其他各个社区积极合作，包括Spark，Kafka等，为构建和谐的社区氛围和形成良好合作打下了坚实的基础。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">技术发展</span></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">技术上，这一年来Apache&nbsp;Kylin主要在以下几个方面</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Fast&nbsp;Cubing</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">在现在的版本中，Cube的计算依赖MapReduce，并且需要多个步骤的MR&nbsp;Job来完成计算，且MR&nbsp;Job的多少和维度相关，越多的维度会带来更多的MR&nbsp;job。而每一次MR&nbsp;job的启停都需要等待集群调度，并且MR&nbsp;job之间的数据需要多次在HDFS落地和传输，从而导致消耗了大量的集群资源。为此我们引入了一种新的算法：Fast&nbsp;Cubing。一个MapReduce即可完成Cub的计算，测试结果表明整个Cubing的时间可以降低30～50%左右，网络传输可以下降5倍，这在超大规模数据集的计算上带来了客观的性能改进。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Streaming&nbsp;OLAP</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Kylin作为一个预计算系统，不可避免的有着数据刷新延迟的限制，这在大部分用户案例中并不是问题，但随着业务和技术的发展，Streaming甚至Realtime的需求越来越高。2015年Kylin的主要发展都在Streaming&nbsp;OLAP上，为了支持低延迟的数据刷新，从整体的架构和设计上都做了相当大的重新设计，目前已经可以支持从Kafka读取数据并进行聚合计算的能力，同时提供SQL接口为前端客户端提供标准的访问接口，数据延迟已经可以做到分钟级别。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">Spark&nbsp;Cubing</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Spark作为MapReduce的一种替代方案一直在社区中被问及Kylin是否可以支持直接使用Spark来作为计算。为此我们在2015年下半年实现了同样算法的Spark&nbsp;Cubing引擎，目前还在测试中。</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">可插拔架构</span></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">为了更广泛的可扩展性，并支持如上各种新特性，Kylin在2.x的代码中引入了可插拔架构和设计，从而解决了对特定技术的依赖问题。在新的设计中，数据源可以从Hive，SparkSQL等各种SQL&nbsp;on&nbsp;Hadoop技术读取，并支持Kafka；在计算引擎方面，除了MapReduce方面的Fast&nbsp;Cubing外，实现了Spark&nbsp;Cubing，Streaming&nbsp;Cubing等多种计算框架，并为将来其他计算框架留下了扩展接口；在存储上，HBase目前依然是唯一的存储层，但在上层设计中已经很好的进行了抽象，很容易可以扩展到其他Key－Value系统。</p><h2>大数据与机器学习</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">机器学习是数据分析不可缺少的一部分。机器学习被赞誉为大数据分析和商务智能发展的未来，成功的机器学习项目依赖于很多因素，包括选择正确的主题，运行环境，合理的机器学习模型，最重要的是现有的数据，大数据为机器学习提供了很好的用武之地。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">机器学习正很快从一个被很少人关注的技术主题转变为被很多人使用的管理工具。优秀的算法，大数据和高性能的计算资源的条件的满足使得机器学习快速发展，机器学习在今年第一次进入Gartner技术成熟曲线的报告中，并且进入大数据一样的应用期；而机器学习也是报告中第一个出现的技术。2015年是机器学习丰收年，发生了很多令人瞩目的大事。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">各大巨头开源：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年1月，<a href="http://www.infoq.com/cn/news/2015/01/facebook-fbcunn" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Facebook开源</a>前沿深度学习工具&#8220;<a href="http://www.infoq.com/cn/news/2015/01/facebook-open-source-torch" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Torch</a>&#8221;。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年4月，亚马逊启动其机器学习平台Amazon&nbsp;Machine&nbsp;Learning，这是一项全面的托管服务，让开发者能够轻松使用历史数据开发并部署预测模型。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年11月，<a href="http://www.infoq.com/cn/news/2015/11/tensorflow" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">谷歌开源</a>其机器学习平台TensorFlow。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">同一月，<a href="http://www.infoq.com/cn/news/2015/11/tensorflow-vs-dmtk-vs-systemml" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">IBM开源SystemML</a>并成为Apache官方孵化项目。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">同时，微软亚洲研究院将分布式机器学习工具DMTK通过Github开源。DMTK由一个服务于分布式机器学习的框架和一组分布式机器学习算法组成，可将机器学习算法应用到大数据中。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">2015年12月，Facebook开源针对神经网络研究的服务器&#8220;<a href="http://www.infoq.com/cn/news/2015/12/Facebook-BigSur-OpenSource" target="_blank" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Big&nbsp;Sur</a>&#8221;，配有高性能图形处理单元（GPUs），转为深度学习方向设计的芯片。</li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">大公司不仅是用开源社区来增强自己的机器学习工具，而且也会以收购来提升自身的机器学习实力。如IBM于今年3月收购了AIchemyAPI，AIchemyAPI能够利用深度学习人工智能，搜集企业、网站发行的图片和文字等来进行文本识别和数据分析。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">此外，2015年不仅仅是关于大公司的，利用机器学习的各种创业公司也占了同等地位。比如EverString完成B轮融资，该公司利用企业内部销售数据，和不断主动挖掘分析全球新闻数据，社交媒体等外部数据，通过机器学习自动建立量化客户模型，为企业预测潜在客户。</p><h2>数据科学家的崛起</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">大数据需要数据分析，数据分析需要人才。数据科学是早就存在的词汇，而数据科学家却是近年来突然出现的新词。在Google、Amazon、Quora、Facebook等大公司的背后，都有一批数据科学专业人才，将大量数据变为可开发有价值的金矿。在大数据时代，数据科学家等分析人才的需求在激增。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">据相关报告，国内大数据人才缺口目前已达百万，一名高级数据挖掘工程师月薪高达30K-50K。招聘网站上的每天都会产生大量的大数据相关职位需求。据拉勾网提供的统计来看，从2014年到2015年，IT行业关于大数据的岗位需求增长了2.4倍。人才培养迫在眉睫。复旦大学于今年成立了全国首个大数据学院。阿里云于年底宣布新增30所合作高校，开设云计算大数据专业,计划用3年时间培养5万名数据科学家。各知名大学也将数据科学设为硕士课程。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">无论是国内还是国外，数据科学都是目前炙手可热的研究领域，数据科学家、数据分析师都是非常火爆的职位，几乎所有的产业都需要数据科学家来从大量的数据中挖掘有价值的信息。大数据分析领域的专属首席级别头衔也愈发多见。美国政府今年任命了DJ&nbsp;Patil作为政府的首席数据科学家（Chief&nbsp;Data&nbsp;Scientist），这也是美国政府内部首次设立&#8220;数据科学家&#8221;这个职位。</p><h2>展望2016：</h2><ul style="margin: 0px 0px 15px 10px; padding: 0px; border: 0px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">Hadoop。对于&nbsp;HDFS，会朝着异构存储介质方向发展，尤其是对新兴存储介质的支持；对于&nbsp;YARN，会朝着通用资源管理和调度方向发展，而不仅仅限于大数据处理领域，在加强对&nbsp;MapReduce、Spark等短类型应用支持的同时，加强对类似Web&nbsp;Service&nbsp;等长服务的支持；</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">对于HBase，将会花费更多精力在稳定性和性能方面，正尝试的技术方向包括：对于&nbsp;HDFS&nbsp;多存储介质的使用；减少对&nbsp;ZooKeeper&nbsp;的使用以及通过使用堆外内存缓解Java&nbsp;GC的影响。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">Spark&nbsp;2.0预计明年三四月份发布，将会确立以DataFrame和Dataset为核心的体系架构。同时在各方面的性能上会有很大的提升。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">Apache&nbsp;Kylin&nbsp;2.0即将发布，随着各项改进的不断完善，该版本将在2016年在OLAP&nbsp;on&nbsp;Hadoop上更进一步！</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">Elasticsearch开源搜索平台，机器学习，Data&nbsp;graphics，数据可视化在2016年会更加火热。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">大数据会越来越大，IOT、社交媒体依然是一个主要的推动因素。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">大数据的安全和隐私会持续受到关注。</li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">&nbsp;</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">专家介绍：</span></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">董西成</span>&nbsp;就职于Hulu，专注于分布式计算和资源管理系统等相关技术。《Hadoop&nbsp;技术内幕：深入解析&nbsp;MapReduce&nbsp;架构设计与实现原理》和《Hadoop&nbsp;技术内幕：深入解&nbsp;析&nbsp;YARN&nbsp;架构设计与实现原理》作者，dongxicheng.org&nbsp;博主。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">梁堰波</span>&nbsp;明略数据技术合伙人，开源爱好者，Apache&nbsp;Spark项目核心贡献者。北京航空航天大学计算机硕士，曾就职于Yahoo!、美团网、法国电信从事机器学习和推荐系统相关的工作，在大数据、机器学习和分布式系统领域具备丰富的项目经验。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">卢亿雷</span>&nbsp;精硕科技(AdMaster)技术副总裁兼总架构师，大数据资深专家，CCF（中国计算学会）大数据专委委员，北航特聘教授。主要负责数据的采集、清洗、存储、挖掘等整个数据流过程，确保提供高可靠、高可用、高扩展、高性能系统服务，提供Hadoop/HBase/Storm/Spark/ElasticSearch等离线、流式及实时分布式计算服务。对分布式存储和分布式计算、超大集群、大数据分析等有深刻理解及实践经验。有超过10年云计算、云存储、大数据经验。曾在联想、百度、Carbonite工作，并拥有多篇大数据相关的专利和论文。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">韩卿</span>(Luke&nbsp;Han)&nbsp;eBay全球分析基础架构部(ADI)&nbsp;大数据平台产品负责人，Apache&nbsp;Kylin&nbsp;副总裁，联合创始人，管理和驱动着Apache&nbsp;Kylin的愿景，路线图，特性及计划等，在全球各地不同部门中发展客户，开拓内外部合作伙伴及管理开源社区等，建立与大数据厂商，集成商及最终用户的联系已构建健壮的Apache&nbsp;Kylin生态系统。在大数据，数据仓库，商务智能等方面拥有超过十年的工作经验。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">&nbsp;</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><div style="margin: 0px 0px 5px; border: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><span style="margin: 0px; border: 0px; padding: 0px; font-weight: 600;">【<a href="http://2016.qconbeijing.com/" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">QCon北京2016</a>】大会火热筹备中，腾讯社交网络质量部副总经理吴凯华、美团网技术总监王栋、奇虎360系统部总监肖康等专家将担任专题出品人，策划实践驱动的技术分享。另，100+位讲师积极邀约中，欢迎<a href="http://www.infoq.com/cn/news/2015/12/qcon-bj-2016" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">自荐或推荐</a>。现在<a href="http://2016.qconbeijing.com/apply" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">购票</a>，可享8折优惠，5人之上团购优惠多多。</span></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/429064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-01-15 15:01 <a href="http://www.blogjava.net/xiaomage234/archive/2016/01/15/429064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实施微服务，我们需要哪些基础框架？【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2015/12/30/428879.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 30 Dec 2015 11:02:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/12/30/428879.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428879.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/12/30/428879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428879.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428879.html</trackback:ping><description><![CDATA[from:http://www.infoq.com/cn/articles/basis-frameworkto-implement-micro-service<br /><br /><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">微服务(MicroServices)架构是当前互联网业界的一个技术热点，圈里有不少同行朋友当前有计划在各自公司开展微服务化体系建设，他们都有相同的疑问：一个微服务架构有哪些技术关注点(technical concerns)？需要哪些基础框架或组件来支持微服务架构？这些框架或组件该如何选型？笔者之前在两家大型互联网公司参与和主导过大型服务化体系和框架建设，同时在这块也投入了很多时间去学习和研究，有一些经验和学习心得，可以和大家一起分享。</p><h2>服务注册、发现、负载均衡和健康检查</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">和单块(Monolithic)架构不同，微服务架构是由一系列职责单一的细粒度服务构成的分布式网状结构，服务之间通过轻量机制进行通信，这时候必然引入一个服务注册发现问题，也就是说服务提供方要注册通告服务地址，服务的调用方要能发现目标服务，同时服务提供方一般以集群方式提供服务，也就引入了负载均衡和健康检查问题。根据负载均衡LB所在位置的不同，目前主要的服务注册、发现和负载均衡方案有三种：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">第一种是集中式LB方案，如下图Fig 1，在服务消费者和服务提供者之间有一个独立的LB，LB通常是专门的硬件设备如F5，或者基于软件如LVS，HAproxy等实现。LB上有所有服务的地址映射表，通常由运维配置注册，当服务消费方调用某个目标服务时，它向LB发起请求，由LB以某种策略（比如Round-Robin）做负载均衡后将请求转发到目标服务。LB一般具备健康检查能力，能自动摘除不健康的服务实例。服务消费方如何发现LB呢？通常的做法是通过DNS，运维人员为服务配置一个DNS域名，这个域名指向LB。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125000.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 1, 集中式LB方案</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">集中式LB方案实现简单，在LB上也容易做集中式的访问控制，这一方案目前还是业界主流。集中式LB的主要问题是单点问题，所有服务调用流量都经过LB，当服务数量和调用量大的时候，LB容易成为瓶颈，且一旦LB发生故障对整个系统的影响是灾难性的。另外，LB在服务消费方和服务提供方之间增加了一跳(hop)，有一定性能开销。</p><div visible=""  "="" style="margin: 0px 0px 20px; border: 1px solid #dfdfdf; float: left; width: 610px; overflow: hidden; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><div only1=""  fullwidth"="" style="margin: 0px; border-width: 0px 1px 0px 0px; border-right-style: dotted; border-right-color: #dfdfdf; float: left; width: 610px; background: none 50% 0% repeat-y #f7f7f7;"><div sponsored=""  only1"="" style="margin: 0px; padding-top: 10px; padding-left: 10px; border: 0px; float: left; width: 610px; min-height: 150px;"><p style="margin: 0px 0px 8px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: both; width: 610px; font-weight: 600;">相关厂商内容</p><div style="margin: 0px; padding-top: 5px; border: 0px; float: left; width: 603.890625px; min-height: 100px;"><h3><a href="http://www.infoq.com/cn/vendorcontent/show.action?vcr=3514&amp;utm_source=infoq&amp;utm_medium=VCR&amp;utm_campaign=vcr_articles_click" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">通过demo学习OpenStack开发所需的基础知识 &#8212; 软件包管理</a></h3><h3><a href="http://www.infoq.com/cn/vendorcontent/show.action?vcr=3678&amp;utm_source=infoq&amp;utm_medium=VCR&amp;utm_campaign=vcr_articles_click" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">百度沙龙61期：纵谈前端接入技术、SEO和安全运维</a></h3><h3><a href="http://www.infoq.com/cn/vendorcontent/show.action?vcr=3585&amp;utm_source=infoq&amp;utm_medium=VCR&amp;utm_campaign=vcr_articles_click" target="_blank" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">阿里百川开放云平台助力无线创业</a></h3><h3><a href="http://www.infoq.com/cn/vendorcontent/show.action?vcr=3430&amp;utm_source=infoq&amp;utm_medium=VCR&amp;utm_campaign=vcr_articles_click" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">利用 Amazon ElastiCache 保障规模化条件下的性能水平</a></h3><h3><a href="http://www.infoq.com/cn/vendorcontent/show.action?vcr=3423&amp;utm_source=infoq&amp;utm_medium=VCR&amp;utm_campaign=vcr_articles_click" style="text-decoration: none; color: #170000; margin: 0px; border: 0px; padding: 0px; outline: none !important;">AWS的商业价值</a></h3><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px;"></div></div></div></div><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px;"></div></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">第二种是进程内LB方案，针对集中式LB的不足，进程内LB方案将LB的功能以库的形式集成到服务消费方进程里头，该方案也被称为软负载(Soft Load Balancing)或者客户端负载方案，下图Fig 2展示了这种方案的工作原理。这一方案需要一个服务注册表(Service Registry)配合支持服务自注册和自发现，服务提供方启动时，首先将服务地址注册到服务注册表（同时定期报心跳到服务注册表以表明服务的存活状态，相当于健康检查），服务消费方要访问某个服务时，它通过内置的LB组件向服务注册表查询（同时缓存并定期刷新）目标服务地址列表，然后以某种负载均衡策略选择一个目标服务地址，最后向目标服务发起请求。这一方案对服务注册表的可用性(Availability)要求很高，一般采用能满足高可用分布式一致的组件（例如Zookeeper, Consul, Etcd等）来实现。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125001.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 2, 进程内LB方案</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">进程内LB方案是一种分布式方案，LB和服务发现能力被分散到每一个服务消费者的进程内部，同时服务消费方和服务提供方之间是直接调用，没有额外开销，性能比较好。但是，该方案以客户库(Client Library)的方式集成到服务调用方进程里头，如果企业内有多种不同的语言栈，就要配合开发多种不同的客户端，有一定的研发和维护成本。另外，一旦客户端跟随服务调用方发布到生产环境中，后续如果要对客户库进行升级，势必要求服务调用方修改代码并重新发布，所以该方案的升级推广有不小的阻力。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">进程内LB的案例是Netflix的开源服务框架，对应的组件分别是：Eureka服务注册表，Karyon服务端框架支持服务自注册和健康检查，Ribbon客户端框架支持服务自发现和软路由。另外，阿里开源的服务框架Dubbo也是采用类似机制。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">第三种是主机独立LB进程方案，该方案是针对第二种方案的不足而提出的一种折中方案，原理和第二种方案基本类似，不同之处是，他将LB和服务发现功能从进程内移出来，变成主机上的一个独立进程，主机上的一个或者多个服务要访问目标服务时，他们都通过同一主机上的独立LB进程做服务发现和负载均衡，见下图Fig 3。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125002.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 3 主机独立LB进程方案</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">该方案也是一种分布式方案，没有单点问题，一个LB进程挂了只影响该主机上的服务调用方，服务调用方和LB之间是进程内调用，性能好，同时，该方案还简化了服务调用方，不需要为不同语言开发客户库，LB的升级不需要服务调用方改代码。该方案的不足是部署较复杂，环节多，出错调试排查问题不方便。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">该方案的典型案例是Airbnb的SmartStack服务发现框架，对应组件分别是：Zookeeper作为服务注册表，Nerve独立进程负责服务注册和健康检查，Synapse/HAproxy独立进程负责服务发现和负载均衡。Google最新推出的基于容器的PaaS平台Kubernetes，其内部服务发现采用类似的机制。</p><h2>服务前端路由</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">微服务除了内部相互之间调用和通信之外，最终要以某种方式暴露出去，才能让外界系统（例如客户的浏览器、移动设备等等）访问到，这就涉及服务的前端路由，对应的组件是服务网关(Service Gateway)，见图Fig 4，网关是连接企业内部和外部系统的一道门，有如下关键作用：</p><ol style="margin: 10px 0px 10px 10px; padding: 0px 0px 0px 20px; border: 0px; width: 549px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">服务反向路由，网关要负责将外部请求反向路由到内部具体的微服务，这样虽然企业内部是复杂的分布式微服务结构，但是外部系统从网关上看到的就像是一个统一的完整服务，网关屏蔽了后台服务的复杂性，同时也屏蔽了后台服务的升级和变化。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">安全认证和防爬虫，所有外部请求必须经过网关，网关可以集中对访问进行安全控制，比如用户认证和授权，同时还可以分析访问模式实现防爬虫功能，网关是连接企业内外系统的安全之门。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">限流和容错，在流量高峰期，网关可以限制流量，保护后台系统不被大流量冲垮，在内部系统出现故障时，网关可以集中做容错，保持外部良好的用户体验。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">监控，网关可以集中监控访问量，调用延迟，错误计数和访问模式，为后端的性能优化或者扩容提供数据支持。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">日志，网关可以收集所有的访问日志，进入后台系统做进一步分析。</li></ol><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125003.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 4, 服务网关</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">除以上基本能力外，网关还可以实现线上引流，线上压测，线上调试(Surgical debugging)，金丝雀测试(Canary Testing)，数据中心双活(Active-Active HA)等高级功能。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">网关通常工作在7层，有一定的计算逻辑，一般以集群方式部署，前置LB进行负载均衡。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">开源的网关组件有Netflix的Zuul，特点是动态可热部署的过滤器(filter)机制，其它如HAproxy，Nginx等都可以扩展作为网关使用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">在介绍过服务注册表和网关等组件之后，我们可以通过一个简化的微服务架构图(Fig 5)来更加直观地展示整个微服务体系内的服务注册发现和路由机制，该图假定采用进程内LB服务发现和负载均衡机制。在下图Fig 5的微服务架构中，服务简化为两层，后端通用服务（也称中间层服务Middle Tier Service）和前端服务（也称边缘服务Edge Service，前端服务的作用是对后端服务做必要的聚合和裁剪后暴露给外部不同的设备，如PC，Pad或者Phone）。后端服务启动时会将地址信息注册到服务注册表，前端服务通过查询服务注册表就可以发现然后调用后端服务；前端服务启动时也会将地址信息注册到服务注册表，这样网关通过查询服务注册表就可以将请求路由到目标前端服务，这样整个微服务体系的服务自注册自发现和软路由就通过服务注册表和网关串联起来了。如果以面向对象设计模式的视角来看，网关类似Proxy代理或者Fa&#231;ade门面模式，而服务注册表和服务自注册自发现类似IoC依赖注入模式，微服务可以理解为基于网关代理和注册表IoC构建的分布式系统。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125004.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 5, 简化的微服务架构图</p><h2>服务容错</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">当企业微服务化以后，服务之间会有错综复杂的依赖关系，例如，一个前端请求一般会依赖于多个后端服务，技术上称为1 -&gt; N扇出(见图Fig 6)。在实际生产环境中，服务往往不是百分百可靠，服务可能会出错或者产生延迟，如果一个应用不能对其依赖的故障进行容错和隔离，那么该应用本身就处在被拖垮的风险中。在一个高流量的网站中，某个单一后端一旦发生延迟，可能在数秒内导致所有应用资源(线程，队列等)被耗尽，造成所谓的雪崩效应(Cascading Failure，见图Fig 7)，严重时可致整个网站瘫痪。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125005.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 6, 服务依赖</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125006.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 7, 高峰期单个服务延迟致雪崩效应</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">经过多年的探索和实践，业界在分布式服务容错一块探索出了一套有效的容错模式和最佳实践，主要包括：</p><ol style="margin: 10px 0px 10px 10px; padding: 0px 0px 0px 20px; border: 0px; width: 549px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">电路熔断器模式(Circuit Breaker Patten), 该模式的原理类似于家里的电路熔断器，如果家里的电路发生短路，熔断器能够主动熔断电路，以避免灾难性损失。在分布式系统中应用电路熔断器模式后，当目标服务慢或者大量超时，调用方能够主动熔断，以防止服务被进一步拖垮；如果情况又好转了，电路又能自动恢复，这就是所谓的弹性容错，系统有自恢复能力。下图Fig 8是一个典型的具备弹性恢复能力的电路保护器状态图，正常状态下，电路处于关闭状态(Closed)，如果调用持续出错或者超时，电路被打开进入熔断状态(Open)，后续一段时间内的所有调用都会被拒绝(Fail Fast)，一段时间以后，保护器会尝试进入半熔断状态(Half-Open)，允许少量请求进来尝试，如果调用仍然失败，则回到熔断状态，如果调用成功，则回到电路闭合状态。</li><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 549px;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125007.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 549px;">Fig 8, 弹性电路保护状态图</p><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">舱壁隔离模式(Bulkhead Isolation Pattern)，顾名思义，该模式像舱壁一样对资源或失败单元进行隔离，如果一个船舱破了进水，只损失一个船舱，其它船舱可以不受影响 。线程隔离(Thread Isolation)就是舱壁隔离模式的一个例子，假定一个应用程序A调用了Svc1/Svc2/Svc3三个服务，且部署A的容器一共有120个工作线程，采用线程隔离机制，可以给对Svc1/Svc2/Svc3的调用各分配40个线程，当Svc2慢了，给Svc2分配的40个线程因慢而阻塞并最终耗尽，线程隔离可以保证给Svc1/Svc3分配的80个线程可以不受影响，如果没有这种隔离机制，当Svc2慢的时候，120个工作线程会很快全部被对Svc2的调用吃光，整个应用程序会全部慢下来。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">限流(Rate Limiting/Load Shedder)，服务总有容量限制，没有限流机制的服务很容易在突发流量(秒杀，双十一)时被冲垮。限流通常指对服务限定并发访问量，比如单位时间只允许100个并发调用，对超过这个限制的请求要拒绝并回退。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">回退(fallback)，在熔断或者限流发生的时候，应用程序的后续处理逻辑是什么？回退是系统的弹性恢复能力，常见的处理策略有，直接抛出异常，也称快速失败(Fail Fast)，也可以返回空值或缺省值，还可以返回备份数据，如果主服务熔断了，可以从备份服务获取数据。</li></ol><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Netflix将上述容错模式和最佳实践集成到一个称为Hystrix的开源组件中，凡是需要容错的依赖点(服务，缓存，数据库访问等)，开发人员只需要将调用封装在Hystrix Command里头，则相关调用就自动置于Hystrix的弹性容错保护之下。Hystrix组件已经在Netflix经过多年运维验证，是Netflix微服务平台稳定性和弹性的基石，正逐渐被社区接受为标准容错组件。</p><h2>服务框架</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">微服务化以后，为了让业务开发人员专注于业务逻辑实现，避免冗余和重复劳动，规范研发提升效率，必然要将一些公共关注点推到框架层面。服务框架(Fig 9)主要封装公共关注点逻辑，包括：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125008.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 9, 服务框架</p><ol style="margin: 10px 0px 10px 10px; padding: 0px 0px 0px 20px; border: 0px; width: 549px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">服务注册、发现、负载均衡和健康检查，假定采用进程内LB方案，那么服务自注册一般统一做在服务器端框架中，健康检查逻辑由具体业务服务定制，框架层提供调用健康检查逻辑的机制，服务发现和负载均衡则集成在服务客户端框架中。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">监控日志，框架一方面要记录重要的框架层日志、metrics和调用链数据，还要将日志、metrics等接口暴露出来，让业务层能根据需要记录业务日志数据。在运行环境中，所有日志数据一般集中落地到企业后台日志系统，做进一步分析和处理。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">REST/RPC和序列化，框架层要支持将业务逻辑以HTTP/REST或者RPC方式暴露出来，HTTP/REST是当前主流API暴露方式，在性能要求高的场合则可采用Binary/RPC方式。针对当前多样化的设备类型(浏览器、普通PC、无线设备等)，框架层要支持可定制的序列化机制，例如，对浏览器，框架支持输出Ajax友好的JSON消息格式，而对无线设备上的Native App，框架支持输出性能高的Binary消息格式。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">配置，除了支持普通配置文件方式的配置，框架层还可集成动态运行时配置，能够在运行时针对不同环境动态调整服务的参数和配置。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">限流和容错，框架集成限流容错组件，能够在运行时自动限流和容错，保护服务，如果进一步和动态配置相结合，还可以实现动态限流和熔断。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">管理接口，框架集成管理接口，一方面可以在线查看框架和服务内部状态，同时还可以动态调整内部状态，对调试、监控和管理能提供快速反馈。Spring Boot微框架的Actuator模块就是一个强大的管理接口。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">统一错误处理，对于框架层和服务的内部异常，如果框架层能够统一处理并记录日志，对服务监控和快速问题定位有很大帮助。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">安全，安全和访问控制逻辑可以在框架层统一进行封装，可做成插件形式，具体业务服务根据需要加载相关安全插件。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">文档自动生成，文档的书写和同步一直是一个痛点，框架层如果能支持文档的自动生成和同步，会给使用API的开发和测试人员带来极大便利。Swagger是一种流行Restful API的文档方案。</li></ol><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">当前业界比较成熟的微服务框架有Netflix的Karyon/Ribbon，Spring的Spring Boot/Cloud，阿里的Dubbo等。</p><h2>运行期配置管理</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">服务一般有很多依赖配置，例如访问数据库有连接字符串配置，连接池大小和连接超时配置，这些配置在不同环境(开发/测试/生产)一般不同，比如生产环境需要配连接池，而开发测试环境可能不配，另外有些参数配置在运行期可能还要动态调整，例如，运行时根据流量状况动态调整限流和熔断阀值。目前比较常见的做法是搭建一个运行时配置中心支持微服务的动态配置，简化架构如下图(Fig 10):</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125009.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 10, 服务配置中心</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">动态配置存放在集中的配置服务器上，用户通过管理界面配置和调整服务配置，具体服务通过定期拉(Scheduled Pull)的方式或者服务器推(Server-side Push)的方式更新动态配置，拉方式比较可靠，但会有延迟同时有无效网络开销(假设配置不常更新)，服务器推方式能及时更新配置，但是实现较复杂，一般在服务和配置服务器之间要建立长连接。配置中心还要解决配置的版本控制和审计问题，对于大规模服务化环境，配置中心还要考虑分布式和高可用问题。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">配置中心比较成熟的开源方案有百度的Disconf，360的QConf，Spring的Cloud Config和阿里的Diamond等。</p><h4>Netflix的微服务框架</h4><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Netflix是一家成功实践微服务架构的互联网公司，几年前，Netflix就把它的几乎整个微服务框架栈开源贡献给了社区，这些框架和组件包括：</p><ol style="margin: 10px 0px 10px 10px; padding: 0px 0px 0px 20px; border: 0px; width: 549px; clear: left; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Eureka:　服务注册发现框架</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Zuul:　服务网关</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Karyon:　服务端框架</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Ribbon:　客户端框架</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Hystrix: 服务容错组件</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Archaius: 服务配置组件</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Servo: Metrics组件</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">Blitz4j: 日志组件</li></ol><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">下图Fig 11展示了基于这些组件构建的一个微服务框架体系，来自recipes-rss。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn1.infoqstatic.com/statics_s2_20151224-0209/resource/articles/basis-frameworkto-implement-micro-service/zh/resources/1125010.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Fig 11, 基于Netflix开源组件的微服务框架</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.8; clear: none; width: 610px; font-family: 'Lantinghei SC', 'Open Sans', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 微软雅黑, STHeiti, 'WenQuanYi Micro Hei', SimSun, Helvetica, sans-serif; background-color: #ffffff;">Netflix的开源框架组件已经在Netflix的大规模分布式微服务环境中经过多年的生产实战验证，正逐步被社区接受为构造微服务框架的标准组件。Pivotal去年推出的Spring Cloud开源产品，主要是基于对Netflix开源组件的进一步封装，方便Spring开发人员构建微服务基础框架。对于一些打算构建微服务框架体系的公司来说，充分利用或参考借鉴Netflix的开源微服务组件(或Spring Cloud)，在此基础上进行必要的企业定制，无疑是通向微服务架构的捷径。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/428879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-12-30 19:02 <a href="http://www.blogjava.net/xiaomage234/archive/2015/12/30/428879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何更好地学习dubbo源代码【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2015/12/15/428674.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 15 Dec 2015 11:25:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/12/15/428674.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428674.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/12/15/428674.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428674.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428674.html</trackback:ping><description><![CDATA[<h1><span style="line-height: 19.5px; color: #333333; font-family: 'Segoe UI', Calibri, 'Myriad Pro', Myriad, 'Trebuchet MS', Helvetica, Arial, sans-serif; font-size: 13px; background-color: #ffffff;">很荣幸，作为这样一款业界使用率和好评率出众的RPC框架的维护者，今天这个文章主要是想帮助那些热爱开源的同学，更好的来研究dubbo的源代码。</span></h1><div clear-block"="" style="margin: 0px; color: #333333; font-family: 'Segoe UI', Calibri, 'Myriad Pro', Myriad, 'Trebuchet MS', Helvetica, Arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;"><strong>&nbsp;一、Dubbo整体架构</strong></p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;"><strong>1、Dubbo与Spring的整合</strong><br />Dubbo在使用上可以做到非常简单，不管是Provider还是Consumer都可以通过Spring的配置文件进行配置，配置完之后，就可以像使用spring bean一样进行服务暴露和调用了，完全看不到dubbo api的存在。这是因为dubbo使用了spring提供的可扩展Schema自定义配置支持。在spring配置文件中，可以像、这样进行配置。META-INF下的spring.handlers文件中指定了dubbo的xml解析类：DubboNamespaceHandler。像前面的被解析成ServiceConfig，被解析成ReferenceConfig等等。<br /><strong>2、jdk spi扩展</strong><br />由于Dubbo是开源框架，必须要提供很多的可扩展点。Dubbo是通过扩展jdk spi机制来实现可扩展的。具体来说，就是在META-INF目录下，放置文件名为接口全称，文件中为key、value键值对，value为具体实现类的全类名，key为标志值。由于dubbo使用了url总线的设计，即很多参数通过URL对象来传递，在实际中，具体要用到哪个值，可以通过url中的参数值来指定。<br />Dubbo对spi的扩展是通过ExtensionLoader来实现的，查看ExtensionLoader的源码，可以看到Dubbo对jdk spi做了三个方面的扩展：</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">（1）jdk spi仅仅通过接口类名获取所有实现，而ExtensionLoader则通过接口类名和key值获取一个实现；</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">（2）Adaptive实现，就是生成一个代理类，这样就可以根据实际调用时的一些参数动态决定要调用的类了。</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">（3）自动包装实现，这种实现的类一般是自动激活的，常用于包装类，比如Protocol的两个实现类：ProtocolFilterWrapper、ProtocolListenerWrapper。<br /><strong>3、url总线设计</strong><br />Dubbo为了使得各层解耦，采用了url总线的设计。我们通常的设计会把层与层之间的交互参数做成Model，这样层与层之间沟通成本比较大，扩展起来也比较麻烦。因此，Dubbo把各层之间的通信都采用url的形式。比如，注册中心启动时，参数的url为：<br />registry://0.0.0.0:9090?codec=registry&amp;transporter=netty<br />这就表示当前是注册中心，绑定到所有ip，端口是9090，解析器类型是registry，使用的底层网络通信框架是netty。</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;"><strong>&nbsp;二、Dubbo启动过程</strong></p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">Dubbo分为注册中心、服务提供者(provider)、服务消费者(consumer)三个部分。<br /><strong>1、注册中心启动过程</strong><br />注册中心的启动过程，主要看两个类：RegistrySynchronizer、RegistryReceiver，两个类的初始化方法都是start。<br />RegistrySynchronizer的start方法：</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">（1）把所有配置信息load到内存；</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">（2）把当前注册中心信息保存到数据库；</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">（3）启动5个定时器。<br />5个定时器的功能是：<br />（1）AutoRedirectTask，自动重定向定时器。默认1小时运行1次。如果当前注册中心的连接数高于平均值的1.2倍，则将多出来的连接数重定向到其他注册中心上，以达到注册中心集群的连接数均衡。<br />（2）DirtyCheckTask，脏数据检查定时器。作用是：分别检查缓存provider、数据库provider、缓存consumer、数据库consumer的数据，清除脏数据；清理不存活的provider和consumer数据；对于缓存中的存在的provider或consumer而数据库不存在，重新注册和订阅。<br />（3）ChangedClearTask，changes变更表的定时清理任务。作用是读取changes表，清除过期数据。<br />（4）AlivedCheckTask，注册中心存活状态定时检查，会定时更新registries表的expire字段，用以判断注册中心的存活状态。如果有新的注册中心，发送同步消息，将当前所有注册中心的地址通知到所有客户端。<br />（5）ChangedCheckTask，变更检查定时器。检查changes表的变更，检查类型包括：参数覆盖变更、路由变更、服务消费者变更、权重变更、负载均衡变更。<br />RegistryReceiver的start方法：启动注册中心服务。默认使用netty框架，绑定本机的9090端口。最后启动服务的过程是在NettyServer来完成的。接收消息时，抛开dubbo协议的解码器，调用类的顺序是</p><pre prettyprint=""  prettyprinted"="" style="margin-top: 6px; margin-bottom: 6px; padding: 2px 7px; font-stretch: normal; font-size: 12px; line-height: 16px; font-family: 'Courier New', Courier, 'Lucida Console', Monaco, 'DejaVu Sans Mono', 'Nimbus Mono L', 'Bitstream Vera Sans Mono', monospace; overflow: auto; white-space: pre-wrap; border: 1px solid #cccccc; word-wrap: normal; width: 597.796875px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"><span style="color: #660066;">NettyHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">NettyServer</span><span style="color: #666600;">-》</span><span style="color: #660066;">MultiMessageHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">HeartbeatHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">AllDispatcher</span><span style="color: #666600;">-》</span><span style="color: #000000;"> </span><span style="color: #660066;">DecodeHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">HeaderExchangeHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">RegistryReceiver</span><span style="color: #666600;">-》</span><span style="color: #660066;">RegistryValidator</span><span style="color: #666600;">-》</span><span style="color: #660066;">RegistryFailover</span><span style="color: #666600;">-》</span><span style="color: #660066;">RegistryExecutor</span><span style="color: #666600;">。</span></pre><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;"><strong>2、provider启动过程</strong><br />provider的启动过程是从ServiceConfig的export方法开始进行的，具体步骤是：<br />（1）进行本地jvm的暴露，不开放任何端口，以提供injvm这种形式的调用，这种调用只是本地调用，不涉及进程间通信。<br />（2）调用RegistryProtocol的export。<br />（3）调用DubboProtocol的export，默认开启20880端口，用以提供接收consumer的远程调用服务。<br />（4）通过新建RemoteRegistry来建立与注册中心的连接。<br />（5）将服务地址注册到注册中心。<br />（6）去注册中心订阅自己的服务。<br /><strong>3、consumer启动过程</strong><br />consumer的启动过程是通过ReferenceConfig的get方法进行的，具体步骤是：<br />（1）通过新建RemoteRegistry来建立与注册中心的连接。<br />（2）新建RegistryDirectory并向注册中心订阅服务，RegistryDirectory用以维护注册中心获取的服务相关信息。<br />（3）创建代理类，发起consumer远程调用时，实际调用的是InvokerInvocationHandler。</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;"><strong>三、实际调用过程</strong><br />consumer端发起调用时，实际调用经过的类是：<br />1、consumer:</p><pre prettyprint=""  prettyprinted"="" style="margin-top: 6px; margin-bottom: 6px; padding: 2px 7px; font-stretch: normal; font-size: 12px; line-height: 16px; font-family: 'Courier New', Courier, 'Lucida Console', Monaco, 'DejaVu Sans Mono', 'Nimbus Mono L', 'Bitstream Vera Sans Mono', monospace; overflow: auto; white-space: pre-wrap; border: 1px solid #cccccc; word-wrap: normal; width: 597.796875px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"><span style="color: #660066;">InvokerInvocationHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">MockClusterInvoker</span><span style="color: #666600;">(如果配置了</span><span style="color: #660066;">Mock</span><span style="color: #666600;">，则直接调用本地</span><span style="color: #660066;">Mock</span><span style="color: #666600;">类)-》</span><span style="color: #660066;">FailoverClusterInvoker</span><span style="color: #666600;">(负载均衡，容错机制，默认在发生错误的情况下，进行两次重试)-》</span><span style="color: #660066;">RegistryDirectory$InvokerDelegete</span><span style="color: #666600;">-》</span><span style="color: #660066;">ConsumerContextFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">FutureFilter</span><span style="color: #666600;">-&amp;</span><span style="color: #000000;">gt</span><span style="color: #666600;">;</span><span style="color: #660066;">DubboInvoker</span></pre><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">2、provider:</p><pre prettyprint=""  prettyprinted"="" style="margin-top: 6px; margin-bottom: 6px; padding: 2px 7px; font-stretch: normal; font-size: 12px; line-height: 16px; font-family: 'Courier New', Courier, 'Lucida Console', Monaco, 'DejaVu Sans Mono', 'Nimbus Mono L', 'Bitstream Vera Sans Mono', monospace; overflow: auto; white-space: pre-wrap; border: 1px solid #cccccc; word-wrap: normal; width: 597.796875px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"><span style="color: #660066;">NettyServer</span><span style="color: #666600;">-》</span><span style="color: #660066;">MultiMessageHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">HeartbeatHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">AllDispatcher</span><span style="color: #666600;">-》</span><span style="color: #660066;">DecodeHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">HeaderExchangeHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">DubboProtocol</span><span style="color: #666600;">.</span><span style="color: #000000;">requestHandler</span><span style="color: #666600;">-》</span><span style="color: #660066;">EchoFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">ClassLoaderFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">GenericFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">ContextFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">ExceptionFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">TimeoutFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">MonitorFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">TraceFilter</span><span style="color: #666600;">-》实际</span><span style="color: #000000;">service</span><span style="color: #666600;">。</span></pre><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;"><strong>四、Dubbo使用的设计模式</strong><br /><strong>1、工厂模式</strong><br />ServiceConfig中有个字段，代码是这样的：</p><pre prettyprint=""  prettyprinted"="" style="margin-top: 6px; margin-bottom: 6px; padding: 2px 7px; font-stretch: normal; font-size: 12px; line-height: 16px; font-family: 'Courier New', Courier, 'Lucida Console', Monaco, 'DejaVu Sans Mono', 'Nimbus Mono L', 'Bitstream Vera Sans Mono', monospace; overflow: auto; white-space: pre-wrap; border: 1px solid #cccccc; word-wrap: normal; width: 597.796875px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"><span style="color: #000088;">private</span> <span style="color: #000088;">static</span> <span style="color: #000088;">final</span> <span style="color: #660066;">Protocol</span><span style="color: #000000;"> protocol </span><span style="color: #666600;">=</span> <span style="color: #660066;">ExtensionLoader</span><span style="color: #666600;">.</span><span style="color: #000000;">getExtensionLoader</span><span style="color: #666600;">(</span><span style="color: #660066;">Protocol</span><span style="color: #666600;">.</span><span style="color: #000088;">class</span><span style="color: #666600;">).</span><span style="color: #000000;">getAdaptiveExtension</span><span style="color: #666600;">();</span></pre><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">Dubbo里有很多这种代码。这也是一种工厂模式，只是实现类的获取采用了jdk spi的机制。这么实现的优点是可扩展性强，想要扩展实现，只需要在classpath下增加个文件就可以了，代码零侵入。另外，像上面的Adaptive实现，可以做到调用时动态决定调用哪个实现，但是由于这种实现采用了动态代理，会造成代码调试比较麻烦，需要分析出实际调用的实现类。<br /><strong>2、装饰器模式</strong><br />Dubbo在启动和调用阶段都大量使用了装饰器模式。以Provider提供的调用链为例，具体的调用链代码是在ProtocolFilterWrapper的buildInvokerChain完成的，具体是将注解中含有group=provider的Filter实现，按照order排序，最后的调用顺序是</p><pre prettyprint=""  prettyprinted"="" style="margin-top: 6px; margin-bottom: 6px; padding: 2px 7px; font-stretch: normal; font-size: 12px; line-height: 16px; font-family: 'Courier New', Courier, 'Lucida Console', Monaco, 'DejaVu Sans Mono', 'Nimbus Mono L', 'Bitstream Vera Sans Mono', monospace; overflow: auto; white-space: pre-wrap; border: 1px solid #cccccc; word-wrap: normal; width: 597.796875px; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"><span style="color: #660066;">EchoFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">ClassLoaderFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">GenericFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">ContextFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">ExceptionFilter</span><span style="color: #666600;">-》</span><span style="color: #000000;"> </span><span style="color: #660066;">TimeoutFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">MonitorFilter</span><span style="color: #666600;">-》</span><span style="color: #660066;">TraceFilter</span><span style="color: #666600;">。</span></pre><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">更确切地说，这里是装饰器和责任链模式的混合使用。例如，EchoFilter的作用是判断是否是回声测试请求，是的话直接返回内容，这是一种责任链的体现。而像ClassLoaderFilter则只是在主功能上添加了功能，更改当前线程的ClassLoader，这是典型的装饰器模式。<br /><strong>3、观察者模式</strong><br />Dubbo的provider启动时，需要与注册中心交互，先注册自己的服务，再订阅自己的服务，订阅时，采用了观察者模式，开启一个listener。注册中心会每5秒定时检查是否有服务更新，如果有更新，向该服务的提供者发送一个notify消息，provider接受到notify消息后，即运行NotifyListener的notify方法，执行监听器方法。<br /><strong>4、动态代理模式</strong><br />Dubbo扩展jdk spi的类ExtensionLoader的Adaptive实现是典型的动态代理实现。Dubbo需要灵活地控制实现类，即在调用阶段动态地根据参数决定调用哪个实现类，所以采用先生成代理类的方法，能够做到灵活的调用。生成代理类的代码是ExtensionLoader的createAdaptiveExtensionClassCode方法。代理类的主要逻辑是，获取URL参数中指定参数的值作为获取实现类的key。</p><p style="margin: 0.25em 0px 0.75em; padding: 0px; line-height: 19.5px;">&nbsp;</p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/428674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-12-15 19:25 <a href="http://www.blogjava.net/xiaomage234/archive/2015/12/15/428674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>那些年Google公开的大数据领域论文【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2015/12/11/428609.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 11 Dec 2015 03:18:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/12/11/428609.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428609.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/12/11/428609.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428609.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428609.html</trackback:ping><description><![CDATA[<div style="margin: 0px 0px 1.5em; padding: 5px 10px; list-style: none; color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background: #f7f7f7;"><strong>摘要：</strong>Google于2004年公布了MapReduce论文，为数据领域工作者开启了大数据算法之门。然而Google的大数据脚步显然不止于此，其后公布了Percolator、Pregel、Dremel、Spanner等多篇论文。没有止步的不仅是Google，很多公司也跟随其脚步开发了很多优秀的产品，虽然其中不乏模仿。</div><div news_content"="" style="margin: 0px 0px 30px; list-style: none; color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">Mikio L. Braun柏林工业大学机器学习学博士后，TWIMPACT联合创始人兼首席数据科学家。在其个人博客上总结了Google近几年大数据领域的论文，并发表了自己的见解。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>以下为译文：</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><a href="http://cms.csdnimg.cn/article/201302/28/512f06bf65206.jpg" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;"><img align="right" src="http://cms.csdnimg.cn/article/201302/28/512f06bf65206.jpg" border="0" style="vertical-align: middle; border: none; width: 300px; height: 171px;"  alt="" /></a></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">主流的大数据基本都是MapReduce的衍生，然而把目光聚焦到实时上就会发现：MapReuce的局限性已经渐渐浮现。下面将讨论一下自大数据开始，Google公布的大数据相关技术，以及这些技术的现状。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>MapReuce、Google File System以及Bigtable：大数据算法的起源</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">按时间算第一篇的论文应该2003年公布的&nbsp;<a href="http://research.google.com/archive/gfs.html" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Google File System</a>，这是一个分布式文件系统。从根本上说：文件被分割成很多块，使用冗余的方式储存于商用机器集群上；这里不得不说基本上Google每篇论文都是关于&#8220;商用机型&#8221;。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">紧随其后的就是2004年被公布的&nbsp;<a href="http://research.google.com/archive/mapreduce.html" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">MapReduce</a>，而今MapReuce基本上已经代表了大数据。传说中，Google使用它计算他们的搜索索引。而Mikio L. Braun认为其工作模式应该是：Google把所有抓取的页面都放置于他们的集群上，并且每天都使用MapReduce来重算。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><a href="http://research.google.com/archive/bigtable.html" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Bigtable</a>发布于2006年，启发了无数的NoSQL数据库，比如：Cassandra、HBase等等。Cassandra架构中有一半是模仿Bigtable，包括了数据模型、SSTables以及提前写日志（另一半是模仿Amazon的Dynamo数据库，使用点对点集群模式）。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>Percolator：处理个体修改</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">Google并没有止步于MapReduce。事实上，随着Internet的指数增长，从零开始重算所有搜索索引变得不切实际。取而代之，Google开发了一个更有价值的系统，同样支持分布式计算。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">这也是其有趣的地方，特别是在对比常见的主流大数据之后。举个例子，Percolator引入了事务，而一些NoSQL数据库仍然在强调得到高扩展性的同时你必须牺牲（或者不再需要）事务处理。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">在2010年这篇&nbsp;<a href="http://research.google.com/pubs/pub36726.html" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Percolator</a>的论文中，Google展示了其网络搜索是如何保持着与时俱进。Percolator建立于已存类似Bigtable的技术，但是加入了事务以及行和表上的锁和表变化的通知。这些通知之后会被用于触发不同阶段的计算。通过这样的方式，个体的更新就可以&#8220;渗透&#8221;整个数据库。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">这种方法会让人联想到类似Storm（或者是Yahoo的S4）的流处理框架（SPF），然而Percolator内在是以数据作为基础。SPF使用的一般是消息传递而不是数据共享，这样的话更容易推测出究竟是发生了什么。然而问题也随之产生：除非你手动的在某个终端上储存，否则你将无法访问计算的结果。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>Pregel：可扩展的图计算</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">最终Google还需要挖掘图数据，比如在线社交网络的社交图谱；所以他们开发了&nbsp;<a href="http://kowshik.github.com/JPregel/pregel_paper.pdf" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Pregel</a>，并在2010年公布其论文。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">Pregel内在的计算模型比MapReduce复杂的多：基本上每个节点都拥有一个工作者线程，并且对众多工作者线程进行迭代并行。在每一个所谓的&#8220;superstep&#8221;中，每一个工作者线程都可以从节点的&#8220;收件夹&#8221;中读取消息和把消息发送给其它节点，设置和读取节点相关值以及边界，或者投票停止。线程会一直运行，直到所有的节点都被投票停止。此外，还拥有Aggregator和Combiner做全局统计。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">论文陈述了许多算法的实现，比如Google的PageRank、最短路径、二分图匹配等。Mikio L. Braun认为，对比MapReduce或SPF，Pregel需要更多实现的再思考。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>Dremel：在线可视化</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">在2010年，Google还公布了&nbsp;<a href="http://research.google.com/pubs/pub36632.html" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Dremel</a>论文。一个为结构化数据设计，并拥有类SQL语言的交互式数据库。然而取代SQL数据库使用字段填补的表格，Dremel中使用的是类JSON格式数据（更准确的说，使用Google&nbsp;<a href="http://code.google.com/p/protobuf/" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Protocol buffer</a>格式，这将加强对允许字段的限制）。内部，数据被使用特殊格式储存，可以让数据扫描工作来的更高效。查询被送往服务器，而优秀的格式可以最大性能的输出结果。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>Spanner：全球分布</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><a href="http://cms.csdnimg.cn/article/201303/04/513413200d335.jpg" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;"><img src="http://cms.csdnimg.cn/article/201303/04/513413200d335.jpg" border="0" style="vertical-align: middle; border: none;"  alt="" /></a></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">最后&nbsp;<a href="http://www.csdn.net/article/2012-09-19/2810132-google-spanner-next-database-datacenter" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Spanner</a>&#8212;&#8212; 全球分布式数据库；Google在2009年提出了Spanner远景计划，并在2012年对外公布Spanner论文。Spanner的公布可以说是Google向大数据技术中添的又一把火，Spanner具有高扩展性、多版本、全球级分布以及同步复制等特性。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">跨数据中心的高扩展性及全球分布会对一致性保障提出苛刻的需求 &#8212;&#8212; 读写的外部一致性和基于时间戳的全局读一致性。为了保障这一点，Google引入了TrueTime API。TureTime API可以同步全球的时间，拥有一个TT.now（）的方法，将获得一个绝对时间，同时还能得到时间误差。为了保证万无一失，TrueTime API具有GPS和原子钟双保险。也只有这样的机制才能让全球范围内的并发处理得到保障。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>大数据超越MapReduce</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">Google并没有止步于MapReduce，他们在MapReduce不适用的地方开发新方法；当然，对于大数据领域来说这是个福音。MapReduce不是万能的；当然，你可以更深入一步，比如说将磁盘数据移入内存，然而同样还存在一些任务的内部结构并不是MapReduce可以扩展的。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">在Google思路以及论文的启发下，同样涌现出一些开源项目，比如：Apache Drill、Apache Giraph、斯坦福GPS等等。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">Google近年来每篇论文都有着深远的影响，同时大数据领域内有很多人必然在翘首以盼Google的下一篇论文。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">原文链接：&nbsp;<a href="http://blog.mikiobraun.de/2013/02/big-data-beyond-map-reduce-googles-papers.html" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;">Big Data beyond MapReduce: Google's Big Data papers</a>&nbsp;（编译/仲浩 审校/王旭东）</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">欢迎&nbsp;<a href="http://e.weibo.com/csdncloud" target="_blank" style="cursor: pointer; color: #0066cc; text-decoration: none;"><strong>@CSDN云计算</strong>&nbsp;</a>微博参与讨论，了解更多云信息。</p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/428609.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-12-11 11:18 <a href="http://www.blogjava.net/xiaomage234/archive/2015/12/11/428609.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>阿里云中间件团队首次解密EDAS企业级分布式应用服务</title><link>http://www.blogjava.net/xiaomage234/archive/2015/12/10/428600.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 10 Dec 2015 11:46:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/12/10/428600.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428600.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/12/10/428600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428600.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428600.html</trackback:ping><description><![CDATA[<div style="margin: 0px 0px 1.5em; padding: 5px 10px; list-style: none; color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background: #f7f7f7;"><strong>摘要：</strong>7月22日，阿里云正式对外发布了企业级互联网架构解决方案，该服务由EDAS应用框架、ONS消息队列、DRDS分布式数据库组成，能有效解决企业上云后网站过载、性能瓶颈、重复开发等问题。</div><div news_content"="" style="margin: 0px 0px 30px; list-style: none; color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">7月22日，阿里云正式对外发布了企业级互联网架构解决方案，该服务由EDAS应用框架、ONS消息队列、DRDS分布式数据库组成，能有效解决企业上云后网站过载、性能瓶颈、重复开发等问题。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">云栖大会武汉站，阿里云中间件团队首次解密这一企业级互联网架构解决方案。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>EDAS，企业级分布式应用服务</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS（企业级分布式应用服务，Enterprise Distributed Application Service）是一个以阿里巴巴中间件团队的多款久经沙场的分布式产品作为核心基础组件构建的企业级云计算解决方案，其充分利用阿里云的ECS等资源，引入淘宝中间件整套成熟的分布式计算框架（包括分布式服务化、链路追踪和稳定性组件等），以应用为中心，帮助企业级客户在阿里云上轻松构建像淘宝这样的大型分布式应用服务。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>具备单应用5K运维能力的一站式PaaS平台</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>应用全生命周期管理</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS能够非常方便的帮助企业级客户实现一站式的应用生命周期管理，其以&#8220;应用&#8221;为中心，从应用的创建开始，到应用的部署与扩容，真正意义上实现对大规模互联网应用在发布和运行过程中的全面管理。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><img src="http://articles.csdn.net/uploads/allimg/150805/224_150805165914_1.png" width="267" border="0" height="195" alt="" style="vertical-align: middle; border: none; cursor: pointer;" /></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>单应用5K运维能力</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">依托于阿里巴巴多年对超大规模互联网电商系统的运维，所沉淀下来宝贵经验和大量运维工具都融入于EDAS产品之中，使得其具备对单个应用多达5000台服务器规模的快速发布能力，包括个性化的Beta和分批发布机制。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>去&#8220;中心化&#8221;的高性能服务框架</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS所提供的分布式服务框架，源自于阿里巴巴内部使用规模最大的中间件产品&#8212;&#8212;HSF。自2007年诞生以来，HSF服务框架就成为了阿里巴巴内部服务化改造的基础组件，其超高的性能、久经考验的稳定性、以及良好的用户体验，支撑了生产环境所有系统的服务化调用，日均调用量为2000~3000亿次，分钟峰值最高达到25亿次。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">和传统基于企业服务总线的架构所截然不同的是，HSF服务框架采用了去&#8220;中心化&#8221;的系统架构，服务的提供者和调用者都直接相连，这样的系统架构不仅去除了中心单点的风险，还能大大提高调用效率。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><img src="http://articles.csdn.net/uploads/allimg/150805/224_150805170531_1.png" width="299" border="0" height="227" alt="" style="vertical-align: middle; border: none; cursor: pointer;" /></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>鹰眼：分布式全链路跟踪系统</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS所提供的鹰眼跟踪系统，通过收集和分析在网络调用上的日志埋点，可以得到同一次请求上的各个系统的调用链关系，有助于梳理应用的请求入口与服务的调用来源、依赖关系，同时，也对分析系统调用瓶颈、估算链路容量、快速定位异常有很大帮助。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>全面的基础和应用监控</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS不仅提供了CPU、内存和Load等维度的基础监控指标，还提供了针对HTTP入口、提供HSF服务的调用QPS和消费HSF服务的调用QPS等应用层面的监控指标，帮助客户更为精准全面的对自己的系统进行监控。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>弹性伸缩</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS提供了手动和自动两种模式的弹性伸缩。通过全面的基础和应用监控，客户能够轻松的实现应用的扩容和缩容。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>限流降级/容量规划：打造健全的服务化体系</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">千万不要以为使用一套RPC框架就算是完成服务化的工作了&#8212;&#8212;这仅仅是服务化的冰山一角，尤其是针对企业级的大规模互联网应用，使用RPC框架进行系统的服务化改造后，所带来的服务治理的挑战，才是企业级系统服务化的开始。EDAS提供了一系列的服务治理工具，能够帮助企业级客户打造健全的服务化体系。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>限流降级</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">服务的限流能够帮助客户在面对大促的时候，从容的做到核心业务与非核心业务的区别对待，最大化的在服务的可用性和用户的体验性上达到平衡。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">服务的降级则能够帮助客户很好的规避由于依赖的服务不可用而引发的问题。当依赖的服务出现不可用情况，可以自定义的配置规则来确定对应的降级方案。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">这些限流降级工具都已经经受了多次双十一大促的考验。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>容量规划</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;">EDAS提供了特有的容量规划功能，通过自动压测，可以测算出当前系统的容量。同时，通过容量模型（当前系统容量、希望支撑的容量和当前应用机器数等）的建立，能够持续的对系统进行容量规划，这将方便客户对未来流量增长情况下，提前科学准确的预估出应用所需要的机器数。</p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><strong>EDAS核心功能展示</strong></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><img src="http://articles.csdn.net/uploads/allimg/150805/224_150805171413_1.png" width="612" border="0" height="512" alt="" style="vertical-align: middle; border: none; cursor: pointer;" /></p><p style="margin: 0px 0px 1.5em; padding: 0px; list-style: none;"><img src="http://articles.csdn.net/uploads/allimg/150805/224_150805171440_1.png" width="566" border="0" height="229" alt="" style="vertical-align: middle; border: none; cursor: pointer;" /></p><div></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/428600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-12-10 19:46 <a href="http://www.blogjava.net/xiaomage234/archive/2015/12/10/428600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dapper，大规模分布式系统的跟踪系统【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2015/12/10/428599.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 10 Dec 2015 11:45:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/12/10/428599.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428599.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/12/10/428599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428599.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428599.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者：Benjamin H. Sigelman, Luiz Andr&#180;e Barroso, Mike Burrows, Pat Stephenson, Manoj Plakal, Donald Beaver, Saul Jaspan, Chandan ShanbhagView project onGitHub概述当代的互联网的服务，通常都是用复杂的、大规模分布式集群来实现的。互联网应用构...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2015/12/10/428599.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/428599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-12-10 19:45 <a href="http://www.blogjava.net/xiaomage234/archive/2015/12/10/428599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZooKeeper Commands: The Four Letter Words</title><link>http://www.blogjava.net/xiaomage234/archive/2015/09/16/427348.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 16 Sep 2015 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/09/16/427348.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/427348.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/09/16/427348.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/427348.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/427348.html</trackback:ping><description><![CDATA[from：https://zookeeper.apache.org/doc/r3.4.6/zookeeperAdmin.html#sc_zkCommands<br /><br /><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em; font-family: Verdana, Helvetica, sans-serif; font-size: 12.8000001907349px; background-color: #ffffff;">ZooKeeper responds to a small set of commands. Each command is composed of four letters. You issue the commands to ZooKeeper via telnet or nc, at the client port.</p><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em; font-family: Verdana, Helvetica, sans-serif; font-size: 12.8000001907349px; background-color: #ffffff;">Three of the more interesting commands: "stat" gives some general information about the server and connected clients, while "srvr" and "cons" give extended details on server and connections respectively.</p><dl style="font-family: Verdana, Helvetica, sans-serif; font-size: 12.8000001907349px; line-height: normal; background-color: #ffffff;"><dt><term>conf</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;Print details about serving configuration.</p></dd><dt><term>cons</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;List full connection/session details for all clients connected to this server. Includes information on numbers of packets received/sent, session id, operation latencies, last operation performed, etc...</p></dd><dt><term>crst</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;Reset connection/session statistics for all connections.</p></dd><dt><term>dump</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">Lists the outstanding sessions and ephemeral nodes. This only works on the leader.</p></dd><dt><term>envi</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">Print details about serving environment</p></dd><dt><term>ruok</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">Tests if server is running in a non-error state. The server will respond with imok if it is running. Otherwise it will not respond at all.</p><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">A response of "imok" does not necessarily indicate that the server has joined the quorum, just that the server process is active and bound to the specified client port. Use "stat" for details on state wrt quorum and client connection information.</p></dd><dt><term>srst</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">Reset server statistics.</p></dd><dt><term>srvr</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;Lists full details for the server.</p></dd><dt><term>stat</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">Lists brief details for the server and connected clients.</p></dd><dt><term>wchs</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;Lists brief information on watches for the server.</p></dd><dt><term>wchc</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;Lists detailed information on watches for the server, by session. This outputs a list of sessions(connections) with associated watches (paths). Note, depending on the number of watches this operation may be expensive (ie impact server performance), use it carefully.</p></dd><dt><term>wchp</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.3.0:</strong>&nbsp;Lists detailed information on watches for the server, by path. This outputs a list of paths (znodes) with associated sessions. Note, depending on the number of watches this operation may be expensive (ie impact server performance), use it carefully.</p></dd><dt><term>mntr</term></dt><dd><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;"><strong>New in 3.4.0:</strong>&nbsp;Outputs a list of variables that could be used for monitoring the health of the cluster.</p><pre style="border-color: #a5b6c6; margin-left: 0em; padding: 0.5em; background-color: #f0f0f0;">$ echo mntr | nc localhost 2185  zk_version  3.4.0 zk_avg_latency  0 zk_max_latency  0 zk_min_latency  0 zk_packets_received 70 zk_packets_sent 69 zk_outstanding_requests 0 zk_server_state leader zk_znode_count   4 zk_watch_count  0 zk_ephemerals_count 0 zk_approximate_data_size    27 zk_followers    4                   - only exposed by the Leader zk_synced_followers 4               - only exposed by the Leader zk_pending_syncs    0               - only exposed by the Leader zk_open_file_descriptor_count 23    - only available on Unix platforms zk_max_file_descriptor_count 1024   - only available on Unix platforms </pre><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">The output is compatible with java properties format and the content may change over time (new keys added). Your scripts should expect changes.</p><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">ATTENTION: Some of the keys are platform specific and some of the keys are only exported by the Leader.</p><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em;">The output contains multiple lines with the following format:</p><pre style="border-color: #a5b6c6; margin-left: 0em; padding: 0.5em; background-color: #f0f0f0;">key \t value</pre></dd></dl><p style="line-height: 15.3599996566772px; margin-top: 0.5em; margin-bottom: 1em; font-family: Verdana, Helvetica, sans-serif; font-size: 12.8000001907349px; background-color: #ffffff;">Here's an example of the&nbsp;<strong>ruok</strong>&nbsp;command:</p><pre style="border-color: #a5b6c6; margin-left: 0em; padding: 0.5em; font-size: 12.8000001907349px; line-height: normal; background-color: #f0f0f0;">$ echo ruok | nc 127.0.0.1 5111 imok</pre><img src ="http://www.blogjava.net/xiaomage234/aggbug/427348.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-09-16 09:10 <a href="http://www.blogjava.net/xiaomage234/archive/2015/09/16/427348.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zookeeper原理</title><link>http://www.blogjava.net/xiaomage234/archive/2015/09/10/427251.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 10 Sep 2015 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/09/10/427251.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/427251.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/09/10/427251.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/427251.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/427251.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ZooKeeper是一个分布式的，开放源码的分布式应用程序协调服务，它包含一个简单的原语集，分布式应用程序可以基于它实现同步服务，配置维护和命名服务等。Zookeeper是hadoop的一个子项目，其发展历程无需赘述。在分布式应用中，由于工程师不能很好地使用锁机制，以及基于消息的协调机制不适合在某些应用中使用，因此需要有一种可靠的、可扩展的、分布式的、可配置的协调机制来统一系统的状态。Zookee...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2015/09/10/427251.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/427251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-09-10 17:55 <a href="http://www.blogjava.net/xiaomage234/archive/2015/09/10/427251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lvs之NAT、DR、TUN三种模式的应用配置案例[转]</title><link>http://www.blogjava.net/xiaomage234/archive/2015/09/02/427100.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 02 Sep 2015 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/09/02/427100.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/427100.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/09/02/427100.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/427100.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/427100.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:http://www.sxt.cn/u/324/blog/3188LVS一、LVS简介&nbsp;&nbsp;&nbsp;&nbsp;LVS是Linux Virtual Server的简写，意即Linux虚拟服务器，是一个虚拟服务器集群系统。本项目在1998年5月由章文嵩博士成立，是中国国内最早出现的自由软件之一。二、LVS的分类LVS-NAT：地址转换LVS-DR： 直接路由LVS-T...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2015/09/02/427100.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/427100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-09-02 16:07 <a href="http://www.blogjava.net/xiaomage234/archive/2015/09/02/427100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Redis实现分布式锁[转]</title><link>http://www.blogjava.net/xiaomage234/archive/2015/08/31/427057.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 31 Aug 2015 07:22:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/08/31/427057.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/427057.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/08/31/427057.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/427057.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/427057.html</trackback:ping><description><![CDATA[from:http://blog.csdn.net/ugg/article/details/41894947<br /><br /><br /><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 24px;"><strong>背景<br /></strong></span>在很多互联网产品应用中，有些场景需要加锁处理，比如：秒杀，全局递增ID，楼层生成等等。大部分的解决方案是基于DB实现的，Redis为单进程单线程模式，采用队列模式将并发访问变成串行访问，且多客户端对Redis的连接并不存在竞争关系。其次Redis提供一些命令SETNX，GETSET，可以方便实现分布式锁机制。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong><span style="font-size: 18px;">Redis命令介绍<br /></span></strong>使用Redis实现分布式锁，有两个重要函数需要介绍<br /><br />SETNX命令（SET if Not eXists）<br />语法：<br />SETNX key value<br />功能：<br />当且仅当 key 不存在，将 key 的值设为 value ，并返回1；若给定的 key 已经存在，则 SETNX 不做任何动作，并返回0。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">GETSET命令<br />语法：<br />GETSET key value<br />功能：<br />将给定 key 的值设为 value ，并返回 key 的旧值 (old value)，当 key 存在但不是字符串类型时，返回一个错误，当key不存在时，返回nil。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">GET命令<br />语法：<br />GET key<br />功能：<br />返回 key 所关联的字符串值，如果 key 不存在那么返回特殊值 nil 。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">DEL命令<br />语法：<br />DEL key [KEY &#8230;]<br />功能：<br />删除给定的一个或多个 key ,不存在的 key 会被忽略。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">兵贵精，不在多。分布式锁，我们就依靠这四个命令。但在具体实现，还有很多细节，需要仔细斟酌，因为在分布式并发多进程中，任何一点出现差错，都会导致死锁，hold住所有进程。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong><span style="font-size: 18px;">加锁实现</span></strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">SETNX 可以直接加锁操作，比如说对某个关键词foo加锁，客户端可以尝试<br />SETNX foo.lock &lt;current unix time&gt;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">如果返回1，表示客户端已经获取锁，可以往下操作，操作完成后，通过<br />DEL foo.lock</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">命令来释放锁。<br />如果返回0，说明foo已经被其他客户端上锁，如果锁是非堵塞的，可以选择返回调用。如果是堵塞调用调用，就需要进入以下个重试循环，直至成功获得锁或者重试超时。理想是美好的，现实是残酷的。仅仅使用SETNX加锁带有竞争条件的，在某些特定的情况会造成死锁错误。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">处理死锁</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">在上面的处理方式中，如果获取锁的客户端端执行时间过长，进程被kill掉，或者因为其他异常崩溃，导致无法释放锁，就会造成死锁。所以，需要对加锁要做时效性检测。因此，我们在加锁时，把当前时间戳作为value存入此锁中，通过当前时间戳和Redis中的时间戳进行对比，如果超过一定差值，认为锁已经时效，防止锁无限期的锁下去，但是，在大并发情况，如果同时检测锁失效，并简单粗暴的删除死锁，再通过SETNX上锁，可能会导致竞争条件的产生，即多个客户端同时获取锁。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">C1获取锁，并崩溃。C2和C3调用SETNX上锁返回0后，获得foo.lock的时间戳，通过比对时间戳，发现锁超时。<br />C2 向foo.lock发送DEL命令。<br />C2 向foo.lock发送SETNX获取锁。<br />C3 向foo.lock发送DEL命令，此时C3发送DEL时，其实DEL掉的是C2的锁。<br />C3 向foo.lock发送SETNX获取锁。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">此时C2和C3都获取了锁，产生竞争条件，如果在更高并发的情况，可能会有更多客户端获取锁。所以，DEL锁的操作，不能直接使用在锁超时的情况下，幸好我们有GETSET方法，假设我们现在有另外一个客户端C4，看看如何使用GETSET方式，避免这种情况产生。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">C1获取锁，并崩溃。C2和C3调用SETNX上锁返回0后，调用GET命令获得foo.lock的时间戳T1，通过比对时间戳，发现锁超时。<br />C4 向foo.lock发送GESET命令，<br />GETSET foo.lock &lt;current unix time&gt;<br />并得到foo.lock中老的时间戳T2</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">如果T1=T2，说明C4获得时间戳。<br />如果T1!=T2，说明C4之前有另外一个客户端C5通过调用GETSET方式获取了时间戳，C4未获得锁。只能sleep下，进入下次循环中。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">现在唯一的问题是，C4设置foo.lock的新时间戳，是否会对锁产生影响。其实我们可以看到C4和C5执行的时间差值极小，并且写入foo.lock中的都是有效时间错，所以对锁并没有影响。<br />为了让这个锁更加强壮，获取锁的客户端，应该在调用关键业务时，再次调用GET方法获取T1，和写入的T0时间戳进行对比，以免锁因其他情况被执行DEL意外解开而不知。以上步骤和情况，很容易从其他参考资料中看到。客户端处理和失败的情况非常复杂，不仅仅是崩溃这么简单，还可能是客户端因为某些操作被阻塞了相当长时间，紧接着 DEL 命令被尝试执行(但这时锁却在另外的客户端手上)。也可能因为处理不当，导致死锁。还有可能因为sleep设置不合理，导致Redis在大并发下被压垮。最为常见的问题还有</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-weight: bold;">GET返回nil时应该走那种逻辑？</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">第一种走超时逻辑<br />C1客户端获取锁，并且处理完后，DEL掉锁，在DEL锁之前。C2通过SETNX向foo.lock设置时间戳T0 发现有客户端获取锁，进入GET操作。<br />C2 向foo.lock发送GET命令，获取返回值T1(nil)。<br />C2 通过T0&gt;T1+expire对比，进入GETSET流程。<br />C2 调用GETSET向foo.lock发送T0时间戳，返回foo.lock的原值T2<br />C2 如果T2=T1相等，获得锁，如果T2!=T1，未获得锁。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">第二种情况走循环走setnx逻辑<br />C1客户端获取锁，并且处理完后，DEL掉锁，在DEL锁之前。C2通过SETNX向foo.lock设置时间戳T0 发现有客户端获取锁，进入GET操作。<br />C2 向foo.lock发送GET命令，获取返回值T1(nil)。<br />C2 循环，进入下一次SETNX逻辑</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">两种逻辑貌似都是OK，但是从逻辑处理上来说，第一种情况存在问题。当GET返回nil表示，锁是被删除的，而不是超时，应该走SETNX逻辑加锁。走第一种情况的问题是，正常的加锁逻辑应该走SETNX，而现在当锁被解除后，走的是GETST，如果判断条件不当，就会引起死锁，很悲催，我在做的时候就碰到了，具体怎么碰到的看下面的问题</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-weight: bold;">GETSET返回nil时应该怎么处理？</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">C1和C2客户端调用GET接口，C1返回T1，此时C3网络情况更好，快速进入获取锁，并执行DEL删除锁，C2返回T2(nil)，C1和C2都进入超时处理逻辑。<br />C1 向foo.lock发送GETSET命令，获取返回值T11(nil)。<br />C1 比对C1和C11发现两者不同，处理逻辑认为未获取锁。<br />C2 向foo.lock发送GETSET命令，获取返回值T22(C1写入的时间戳)。<br />C2 比对C2和C22发现两者不同，处理逻辑认为未获取锁。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">此时C1和C2都认为未获取锁，其实C1是已经获取锁了，但是他的处理逻辑没有考虑GETSET返回nil的情况，只是单纯的用GET和GETSET值就行对比，至于为什么会出现这种情况？一种是多客户端时，每个客户端连接Redis的后，发出的命令并不是连续的，导致从单客户端看到的好像连续的命令，到Redis server后，这两条命令之间可能已经插入大量的其他客户端发出的命令，比如DEL,SETNX等。第二种情况，多客户端之间时间不同步，或者不是严格意义的同步。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-weight: bold;">时间戳的问题</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">我们看到foo.lock的value值为时间戳，所以要在多客户端情况下，保证锁有效，一定要同步各服务器的时间，如果各服务器间，时间有差异。时间不一致的客户端，在判断锁超时，就会出现偏差，从而产生竞争条件。<br />锁的超时与否，严格依赖时间戳，时间戳本身也是有精度限制，假如我们的时间精度为秒，从加锁到执行操作再到解锁，一般操作肯定都能在一秒内完成。这样的话，我们上面的CASE，就很容易出现。所以，最好把时间精度提升到毫秒级。这样的话，可以保证毫秒级别的锁是安全的。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">分布式锁的问题</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">1：必要的超时机制：获取锁的客户端一旦崩溃，一定要有过期机制，否则其他客户端都降无法获取锁，造成死锁问题。<br />2：分布式锁，多客户端的时间戳不能保证严格意义的一致性，所以在某些特定因素下，有可能存在锁串的情况。要适度的机制，可以承受小概率的事件产生。<br />3：只对关键处理节点加锁，良好的习惯是，把相关的资源准备好，比如连接数据库后，调用加锁机制获取锁，直接进行操作，然后释放，尽量减少持有锁的时间。<br />4：在持有锁期间要不要CHECK锁，如果需要严格依赖锁的状态，最好在关键步骤中做锁的CHECK检查机制，但是根据我们的测试发现，在大并发时，每一次CHECK锁操作，都要消耗掉几个毫秒，而我们的整个持锁处理逻辑才不到10毫秒，玩客没有选择做锁的检查。<br />5：sleep学问，为了减少对Redis的压力，获取锁尝试时，循环之间一定要做sleep操作。但是sleep时间是多少是门学问。需要根据自己的Redis的QPS，加上持锁处理时间等进行合理计算。<br />6：至于为什么不使用Redis的muti，expire，watch等机制，可以查一参考资料，找下原因。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 18px;">锁测试数据</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>未使用sleep</strong><br />第一种，锁重试时未做sleep。单次请求，加锁，执行，解锁时间&nbsp;<br /><img src="http://img.blog.csdn.net/20141212162927906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdWdn/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />可以看到加锁和解锁时间都很快，当我们使用</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">ab -n1000 -c100 'http://sandbox6.wanke.etao.com/test/test_sequence.php?tbpm=t'<br />AB 并发100累计1000次请求，对这个方法进行压测时。&nbsp;<br /><img src="http://img.blog.csdn.net/20141212162944369" alt="" style="border: none; max-width: 100%;" /><br /><br />我们会发现，获取锁的时间变成，同时持有锁后，执行时间也变成，而delete锁的时间，将近10ms时间，为什么会这样？<br />1：持有锁后，我们的执行逻辑中包含了再次调用Redis操作，在大并发情况下，Redis执行明显变慢。<br />2：锁的删除时间变长，从之前的0.2ms，变成9.8ms，性能下降近50倍。<br />在这种情况下，我们压测的QPS为49，最终发现QPS和压测总量有关，当我们并发100总共100次请求时，QPS得到110多。当我们使用sleep时</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>使用Sleep时</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">单次执行请求时<br /><img src="http://img.blog.csdn.net/20141212163004664" alt="" style="border: none; max-width: 100%;" /><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">我们看到，和不使用sleep机制时，性能相当。当时用相同的压测条件进行压缩时&nbsp;<br /><img src="http://img.blog.csdn.net/20141212163101609" alt="" style="border: none; max-width: 100%;" /><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">获取锁的时间明显变长，而锁的释放时间明显变短，仅是不采用sleep机制的一半。当然执行时间变成就是因为，我们在执行过程中，重新创建数据库连接，导致时间变长的。同时我们可以对比下Redis的命令执行压力情况&nbsp;<br /><img src="http://img.blog.csdn.net/20141212163043992" alt="" style="border: none; max-width: 100%;" /><br />上图中细高部分是为未采用sleep机制的时的压测图，矮胖部分为采用sleep机制的压测图，通上图看到压力减少50%左右，当然，sleep这种方式还有个缺点QPS下降明显，在我们的压测条件下，仅为35，并且有部分请求出现超时情况。不过综合各种情况后，我们还是决定采用sleep机制，主要是为了防止在大并发情况下把Redis压垮，很不行，我们之前碰到过，所以肯定会采用sleep机制。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong><span style="font-size: 18px;">参考资料</span></strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><a target="_blank" href="http://www.worlduc.com/FileSystem/18/2518/590664/9f63555e6079482f831c8ab1dcb8c19c.pdf" style="color: #336699; text-decoration: none;">http://www.worlduc.com/FileSystem/18/2518/590664/9f63555e6079482f831c8ab1dcb8c19c.pdf</a><br /><a target="_blank" href="http://redis.io/commands/setnx" style="color: #336699; text-decoration: none;">http://redis.io/commands/setnx</a><br /><a target="_blank" href="http://www.blogjava.net/caojianhua/archive/2013/01/28/394847.html" style="color: #336699; text-decoration: none;">http://www.blogjava.net/caojianhua/archive/2013/01/28/394847.html</a></p><div style="color: #333333; font-family: Arial; line-height: 26px; padding-top: 20px; background-color: #ffffff;"><p style="font-size: 12px;">版权声明：本文为博主原创文章，未经博主允许不得转载。</p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/427057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-08-31 15:22 <a href="http://www.blogjava.net/xiaomage234/archive/2015/08/31/427057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大型分布式系统案例实战学习</title><link>http://www.blogjava.net/xiaomage234/archive/2015/04/13/424356.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 13 Apr 2015 02:23:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/04/13/424356.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/424356.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/04/13/424356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/424356.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/424356.html</trackback:ping><description><![CDATA[<div>看了dataguru网站的介绍，这个 《大型分布式系统案例实战学习》貌似还可以，2015.5.6开课，已经报名，系统理一下知识点。<br /><br />也作为使用了mycat开源工具的回报：） 另外这个逆向学习收费模式还挺有意思的<br /><br /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12pt; line-height: 25px; background-color: #f1f1f1;">如果对Dataguru的课程有兴趣，<strong><a href="http://www.dataguru.cn/invite.php?lessonid=379&amp;invitecode=V5M5">报名</a></strong>的时候可以填写我的优惠码 V5M5，能立减50%的固定学费！</span><div><br /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">课程大纲：</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第1课 大型分布式系统原理概述</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">结合业界主流的那些开源软件，介绍和分析分布式系统的基本架构，组成部分，和实现原理。几款常用的软件以及功能功能性对比。</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第2课 分布式系统之网络篇</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Zookeeper入门</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Zookeeper原理: Zookeeper原理介绍</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Curator客户端 : 对Zookeeper知名客户端Curator进行介绍，初步掌握其编程方式和用法。</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">迷你P2P网络服务案例: 采用Zookeeper打造一个迷你P2P网络系统，节点之间相互交换名片，并且实现动态路由（节点宕机后其他节点自动感知并更新链路状态），</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第3课&nbsp;&nbsp;分布式存储-文件系统篇</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">传统的分布式文件系统：Lustre、GlusterFS等经典分布式文件系统分析</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">新型分布式文件系统：介绍Ceph以及它跟Openstack的关系</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">互联网领域中的小文件系统：GridFS、FastDFS、TFS等分析学习</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第4课 分布式存储-内存篇</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Hazelcast 详解与分析</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">GridGain详解与分析</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">MemCache详解与分析</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">案例集锦：分布式系统存储之基于内存的两表Join演示</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第5课 分布式存储-数据库篇</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">分布式数据库原理 ：介绍分布式数据库的实现原理，特性、优缺点、以及难点、热点问题</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Mycat前世今生：介绍目前基于MYSQL的热门开源数据库血统，包括Cobar、tddl、Amoeba、以及目前很火的Mycat</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">案例集锦：某大型网站每天1亿数据处的案例剖析</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第6课 分布式系统之云计算篇</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">主机虚拟化：介绍主机虚拟化的技术</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">网络虚拟化：介绍网络虚拟化的技术</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">存储虚拟化：介绍存储虚拟化的技术</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">云计算实践：VirtualBox虚机集群搭建</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Openstack原理介绍：介绍Openstack的体系、架构、以及基本功能</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">案例集锦：基于RDO实现Openstack的安装、部署等。</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第7课 分布式计算框架</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Map-Reduce原理：介绍Map-Reduce的原理以及限制问题</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Apache　Storm应用：学习Storm的原理并搭建测试环境，掌握基本编程</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">案例集锦：实现基于Storm的１０００万&#215;１０００万的SQL　Join和排序分页</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第8课 通信机制的设计与实现</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">分布式通信机制概述：讲解分布式通信的几种常见机制，RPC调用、共享远程数据、消息队列等。</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">RPC通信机制的原理 讲解RPC通信机制的原理和实现方式：</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">案例集锦：设计并实现一个XML-RPC框架 动手设计和实现一个简单的XML-RPC框架</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第9课 消息队列</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">消息队列机制介绍: 介绍古典的和新型的消息队列机制的相同点和不同点</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">消息队列通信的案例分析: 对一些采用消息队列通信的系统做分析，掌握消息队列用作分布式通信的一般设计原则</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">案例集锦：对知名开源消息中间件Kafka做一个入门学习，并动手完成一个实际编程案例</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第10课 打造高可用系统（上）</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">高可用系统常规方案：介绍高可用系统的一些原理、实现机制、常规实现方案，包括基于硬件、软件中间件、系统架构等一些典型方案的实现</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">HA　Proxy入门：介绍业界常规的HA　Proxy的原理以及用法</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">实践篇：Java开发一个类似HA Proxy的代理中间件</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第11课 打造高可用系统（下）</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">高可用集群套件中间件：介绍基于Corosync+Pacemaker的高可用集群套件中间件系统的原理、配置以及常见案例</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Corosync技术；&nbsp;</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Pacemaker技术；</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Pacemaker实践：实现基于Pacemaker的MYSQL高可用方案。</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第12课 Mycat架构的分布式演进背后的秘密</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">配置文件的分布式访问问题：为什么最终选择了Zookeeper</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Mycat负载均衡的特殊性：为什么标准的HA Proxy还无法满足Mycat的负载均衡要求</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">大数据Join背后的难题：数据、网络、内存和计算能力的矛盾和调和</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第13课 Java分布式系统中的高性能难题</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">高性能网络框架的难题：AIO，NIO，Netty还是自己开发框架</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">堆内和堆外存储：堆内与堆外存储的差别，开源的堆外存储组件为何凤毛麟角</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">高性能事件派发机制：线程池模型的性能问题以及不为人知的Disruptor模型</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第14课 挑战自我&#8212;&#8212;全栈架构师实践</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">本节课程的目标，是挑战自我，开发一个基于Zeroc ICE+Zookeeper+Mycat+Android App+ Web系统的&#8220;身边购&#8221;平台，目标是支持1亿用户，每天交易订单为1亿，商家自己在手机上通过Appp注册自己的店铺，店铺包括地理位置信息，后台审批通过，然后可以拍照上架自己的货物，定价，发售。用户登录App以后，根据其地理位置信息，显示附近的（默认3公里）新品、热门商品、二手商品等，并可以下单。</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">授课时间：</span><br style="word-wrap: break-word; color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;" /><span style="color: #444444; font-family: 微软雅黑, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">第一期课程预计2015年5月6日开课，预计课程持续时间为16周。</span></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/424356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-04-13 10:23 <a href="http://www.blogjava.net/xiaomage234/archive/2015/04/13/424356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>redis 3.0的集群部署</title><link>http://www.blogjava.net/xiaomage234/archive/2015/04/03/424091.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 03 Apr 2015 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/04/03/424091.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/424091.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/04/03/424091.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/424091.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/424091.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:http://blog.csdn.net/myrainblues/article/details/25881535最近研究redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到redis3 release出来后，换掉memCache 集群.一:关于redis cluster1:redis cluster的现状reids-cluster计划在redis3.0中推出...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2015/04/03/424091.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/424091.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-04-03 11:00 <a href="http://www.blogjava.net/xiaomage234/archive/2015/04/03/424091.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>13 款开源的全文搜索引擎［转］</title><link>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423495.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 16 Mar 2015 10:37:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423495.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/423495.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423495.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/423495.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/423495.html</trackback:ping><description><![CDATA[<article id="post-detail-14" post="" type-post="" status-publish="" format-standard="" hentry=""  category-uncategorized"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; line-height: 14px; background-color: #ffffff;"><div style="margin: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><div id="mid-content" style="margin: 10px; border: 0px; vertical-align: baseline;"><div id="h-0" style="margin: 0px; border: 0px; vertical-align: baseline;"><h3><span style="color: #333333; font-size: 1rem; line-height: 1.714285714;">本文转载自</span><a href="http://blog.csdn.net/xum2008/article/details/8740063" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">xum2008的博客</a><span style="color: #333333; font-size: 1rem; line-height: 1.714285714;">，主要介绍13款现有的开源搜索引擎，你可以将它们用在你的项目中以实现检索功能。&nbsp;</span></h3></div><div clearfix"="" style="margin: 0px; border: 0px; font-size: 1rem; vertical-align: baseline; color: #333333;"><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">1.&nbsp; Lucene</strong>&nbsp;<br /><br />Lucene的开发语言是Java，也是Java家族中最为出名的一个开源搜索引擎，在Java世界中已经是标准的全文检索程序，它提供了完整的查询引擎和索引引擎，没有中文分词引擎，需要自己去实现，因此用Lucene去做一个搜素引擎需要自己去架构.另外它不支持实时搜索，但linkedin和twitter有分别对Lucene改进的实时搜素. 其中Lucene有一个C++移植版本叫CLucene，CLucene因为使用C++编写，所以理论上要比lucene快.&nbsp;<br /><br />官方主页：<a href="http://lucene.apache.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://lucene.apache.org/</a>&nbsp;<br /><br />CLucene官方主页：<a href="http://sourceforge.net/projects/clucene/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://sourceforge.net/projects/clucene/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">2.&nbsp; Sphinx</strong>&nbsp;<br /><br />Sphinx是一个用C++语言写的开源搜索引擎，也是现在比较主流的搜索引擎之一，在建立索引的事件方面比Lucene快50%，但是索引文件比Lucene要大一倍，因此Sphinx在索引的建立方面是空间换取事件的策略，在检索速度上，和lucene相差不大，但检索精准度方面Lucene要优于Sphinx，另外在加入中文分词引擎难度方面，Lucene要优于Sphinx.其中Sphinx支持实时搜索，使用起来比较简单方便.&nbsp;<br /><br />官方主页：<a href="http://sphinxsearch.com/about/sphinx/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://sphinxsearch.com/about/sphinx/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">3.&nbsp; Xapian</strong>&nbsp;<br /><br />Xapian是一个用C++编写的全文检索程序，它的api和检索原理和lucene在很多方面都很相似，算是填补了lucene在C++中的一个空缺.&nbsp;<br /><br />官方主页：<a href="http://xapian.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://xapian.org/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">4.&nbsp; Nutch</strong>&nbsp;<br /><br />Nutch是一个用java实现的开源的web搜索引擎，包括爬虫crawler，索引引擎，查询引擎. 其中Nutch是基于Lucene的，Lucene为Nutch提供了文本索引和搜索的API.&nbsp;<br /><br />对于应该使用Lucene还是使用Nutch，应该是如果你不需要抓取数据的话，应该使用Lucene，最常见的应用是：你有数据源，需要为这些数据提供一个搜索页面，在这种情况下，最好的方式是直接从数据库中取出数据，并用Lucene API建立索引.&nbsp;<br /><br />官方主页：<a href="http://nutch.apache.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://nutch.apache.org/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">5.&nbsp; DataparkSearch</strong>&nbsp;<br /><br />DataparkSearch是一个用C语言实现的开源的搜索引擎. 其中网页排序是采用神经网络模型.&nbsp; 其中支持HTTP，HTTPS，FTP，NNTP等下载网页.包括索引引擎，检索引擎和中文分词引擎(这个也是唯一的一个开源的搜索引擎里有中文分词引擎).能个性化定制搜索结果，拥有完整的日志记录.&nbsp;<br /><br />官方主页：<a href="http://www.dataparksearch.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://www.dataparksearch.org/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">6.&nbsp; Zettair</strong>&nbsp;<br /><br />Zettair是根据Justin Zobel的研究成果为基础的全文检索实验系统.它是用C语言实现的. 其中Justin Zobel在全文检索领域很有名气，是业界第一个系统提出倒排序索引差分压缩算法的人，倒排列表的压缩大大提高了检索和加载的性能，同时空间膨胀率也缩小到相当优秀的水平. 由于Zettair是源于学术界，代码是由RMIT University的搜索引擎组织写的，因此它的代码简洁精炼，算法高效，是学习倒排索引经典算法的非常好的实例. 其中支持linux，windows，mac os等系统.&nbsp;<br /><br />官方主页：<a href="http://www.seg.rmit.edu.au/zettair/about.html" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://www.seg.rmit.edu.au/zettair/about.html</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">7.&nbsp; Indri</strong>&nbsp;<br /><br />Indri是一个用C语言和C++语言写的全文检索引擎系统，是由University of Massachusetts和Carnegie Mellon University合作推出的一个开源项目. 特点是跨平台，API接口支持Java，PHP，C++.&nbsp;<br /><br />官方主页：<a href="http://www.lemurproject.org/indri/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://www.lemurproject.org/indri/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">8.&nbsp; Terrier</strong>&nbsp;<br /><br />Terrier是由School of Computing Science，Universityof Glasgow用java开发的一个全文检索系统.&nbsp;<br /><br />官方主页：<a href="http://terrier.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://terrier.org/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">9.&nbsp; Galago</strong>&nbsp;<br /><br />Galago是一个用java语言写的关于文本搜索的工具集. 其中包括索引引擎和查询引擎，还包括一个叫TupleFlow的分布式计算框架(和google的MapReduce很像).这个检索系统支持很多Indri查询语言.&nbsp;<br /><br />官方主页：<a href="http://www.galagosearch.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://www.galagosearch.org/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">10.&nbsp; Zebra</strong>&nbsp;<br /><br />Zebra是一个用C语言实现的检索程序，特点是对大数据的支持，支持EMAIL，XML，MARC等格式的数据.&nbsp;<br /><br />官方主页：<a href="https://www.indexdata.com/zebra" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">https://www.indexdata.com/zebra</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">11.&nbsp; Solr</strong>&nbsp;<br /><br />Solr是一个用java开发的独立的企业级搜索应用服务器，它提供了类似于Web-service的API接口，它是基于Lucene的全文检索服务器，也算是Lucene的一个变种，很多一线互联网公司都在使用Solr，也算是一种成熟的解决方案.&nbsp;<br /><br />官方主页：<a href="http://lucene.apache.org/solr/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://lucene.apache.org/solr/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">12.&nbsp; Elasticsearch</strong>&nbsp;<br /><br />Elasticsearch是一个采用java语言开发的，基于Lucene构造的开源，分布式的搜索引擎. 设计用于云计算中，能够达到实时搜索，稳定可靠. Elasticsearch的数据模型是JSON.&nbsp;<br /><br />官方主页：<a href="http://www.elasticsearch.org/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">http://www.elasticsearch.org/</a>&nbsp;<br /><br /><strong style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline;">13.&nbsp; Whoosh</strong>&nbsp;<br /><br />Whoosh是一个用纯python写的开源搜索引擎.&nbsp;<br /><br />官方主页：<a href="https://bitbucket.org/mchaput/whoosh/wiki/Home" target="_blank" style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; vertical-align: baseline; outline: none; color: #9f9f9f; text-decoration: none;">https://bitbucket.org/mchaput/whoosh/wiki/Home</a>&nbsp;　</div></div><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 16px; vertical-align: baseline; line-height: 1.6;"></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 16px; vertical-align: baseline; line-height: 1.6;"></p></div><footer style="margin: 1.714285714rem 0px 12px; padding: 0px; border: 0px; font-size: 0.928571429rem; vertical-align: baseline; color: #757575; clear: both; line-height: 1.846153846;">发布在[ 技术 ]&nbsp;<a href="http://songwie.com/articlelist/14#" title="" rel="bookmark" style="margin: 0px; padding: 0px; border-width: 0px 0px 1px; border-bottom-style: dotted; border-bottom-color: #cccccc; font-size: 13px; vertical-align: baseline; outline: none; color: #757575; text-decoration: none;"><time datetime="2014/12/06 21:07:33" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2014-12-30 12:00:00.0</time></a>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline;">by&nbsp;<span vcard"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><a fn=""  n"="" href="http://www.songwie.com/blog/author/1" title="" rel="author" style="margin: 0px; padding: 0px; border-width: 0px 0px 1px; border-bottom-style: dotted; border-bottom-color: #cccccc; vertical-align: baseline; outline: none; color: #757575; text-decoration: none;">从零开始</a></span></span></footer></article><nav id="nav-single" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; line-height: 14px; background-color: #ffffff;"><h3>Post navigation</h3><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; float: left; width: 480px;">上一篇<a href="http://songwie.com/articlelist/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #0f3647; text-decoration: none;"></a></span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; float: right; text-align: right; width: 480px;">下一篇<a href="http://songwie.com/articlelist/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #0f3647; text-decoration: none;"></a></span></nav><div id="comments" style="margin: 3.428571429rem 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; line-height: 14px; background-color: #ffffff;"><ol style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; list-style: none;"><div style="margin: 20px 0px 0px; border: 0px; vertical-align: baseline; min-height: 20px;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><div style="margin: 0px 0px 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; border-width: 0px 0px 1px; border-bottom-style: dashed; border-bottom-color: #cccccc; vertical-align: baseline; min-height: 50px;"><img avatar"="" alt="" src="http://songwie.com/resources/img/reply.png" style="margin: 0px 10px 20px 0px; padding: 0px; border: 0px; vertical-align: top; border-radius: 6px; width: 42px; height: 42px; float: left;" /><div id="comment-42" style="margin: 0px 0px 0px 35px; padding-left: 5px; border: 0px; vertical-align: baseline;"><div style="margin: 0px; border: 0px; vertical-align: baseline;"><a href="http://songwie.com/articlelist/article/reply/14#42" rel="external nofollow" style="margin: 0px; padding: 0px; border: 0px; font-size: 1em; vertical-align: baseline; outline: none; color: #0f3647; text-decoration: none; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; line-height: 1.5em;">不错</a>&nbsp;<span style="margin: 0px 0px 0px 10px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline; color: #999999;"><a href="http://songwie.com/articlelist/article/reply/14#42" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #0f3647; text-decoration: none;"><time datetime="2014/12/09 09:24:13" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">在2014-12-30 18:12:42.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</time></a></span><span style="margin: 0px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline; color: #999999;"><a href="http://songwie.com/articlelist/article/reply/14#42" style="margin: 0px; padding: 0px; border: 0px; font-size: 0.928571429rem; vertical-align: baseline; outline: none; color: #686868; text-decoration: none; line-height: 1.846153846;"><span fa-comment-o=""  "="" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; display: inline-block; font-family: FontAwesome; line-height: 1; -webkit-font-smoothing: antialiased;">回复</span></a></span></div><div style="margin: 5px 0px 0px; border: 0px; vertical-align: baseline; word-break: break-all; color: #333333;">不错</div></div></div></li></div></ol><ol style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; list-style: none;"><div style="margin: 20px 0px 0px; border: 0px; vertical-align: baseline; min-height: 20px;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><div style="margin: 0px 0px 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; border-width: 0px 0px 1px; border-bottom-style: dashed; border-bottom-color: #cccccc; vertical-align: baseline; min-height: 50px;"><img avatar"="" alt="" src="http://songwie.com/resources/img/reply.png" style="margin: 0px 10px 20px 0px; padding: 0px; border: 0px; vertical-align: top; border-radius: 6px; width: 42px; height: 42px; float: left;" /><div id="comment-943" style="margin: 0px 0px 0px 35px; padding-left: 5px; border: 0px; vertical-align: baseline;"><div style="margin: 0px; border: 0px; vertical-align: baseline;"><a href="http://songwie.com/articlelist/article/reply/14#943" rel="external nofollow" style="margin: 0px; padding: 0px; border: 0px; font-size: 1em; vertical-align: baseline; outline: none; color: #0f3647; text-decoration: none; font-weight: bold; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; line-height: 1.5em;"></a><span style="margin: 0px 0px 0px 10px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline; color: #999999;"><a href="http://songwie.com/articlelist/article/reply/14#943" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #0f3647; text-decoration: none;"><time datetime="2014/12/09 09:24:13" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">在2015-03-16 18:18:40.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</time></a></span><span style="margin: 0px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline; color: #999999;"><a href="http://songwie.com/articlelist/article/reply/14#943" style="margin: 0px; padding: 0px; border: 0px; font-size: 0.928571429rem; vertical-align: baseline; outline: none; color: #686868; text-decoration: none; line-height: 1.846153846;"><span fa-comment-o=""  "="" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; display: inline-block; font-family: FontAwesome; line-height: 1; -webkit-font-smoothing: antialiased;">回复</span></a></span></div><div style="margin: 5px 0px 0px; border: 0px; vertical-align: baseline; word-break: break-all; color: #333333;">增加一个，SolrCloud是基于Solr和Zookeeper的分布式搜索方案，是正在开发中的Solr4.0的核心组件之一，它的主要思想是使用Zookeeper作为集群的配置信息中心。它有几个特色功能：1）集中式的配置信息 2）自动容错 3）近实时搜索 4）查询时自动负载均衡</div></div></div></li></div></ol></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/423495.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-03-16 18:37 <a href="http://www.blogjava.net/xiaomage234/archive/2015/03/16/423495.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mycat分布式mysql中间件（数据库切分概述）[转]</title><link>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 16 Mar 2015 10:27:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/423493.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/423493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/423493.html</trackback:ping><description><![CDATA[from:http://songwie.com/articlelist/21<br /><br /><div style="margin: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714; color: #444444; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; background-color: #ffffff;"><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">mysql数据库切分</span></strong></h2><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">前言</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过MySQLReplication功能所实现的扩展总是会受到数据库大小的限制，一旦数据库过于庞大，尤其是当写入过于频繁，很难由一台主机支撑的时候，我们还是会面临到扩展瓶颈。这时候，我们就必须许找其他技术手段来解决这个瓶颈，那就是我们这一章所要介绍恶的数据切分技术。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">何谓数据切分</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">可能很多读者朋友在网上或者杂志上面都已经多次见到关于数据切分的相关文章了，只不过在有些文章中称之为数据的Sharding。其实不管是称之为数据的Sharding还是数据的切分，其概念都是一样的。简单来说，就是指通过某种特定的条件，将我们存放在同一个数据库中的数据分散存放到多个数据库（主机）上面，以达到分散单台设备负载的效果。数据的切分同时还可以提高系统的总体可用性，因为单台设备Crash之后，只有总体数据的某部分不可用，而不是所有的数据。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">数据的切分（Sharding）根据其切分规则的类型，可以分为两种切分模式。一种是按照不同的表（或者Schema）来切分到不同的数据库（主机）之上，这种切可以称之为数据的垂直（纵向）切分；另外一种则是根据表中的数据的逻辑关系，将同一个表中的数据按照某种条件拆分到多台数据库（主机）上面，这种切分称之为数据的水平（横向）切分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">垂直切分的最大特点就是规则简单，实施也更为方便，尤其适合各业务之间的耦合度非常低，相互影响很小，业务逻辑非常清晰的系统。在这种系统中，可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。根据不同的表来进行拆分，对应用程序的影响也更小，拆分规则也会比较简单清晰。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">水平切分于垂直切分相比，相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的数据库中，对于应用程序来说，拆分规则本身就较根据表名来拆分更为复杂，后期的数据维护也会更为复杂一些。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当我们某个（或者某些）表的数据量和访问量特别的大，通过垂直切分将其放在独立的设备上后仍然无法满足性能要求，这时候我们就必须将垂直切分和水平切分相结合，先垂直切分，然后再水平切分，才能解决这种超大型表的性能问题。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">下面我们就针对垂直、水平以及组合切分这三种数据切分方式的架构实现及切分后数据的整合进行相应的分析。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据的垂直切分</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">我们先来看一下，数据的垂直切分到底是如何一个切分法的。数据的垂直切分，也可以称之为纵向切分。将数据库想象成为由很多个一大块一大块的&#8220;数据块&#8221;（表）组成，我们垂直的将这些&#8220;数据块&#8221;切开，然后将他们分散到多台数据库主机上面。这样的切分方法就是一个垂直（纵向）的数据切分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一个架构设计较好的应用系统，其总体功能肯定是由很多个功能模块所组成的，而每一个功能模块所需要的数据对应到数据库中就是一个或者多个表。而在架构设计中，各个功能模块相互之间的交互点越统一越少，系统的耦合度就越低，系统各个模块的维护性以及扩展性也就越好。这样的系统，实现数据的垂直切分也就越容易。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当我们的功能模块越清晰，耦合度越低，数据垂直切分的规则定义也就越容易。完全可以根据功能模块来进行数据的切分，不同功能模块的数据存放于不同的数据库主机中，可以很容易就避免掉跨数据库的Join存在，同时系统架构也非常的清晰。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然，很难有系统能够做到所有功能模块所使用的表完全独立，完全不需要访问对方的表或者需要两个模块的表进行Join操作。这种情况下，我们就必须根据实际的应用场景进行评估权衡。决定是迁就应用程序将需要Join的表的相关某快都存放在同一个数据库中，还是让应用程序做更多的事情，也就是程序完全通过模块接口取得不同数据库中的数据，然后在程序中完成Join操作。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一般来说，如果是一个负载相对不是很大的系统，而且表关联又非常的频繁，那可能数据库让步，将几个相关模块合并在一起减少应用程序的工作的方案可以减少较多的工作量，是一个可行的方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然，通过数据库的让步，让多个模块集中共用数据源，实际上也是简介的默许了各模块架构耦合度增大的发展，可能会让以后的架构越来越恶化。尤其是当发展到一定阶段之后，发现数据库实在无法承担这些表所带来的压力，不得不面临再次切分的时候，所带来的架构改造成本可能会远远大于最初的时候。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，在数据库进行垂直切分的时候，如何切分，切分到什么样的程度，是一个比较考验人的难题。只能在实际的应用场景中通过平衡各方面的成本和收益，才能分析出一个真正适合自己的拆分方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">比如在本书所使用示例系统的example数据库，我们简单的分析一下，然后再设计一个简单的切分规则，进行一次垂直垂直拆分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">系统功能可以基本分为四个功能模块：用户，群组消息，相册以及事件，分别对应为如下这些表：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 用户模块表：user,user_profile,user_group,user_photo_album</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2. 群组讨论表：groups,group_message,group_message_content,top_message</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">3. 相册相关表：photo,photo_album,photo_album_relation,photo_comment</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">4. 事件信息表：event</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">初略一看，没有哪一个模块可以脱离其他模块独立存在，模块与模块之间都存在着关系，莫非无法切分？</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然不是，我们再稍微深入分析一下，可以发现，虽然各个模块所使用的表之间都有关联，但是关联关系还算比较清晰，也比较简单。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;群组讨论模块和用户模块之间主要存在通过用户或者是群组关系来进行关联。一般关联的时候都会是通过用户的id或者nick_name以及group的id来进行关联，通过模块之间的接口实现不会带来太多麻烦；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;相册模块仅仅与用户模块存在通过用户的关联。这两个模块之间的关联基本就有通过用户id关联的内容，简单清晰，接口明确；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 事件模块与各个模块可能都有关联，但是都只关注其各个模块中对象的ID信息，同样可以做到很容易分拆。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，我们第一步可以将数据库按照功能模块相关的表进行一次垂直拆分，每个模块所涉及的表单独到一个数据库中，模块与模块之间的表关联都在应用系统端通过藉口来处理。如下图所示：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194849_11.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194120_831.jpg" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过这样的垂直切分之后，之前只能通过一个数据库来提供的服务，就被分拆成四个数据库来提供服务，服务能力自然是增加几倍了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">垂直切分的优点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 数据库的拆分简单明了，拆分规则明确；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用程序模块清晰明确，整合容易；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 数据维护方便易行，容易定位；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">垂直切分的缺点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 部分表关联无法在数据库级别完成，需要在程序中完成；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 对于访问极其频繁且数据量超大的表仍然存在性能平静，不一定能满足要求；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 事务处理相对更为复杂；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 切分达到一定程度之后，扩展性会遇到限制；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 过读切分可能会带来系统过渡复杂而难以维护。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">针对于垂直切分可能遇到数据切分及事务问题，在数据库层面实在是很难找到一个较好的处理方案。实际应用案例中，数据库的垂直切分大多是与应用系统的模块相对应，同一个模块的数据源存放于同一个数据库中，可以解决模块内部的数据关联问题。而模块与模块之间，则通过应用程序以服务接口方式来相互提供所需要的数据。虽然这样做在数据库的总体操作次数方面确实会有所增加，但是在系统整体扩展性以及架构模块化方面，都是有益的。可能在某些操作的单次响应时间会稍有增加，但是系统的整体性能很可能反而会有一定的提升。而扩展瓶颈问题，就只能依靠下一节将要介绍的数据水平切分架构来解决了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据的水平切分</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">上面一节分析介绍了数据的垂直切分，这一节再分析一下数据的水平切分。数据的垂直切分基本上可以简单的理解为按照表按照模块来切分数据，而水平切分就不再是按照表或者是功能模块来切分了。一般来说，简单的水平切分主要是将某个访问极其平凡的表再按照某个字段的某种规则来分散到多个表之中，每个表中包含一部分数据。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">简单来说，我们可以将数据的水平切分理解为是按照数据行的切分，就是将表中的某些行切分到一个数据库，而另外的某些行又切分到其他的数据库中。当然，为了能够比较容易的判定各行数据被切分到哪个数据库中了，切分总是都需要按照某种特定的规则来进行的。如根据某个数字类型字段基于特定数目取模，某个时间类型字段的范围，或者是某个字符类型字段的hash值。如果整个系统中大部分核心表都可以通过某个字段来进行关联，那这个字段自然是一个进行水平分区的上上之选了，当然，非常特殊无法使用就只能另选其他了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一般来说，像现在互联网非常火爆的Web2.0类型的网站，基本上大部分数据都能够通过会员用户信息关联上，可能很多核心表都非常适合通过会员ID来进行数据的水平切分。而像论坛社区讨论系统，就更容易切分了，非常容易按照论坛编号来进行数据的水平切分。切分之后基本上不会出现各个库之间的交互。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">如我们的示例系统，所有数据都是和用户关联的，那么我们就可以根据用户来进行水平拆分，将不同用户的数据切分到不同的数据库中。当然，唯一有点区别的是用户模块中的groups表和用户没有直接关系，所以groups不能根据用户来进行水平拆分。对于这种特殊情况下的表，我们完全可以独立出来，单独放在一个独立的数据库中。其实这个做法可以说是利用了前面一节所介绍的&#8220;数据的垂直切分&#8221;方法，我将在下一节中更为详细的介绍这种垂直切分与水平切分同时使用的联合切分方法。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，对于我们的示例数据库来说，大部分的表都可以根据用户ID来进行水平的切分。不同用户相关的数据进行切分之后存放在不同的数据库中。如将所有用户ID通过2取模然后分别存放于两个不同的数据库中。每个和用户ID关联上的表都可以这样切分。这样，基本上每个用户相关的数据，都在同一个数据库中，即使是需要关联，也可以非常简单的关联上。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">我们可以通过下图来更为直观的展示水平切分相关信息：水平切分的优点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194915_274.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 表关联基本能够在数据库端全部完成；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 不会存在某些超大型数据量和高负载的表遇到瓶颈的问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用程序端整体架构改动相对较少；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 事务处理相对简单；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 只要切分规则能够定义好，基本上较难遇到扩展性限制；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">水平切分的缺点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 切分规则相对更为复杂，很难抽象出一个能够满足整个数据库的切分规则；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 后期数据的维护难度有所增加，人为手工定位数据更困难；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用系统各模块耦合度较高，可能会对后面数据的迁移拆分造成一定的困难。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">垂直与水平切分的联合使用</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">上面两节内容中，我们分别，了解了&#8220;垂直&#8221;和&#8220;水平&#8221;这两种切分方式的实现以及切分之后的架构信息，同时也分析了两种架构各自的优缺点。但是在实际的应用场景中，除了那些负载并不是太大，业务逻辑也相对较简单的系统可以通过上面两种切分方法之一来解决扩展性问题之外，恐怕其他大部分业务逻辑稍微复杂一点，系统负载大一些的系统，都无法通过上面任何一种数据的切分方法来实现较好的扩展性，而需要将上述两种切分方法结合使用，不同的场景使用不同的切分方法。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在这一节中，我将结合垂直切分和水平切分各自的优缺点，进一步完善我们的整体架构，让系统的扩展性进一步提高。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一般来说，我们数据库中的所有表很难通过某一个（或少数几个）字段全部关联起来，所以很难简单的仅仅通过数据的水平切分来解决所有问题。而垂直切分也只能解决部分问题，对于那些负载非常高的系统，即使仅仅只是单个表都无法通过单台数据库主机来承担其负载。我们必须结合&#8220;垂直&#8221;和&#8220;水平&#8221;两种切分方式同时使用，充分利用两者的优点，避开其缺点。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">每一个应用系统的负载都是一步一步增长上来的，在开始遇到性能瓶颈的时候，大多数架构师和DBA都会选择先进行数据的垂直拆分，因为这样的成本最先，最符合这个时期所追求的最大投入产出比。然而，随着业务的不断扩张，系统负载的持续增长，在系统稳定一段时期之后，经过了垂直拆分之后的数据库集群可能又再一次不堪重负，遇到了性能瓶颈。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">这时候我们该如何抉择？是再次进一步细分模块呢，还是寻求其他的办法来解决？如果我们再一次像最开始那样继续细分模块，进行数据的垂直切分，那我们可能在不久的将来，又会遇到现在所面对的同样的问题。而且随着模块的不断的细化，应用系统的架构也会越来越复杂，整个系统很可能会出现失控的局面。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">这时候我们就必须要通过数据的水平切分的优势，来解决这里所遇到的问题。而且，我们完全不必要在使用数据水平切分的时候，推倒之前进行数据垂直切分的成果，而是在其基础上利用水平切分的优势来避开垂直切分的弊端，解决系统复杂性不断扩大的问题。而水平拆分的弊端（规则难以统一）也已经被之前的垂直切分解决掉了，让水平拆分可以进行的得心应手。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">对于我们的示例数据库，假设在最开始，我们进行了数据的垂直切分，然而随着业务的不断增长，数据库系统遇到了瓶颈，我们选择重构数据库集群的架构。如何重构？考虑到之前已经做好了数据的垂直切分，而且模块结构清晰明确。而业务增长的势头越来越猛，即使现在进一步再次拆分模块，也坚持不了太久。我们选择了在垂直切分的基础上再进行水平拆分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在经历过垂直拆分后的各个数据库集群中的每一个都只有一个功能模块，而每个功能模块中的所有表基本上都会与某个字段进行关联。如用户模块全部都可以通过用户ID进行切分，群组讨论模块则都通过群组ID来切分，相册模块则根据相册ID来进切分，最后的事件通知信息表考虑到数据的时限性（仅仅只会访问最近某个事件段的信息），则考虑按时间来切分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">下图展示了切分后的整个架构：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194941_67.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">实际上，在很多大型的应用系统中，垂直切分和水平切这两种数据的切分方法基本上都是并存的，而且经常在不断的交替进行，以不断的增加系统的扩展能力。我们在应对不同的应用场景的时候，也需要充分考虑到这两种切分方法各自的局限，以及各自的优势，在不同的时期（负载压力）使用不同的结合方式。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">联合切分的优点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 可以充分利用垂直切分和水平切分各自的优势而避免各自的缺陷；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 让系统扩展性得到最大化提升；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">联合切分的缺点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 数据库系统架构比较复杂，维护难度更大；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用程序架构也相对更复杂；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据切分及整合方案</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过前面的章节，我们已经很清楚了通过数据库的数据切分可以极大的提高系统的扩展性。但是，数据库中的数据在经过垂直和（或）水平切分被存放在不同的数据库主机之后，应用系统面临的最大问题就是如何来让这些数据源得到较好的整合，可能这也是很多读者朋友非常关心的一个问题。这一节我们主要针对的内容就是分析可以使用的各种可以帮助我们实现数据切分以及数据整合的整体解决方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">数据的整合很难依靠数据库本身来达到这个效果，虽然MySQL存在Federated存储引擎，可以解决部分类似的问题，但是在实际应用场景中却很难较好的运用。那我们该如何来整合这些分散在各个MySQL主机上面的数据源呢？</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">总的来说，存在两种解决思路：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 在每个应用程序模块中配置管理自己需要的一个（或者多个）数据源，直接访问各个数据库，在模块内完成数据的整合；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2. 通过中间代理层来统一管理所有的数据源，后端数据库集群对前端应用程序透明；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">可能90%以上的人在面对上面这两种解决思路的时候都会倾向于选择第二种，尤其是系统不断变得庞大复杂的时候。确实，这是一个非常正确的选择，虽然短期内需要付出的成本可能会相对更大一些，但是对整个系统的扩展性来说，是非常有帮助的。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，对于第一种解决思路我这里就不准备过多的分析，下面我重点分析一下在第二种解决思路中的一些解决方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733; 自行开发中间代理层</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在决定选择通过数据库的中间代理层来解决数据源整合的架构方向之后，有不少公司（或者企业）选择了通过自行开发符合自身应用特定场景的代理层应用程序。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过自行开发中间代理层可以最大程度的应对自身应用的特定，最大化的定制很多个性化需求，在面对变化的时候也可以灵活的应对。这应该说是自行开发代理层最大的优势了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然，选择自行开发，享受让个性化定制最大化的乐趣的同时，自然也需要投入更多的成本来进行前期研发以及后期的持续升级改进工作，而且本身的技术门槛可能也比简单的Web应用要更高一些。所以，在决定选择自行开发之前，还是需要进行比较全面的评估为好。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">由于自行开发更多时候考虑的是如何更好的适应自身应用系统，应对自身的业务场景，所以这里也不好分析太多。后面我们主要分析一下当前比较流行的几种数据源整合解决方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733;利用MySQLProxy实现数据切分及整合</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">MySQLProxy是MySQL官方提供的一个数据库代理层产品，和MySQLServer一样，同样是一个基于GPL开源协议的开源产品。可用来监视、分析或者传输他们之间的通讯信息。他的灵活性允许你最大限度的使用它，目前具备的功能主要有连接路由，Query分析，Query过滤和修改，负载均衡，以及基本的HA机制等。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">实际上，MySQLProxy本身并不具有上述所有的这些功能，而是提供了实现上述功能的基础。要实现这些功能，还需要通过我们自行编写LUA脚本来实现。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">MySQLProxy实际上是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy，然后经由MySQLProxy进行相应的分析，判断出是读操作还是写操作，分发至对应的MySQLServer上。对于多节点Slave集群，也可以起做到负载均衡的效果。以下是MySQLProxy的基本架构图：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194958_853.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过上面的架构简图，我们可以很清晰的看出MySQLProxy在实际应用中所处的位置，以及能做的基本事情。关于MySQLProxy更为详细的实施细则在MySQL官方文档中有非常详细的介绍和示例，感兴趣的读者朋友可以直接从MySQL官方网站免费下载或者在线阅读，我这里就不累述浪费纸张了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733;利用Amoeba实现数据切分及整合</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">Amoeba是一个基于Java开发的，专注于解决分布式数据库数据源整合Proxy程序的开源框架，基于GPL3开源协议。目前，Amoeba已经具有Query路由，Query过滤，读写分离，负载均衡以及HA机制等相关内容。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">Amoeba 主要解决的以下几个问题：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 数据切分后复杂数据源整合；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2. 提供数据切分规则并降低数据切分规则给数据库带来的影响；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">3. 降低数据库与客户端的连接数；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">4. 读写分离路由；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">我们可以看出，Amoeba所做的事情，正好就是我们通过数据切分来提升数据库的扩展性所需要的。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">Amoeba并不是一个代理层的Proxy程序，而是一个开发数据库代理层Proxy程序的开发框架，目前基于Amoeba所开发的Proxy程序有AmoebaForMySQL和AmoebaForAladin两个。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">AmoebaForMySQL主要是专门针对MySQL数据库的解决方案，前端应用程序请求的协议以及后端连接的数据源数据库都必须是MySQL。对于客户端的任何应用程序来说，AmoebaForMySQL和一个MySQL数据库没有什么区别，任何使用MySQL协议的客户端请求，都可以被AmoebaForMySQL解析并进行相应的处理。下如可以告诉我们AmoebaForMySQL的架构信息（出自Amoeba开发者博客）：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228195022_18.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">AmoebaForAladin则是一个适用更为广泛，功能更为强大的Proxy程序。他可以同时连接不同数据库的数据源为前端应用程序提供服务，但是仅仅接受符合MySQL协议的客户端应用程序请求。也就是说，只要前端应用程序通过MySQL协议连接上来之后，AmoebaForAladin会自动分析Query语句，根据Query语句中所请求的数据来自动识别出该所Query的数据源是在什么类型数据库的哪一个物理主机上面。下图展示了AmoebaForAladin的架构细节（出自Amoeba开发者博客）：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228195037_993.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">咋一看，两者好像完全一样嘛。细看之后，才会发现两者主要的区别仅在于通过MySQLProtocalAdapter处理之后，根据分析结果判断出数据源数据库，然后选择特定的JDBC驱动和相应协议连接后端数据库。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">其实通过上面两个架构图大家可能也已经发现了Amoeba的特点了，他仅仅只是一个开发框架，我们除了选择他已经提供的ForMySQL和ForAladin这两款产品之外，还可以基于自身的需求进行相应的二次开发，得到更适应我们自己应用特点的Proxy程序。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当对于使用MySQL数据库来说，不论是AmoebaForMySQL还是AmoebaForAladin都可以很好的使用。当然，考虑到任何一个系统越是复杂，其性能肯定就会有一定的损失，维护成本自然也会相对更高一些。所以，对于仅仅需要使用MySQL数据库的时候，我还是建议使用AmoebaForMySQL。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">AmoebaForMySQL的使用非常简单，所有的配置文件都是标准的XML文件，总共有四个配置文件。分别为：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;amoeba.xml：主配置文件，配置所有数据源以及Amoeba自身的参数设置；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;rule.xml：配置所有Query路由规则的信息；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;functionMap.xml：配置用于解析Query中的函数所对应的Java实现类；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; rullFunctionMap.xml：配置路由规则中需要使用到的特定函数的实现类；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">如果您的规则不是太复杂，基本上仅需要使用到上面四个配置文件中的前面两个就可完成所有工作。Proxy程序常用的功能如读写分离，负载均衡等配置都在amoeba.xml中进行。此外，Amoeba已经支持了实现数据的垂直切分和水平切分的自动路由，路由规则可以在rule.xml进行设置。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">目前Amoeba少有欠缺的主要就是其在线管理功能以及对事务的支持了，曾经在与相关开发者的沟通过程中提出过相关的建议，希望能够提供一个可以进行在线维护管理的命令行管理工具，方便在线维护使用，得到的反馈是管理专门的管理模块已经纳入开发日程了。另外在事务支持方面暂时还是Amoeba无法做到的，即使客户端应用在提交给Amoeba的请求是包含事务信息的，Amoeba也会忽略事务相关信息。当然，在经过不断完善之后，我相信事务支持肯定是Amoeba重点考虑增加的feature。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">关于Amoeba更为详细的使用方法读者朋友可以通过Amoeba开发者博客（http://amoeba.sf.net）上面提供的使用手册获取，这里就不再细述了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733;利用HiveDB实现数据切分及整合</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">和前面的MySQLProxy以及Amoeba一样，HiveDB同样是一个基于Java针对MySQL数据库的提供数据切分及整合的开源框架，只是目前的HiveDB仅仅支持数据的水平切分。主要解决大数据量下数据库的扩展性及数据的高性能访问问题，同时支持数据的冗余及基本的HA机制。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">HiveDB的实现机制与MySQLProxy和Amoeba有一定的差异，他并不是借助MySQL的Replication功能来实现数据的冗余，而是自行实现了数据冗余机制，而其底层主要是基于HibernateShards来实现的数据切分工作。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在HiveDB中，通过用户自定义的各种Partitionkeys（其实就是制定数据切分规则），将数据分散到多个MySQLServer中。在访问的时候，在运行Query请求的时候，会自动分析过滤条件，并行从多个MySQLServer中读取数据，并合并结果集返回给客户端应用程序。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">单纯从功能方面来讲，HiveDB可能并不如MySQLProxy和Amoeba那样强大，但是其数据切分的思路与前面二者并无本质差异。此外，HiveDB并不仅仅只是一个开源爱好者所共享的内容，而是存在商业公司支持的开源项目。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">下面是HiveDB官方网站上面一章图片，描述了HiveDB如何来组织数据的基本信息，虽然不能详细的表现出太多架构方面的信息，但是也基本可以展示出其在数据切分方面独特的一面了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228195051_109.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 19.5px;">&#9733; mycat 数据整合：具体http://www.songwie.com/articlelist/11</span></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733; 其他实现数据切分及整合的解决方案</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">除了上面介绍的几个数据切分及整合的整体解决方案之外，还存在很多其他同样提供了数据切分与整合的解决方案。如基于MySQLProxy的基础上做了进一步扩展的HSCALE，通过Rails构建的SpockProxy，以及基于Pathon的Pyshards等等。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">不管大家选择使用哪一种解决方案，总体设计思路基本上都不应该会有任何变化，那就是通过数据的垂直和水平切分，增强数据库的整体服务能力，让应用系统的整体扩展能力尽可能的提升，扩展方式尽可能的便捷。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">只要我们通过中间层Proxy应用程序较好的解决了数据切分和数据源整合问题，那么数据库的线性扩展能力将很容易做到像我们的应用程序一样方便，只需要通过添加廉价的PCServer服务器，即可线性增加数据库集群的整体服务能力，让数据库不再轻易成为应用系统的性能瓶颈。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><br /></p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据切分与整合可能存在的问题</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">这里，大家应该对数据切分与整合的实施有了一定的认识了，或许很多读者朋友都已经根据各种解决方案各自特性的优劣基本选定了适合于自己应用场景的方案，后面的工作主要就是实施准备了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在实施数据切分方案之前，有些可能存在的问题我们还是需要做一些分析的。一般来说，我们可能遇到的问题主要会有以下几点：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 引入分布式事务的问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;跨节点Join的问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 跨节点合并排序分页问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 引入分布式事务的问题</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一旦数据进行切分被分别存放在多个MySQLServer中之后，不管我们的切分规则设计的多么的完美（实际上并不存在完美的切分规则），都可能造成之前的某些事务所涉及到的数据已经不在同一个MySQLServer中了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在这样的场景下，如果我们的应用程序仍然按照老的解决方案，那么势必需要引入分布式事务来解决。而在MySQL各个版本中，只有从MySQL5.0开始以后的各个版本才开始对分布式事务提供支持，而且目前仅有Innodb提供分布式事务支持。不仅如此，即使我们刚好使用了支持分布式事务的MySQL版本，同时也是使用的Innodb存储引擎，分布式事务本身对于系统资源的消耗就是很大的，性能本身也并不是太高。而且引入分布式事务本身在异常处理方面就会带来较多比较难控制的因素。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">怎么办？其实我们可以可以通过一个变通的方法来解决这种问题，首先需要考虑的一件事情就是：是否数据库是唯一一个能够解决事务的地方呢？其实并不是这样的，我们完全可以结合数据库以及应用程序两者来共同解决。各个数据库解决自己身上的事务，然后通过应用程序来控制多个数据库上面的事务。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">也就是说，只要我们愿意，完全可以将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务，并通过应用程序来总控各个小事务。当然，这样作的要求就是我们的俄应用程序必须要有足够的健壮性，当然也会给应用程序带来一些技术难度。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2.跨节点Join的问题</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">上面介绍了可能引入分布式事务的问题，现在我们再看看需要跨节点Join的问题。数据切分之后，可能会造成有些老的Join语句无法继续使用，因为Join使用的数据源可能被切分到多个MySQLServer中了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">怎么办？这个问题从MySQL数据库角度来看，如果非得在数据库端来直接解决的话，恐怕只能通过MySQL一种特殊的存储引擎Federated来解决了。Federated存储引擎是MySQL解决类似于Oracle的DBLink之类问题的解决方案。和OracleDBLink的主要区别在于Federated会保存一份远端表结构的定义信息在本地。咋一看，Federated确实是解决跨节点Join非常好的解决方案。但是我们还应该清楚一点，那就似乎如果远端的表结构发生了变更，本地的表定义信息是不会跟着发生相应变化的。如果在更新远端表结构的时候并没有更新本地的Federated表定义信息，就很可能造成Query运行出错，无法得到正确的结果。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">对待这类问题，我还是推荐通过应用程序来进行处理，先在驱动表所在的MySQLServer中取出相应的驱动结果集，然后根据驱动结果集再到被驱动表所在的MySQLServer中取出相应的数据。可能很多读者朋友会认为这样做对性能会产生一定的影响，是的，确实是会对性能有一定的负面影响，但是除了此法，基本上没有太多其他更好的解决办法了。而且，由于数据库通过较好的扩展之后，每台MySQLServer的负载就可以得到较好的控制，单纯针对单条Query来说，其响应时间可能比不切分之前要提高一些，所以性能方面所带来的负面影响也并不是太大。更何况，类似于这种需要跨节点Join的需求也并不是太多，相对于总体性能而言，可能也只是很小一部分而已。所以为了整体性能的考虑，偶尔牺牲那么一点点，其实是值得的，毕竟系统优化本身就是存在很多取舍和平衡的过程。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">3. 跨节点合并排序分页问题</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一旦进行了数据的水平切分之后，可能就并不仅仅只有跨节点Join无法正常运行，有些排序分页的Query语句的数据源可能也会被切分到多个节点，这样造成的直接后果就是这些排序分页Query无法继续正常运行。其实这和跨节点Join是一个道理，数据源存在于多个节点上，要通过一个Query来解决，就和跨节点Join是一样的操作。同样Federated也可以部分解决，当然存在的风险也一样。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">还是同样的问题，怎么办？我同样仍然继续建议通过应用程序来解决。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">如何解决？解决的思路大体上和跨节点Join的解决类似，但是有一点和跨节点Join不太一样，Join很多时候都有一个驱动与被驱动的关系，所以Join本身涉及到的多个表之间的数据读取一般都会存在一个顺序关系。但是排序分页就不太一样了，排序分页的数据源基本上可以说是一个表（或者一个结果集），本身并不存在一个顺序关系，所以在从多个数据源取数据的过程是完全可以并行的。这样，排序分页数据的取数效率我们可以做的比跨库Join更高，所以带来的性能损失相对的要更小，在有些情况下可能比在原来未进行数据切分的数据库中效率更高了。当然，不论是跨节点Join还是跨节点排序分页，都会使我们的应用服务器消耗更多的资源，尤其是内存资源，因为我们在读取访问以及合并结果集的这个过程需要比原来处理更多的数据。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">分析到这里，可能很多读者朋友会发现，上面所有的这些问题，我给出的建议基本上都是通过应用程序来解决。大家可能心里开始犯嘀咕了，是不是因为我是DBA，所以就很多事情都扔给应用架构师和开发人员了？</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">其实完全不是这样，首先应用程序由于其特殊性，可以非常容易做到很好的扩展性，但是数据库就不一样，必须借助很多其他的方式才能做到扩展，而且在这个扩展过程中，很难避免带来有些原来在集中式数据库中可以解决但被切分开成一个数据库集群之后就成为一个难题的情况。要想让系统整体得到最大限度的扩展，我们只能让应用程序做更多的事情，来解决数据库集群无法较好解决的问题。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">小结</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过数据切分技术将一个大的MySQLServer切分成多个小的MySQLServer，既解决了写入性能瓶颈问题，同时也再一次提升了整个数据库集群的扩展性。不论是通过垂直切分，还是水平切分，都能够让系统遇到瓶颈的可能性更小。尤其是当我们使用垂直和水平相结合的切分方法之后，理论上将不会再遇到扩展瓶颈了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 16px; vertical-align: baseline; line-height: 1.6;"></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 16px; vertical-align: baseline; line-height: 1.6;"></p></div><footer style="margin: 1.714285714rem 0px 12px; padding: 0px; border: 0px; font-size: 0.928571429rem; vertical-align: baseline; color: #757575; clear: both; line-height: 1.846153846; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; background-color: #ffffff;">发布在[ 技术 ]&nbsp;<a href="http://songwie.com/articlelist/21#" title="" rel="bookmark" style="margin: 0px; padding: 0px; border-width: 0px 0px 1px; border-bottom-style: dotted; border-bottom-color: #cccccc; font-size: 13px; vertical-align: baseline; outline: none; color: #757575; text-decoration: none;"><time datetime="2014/12/06 21:07:33" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2015-01-05 17:49:30.0</time></a>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline;">by&nbsp;<span vcard"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><a fn=""  n"="" href="http://www.songwie.com/blog/author/1" title="" rel="author" style="margin: 0px; padding: 0px; border-width: 0px 0px 1px; border-bottom-style: dotted; border-bottom-color: #cccccc; vertical-align: baseline; outline: none; color: #757575; text-decoration: none;">从零开始</a></span></span></footer><img src ="http://www.blogjava.net/xiaomage234/aggbug/423493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-03-16 18:27 <a href="http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hydra - 京东开源的基于Dubbo的调用分布跟踪系统</title><link>http://www.blogjava.net/xiaomage234/archive/2015/03/09/423321.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 09 Mar 2015 08:06:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/03/09/423321.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/423321.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/03/09/423321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/423321.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/423321.html</trackback:ping><description><![CDATA[<div id="content" mod-cs-content="" text-content=""  clearfix"="" style="zoom: 1; width: 760px; overflow: visible; line-height: 1.5; margin: 7px 0px 10px; padding: 20px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff;"><p style="margin: 0px; padding: 0px;">from:&nbsp;<span style="line-height: 1.5;">http://wapapp.baidu.com/tianhuimin/item/6e144c362eced2ff96f88d42</span></p><p style="margin: 0px; padding: 0px;">1&nbsp;概述1.1&nbsp;研发背景</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">支撑互联网应用的各种服务通常都是用复杂大规模分布式集群来实现的。而这些互联网应用又构建在不同的软件模块集上，这些软件模块，有可能是由不同的团队开&nbsp;发、可能使用不同的编程语言来实现、有可能布在了几千台服务器，横跨多个不同的数据中心。因此，就需要一些可以帮助理解系统行为、用于分析性能问题的工&nbsp;具。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">hydra分布式跟踪系统就为了解决以上这些问题而设计的。</p>1.2&nbsp;理论依据<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">Google的论文《Dapper,&nbsp;a&nbsp;Large-Scale&nbsp;Distributed&nbsp;Systems&nbsp;Tracing&nbsp;Infrastructure》是我们设计开发的指导思想(原文和译文地址&nbsp;https://github.com/bigbully/Dapper-translation)。Google针对自己的分布式跟踪系统Dapper&nbsp;在生产环境下运行两年多时间积累的经验，在论文中重点提到了分布式跟踪系统对业务系统的零侵入这个先天优势，并总结了大量的应用场景，还提及它的不足之&nbsp;处。我们通过对这篇论文的深入研究，并参考了Twitter同样依据这篇论文的scala实现Zipkin，结合我们自身的现有架构，我们认为分布式跟踪&nbsp;系统在我们内部是非常适合的，而且也是急需的。</p>1.3&nbsp;功能概述<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">hydra目前的功能并不复杂，他可以接入一些基础组件，然后实现在基础组件上收集在组建上产生的行为的时间消耗，并且提供跟踪查询页面，对跟踪到的数据进行查询和展示。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">我们会在之后的功能介绍中对hydra现有功能进行说明。</p>2&nbsp;领域模型<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">分布式跟踪的领域模型其实已经很成熟，早在1997年IBM就把ARM2.0(Application&nbsp;Response&nbsp;Measurement)作为一个公开的标准提供给了Open&nbsp;Group，无奈当时SOA的架构还未成熟，对业务的跟踪还需要直接嵌入到业务代码中，致使跟踪系统无法顺利推广。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">如今互联网领域大多数后台服务都已经完成了SOA化，所以对业务的跟踪可以直接简化为对服务调用框架的跟踪，所以越来越多的跟踪系统也涌现出来。&nbsp;在hydra系统中，我们使用的领域模型参考了Google的Dapper和Twitter的Zipkin(http://twitter.github.io/zipkin/)。</p>2.1&nbsp;hydra中的跟踪数据模型<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">参考Dapper和Zipkin的设计，hydra也提炼出了自己的领域模型，如图所示:</p><img width="640" height="398" src="http://g.hiphotos.baidu.com/album/pic/item/314e251f95cad1c88959439b7e3e6709c83d51af.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Trace:一次服务调用追踪链路。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Span:追踪服务调基本结构，多span形成树形结构组合成一次Trace追踪记录。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Annotation:在span中的标注点，记录整个span时间段内发生的事件。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">BinaryAnnotation:属于Annotation一种类型和普通Annotation区别，这键值对形式标注在span中发生的事件，和一些其他相关的信息。</p></li></ul><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">Annotation在整个跟踪数据模型中最灵活的，灵活运用annotation基本能表达你所想到的跟踪场景。在hydra中(参考了zipkin)定义4种不同value的annotation用来表达记录span&nbsp;4个最基本的事件。通过这4个annotation能计算出链路中业务消耗和网络消耗时间。</p>2.2&nbsp;dubbo服务调用框架的模型<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">公司内部，尤其是我们部门有很多业务系统使用dubbo作为服务调用框，所以我们的分布式跟踪系统第一个接入组件就是dubbo。&nbsp;另一个原因也是因为我们团队对dubbo有着非常深入的理解，加之dubbo本身的架构本身十分适合扩展，作为服务调用框架而言，跟踪的效果会非常明显，&nbsp;比如Twitter的Zipkin也是植入到内部的Finagle服务调用框架上来进行跟踪的。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">由于现阶段hydra主要接入了dubbo服务调用框架,所以在这必须了解dubbo的几个模型，如下图所示:</p><img width="640" height="348" src="http://b.hiphotos.baidu.com/album/pic/item/b21bb051f8198618b79550384bed2e738ad4e6b8.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Application:一类业务类型的服务，下面可能包含多个接口服务，可能出现多种类型业务跟踪链路。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">InterfaceService:接口服务，一个服务接口提供多种业务处理方法。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Method:接口服务中具体处理业务的方法。</p></li></ul>2.3&nbsp;Hydra中跟踪模型和dubbo模型之间关系<img width="800" height="518" src="http://c.hiphotos.baidu.com/album/pic/item/38dbb6fd5266d0165be12194962bd40734fa3595.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">如图所示的应用场景对A服务的调用。A服务在被调用的过程中会继续调用服务B和服务C,而服务C被调用之后又会继续调用服务D和服&nbsp;务E。在我们的领域模型中，服务A被调用到调用完成的过程，就是一次trace。而每一个服务被调用并返回的过程（一去一回的箭头）为一个span。可以&nbsp;看到这个示例中包含5个span，client-A，A-B，A-C，C-D，C-E。span本身以树形结构展开，A-C是C-D和C-E的父&nbsp;span，而client-A是整个树形结构的root&nbsp;span。之后要提到的一个概念就是annotation，annotation代表在服务调用过程中发生的一些我们感兴趣的事情，如图所示C-E上标出&nbsp;来的那四个点，就是四个annotation，来记录事件时间戳，分别是C服务的cs（client&nbsp;send），E服务的ss（server&nbsp;receive）,E服务的ss（server&nbsp;send）,&nbsp;C服务的cr（client&nbsp;receive）。如果有一些自定义的annotation我们会把它作为BinaryAnnotation，其实就是一个k-v对，记录任何跟踪系统想&nbsp;记录的信息，比如服务调用中的异常信息，重要的业务信息等等。</p>3&nbsp;功能介绍<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">当前hydra1.0版的功能主要分为两个部分，跟踪查询和跟踪展示。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">如图所示为查询页面：</p><img width="640" height="311" src="http://h.hiphotos.baidu.com/album/pic/item/d53f8794a4c27d1e95c484781ad5ad6edcc438af.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">在hydra针对业务提出两个相关的概念：应用和服务。不同的业务的所属不同的应用(相当于dubbo中的Application)，服务（相当于dubbo中的interface）挂在应用之下。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">在hydra的查询界面中首先要选择想要关注的应用名，然后通过自动完成的方式输入应用下的服务。选择服务的开始时间和需要查看的跟踪次数。另外hydra需要确定返回数据的总量，防止查询出大数据量导致页面失去响应。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">另外我们提供对额外的筛选条件：调用响应时间、是否发生异常。调用响应时间指的是这一次服务调用从调用开始到调用结束的时间，是否发生异常则包括一次服务调用中所有历经的服务抛出的异常都会捕获到。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">对于查询之后的数据，hydra提供在前台进行排序的功能。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">对于每一次跟踪，我们可以进一步展示他的服务调用层级与响应时间的时序图。如下图所示：</p><img width="800" height="347" src="http://g.hiphotos.baidu.com/album/pic/item/738b4710b912c8fcfd114971fd039245d78821af.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">我们参考Dapper中论述的场景，在时序图中用绿色代表服务调用时间，浅蓝色代表网络耗时，另外如果服务调用抛出异常被&nbsp;hydra捕捉到的话，会用红色表示。鼠标移动到时序图中的每一个对象上，会Tip展现详细信息，包括服务名、方法名、调用时长、Endpoint、异常&nbsp;信息等。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">左侧的树形结构图可以收起和展开，同时右侧的时序图产生联动，利于调整关注点在不同的服务上。</p>4&nbsp;整体架构4.1&nbsp;完整版<img width="640" height="445" src="http://g.hiphotos.baidu.com/album/pic/item/ac6eddc451da81cb77043c715366d016082431af.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">对于分布式跟踪系统而言，必须对接入的基础组件进行改造，我们对dubbo的改造很简单，只是在过滤器链上增加一个过滤器，我们将其封装成一个hydra-dubbo的jar包，由dubbo直接依赖。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">所有跟踪所需的通用性的API我们封装在hydra-client中，遍于接入各种组件。&nbsp;hydra-manager用来完成每个服务的注册、采样率的调成、发送seed生成全局唯一的traceId等通用性的功能。所有hydra-manager数据统一用mysql进行存储。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">我们使用hydra-collector和hydra-collector-service进行跟踪数据的异步存储，中间使用metaQ进行缓冲。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">hydra-manager和hydra-collector使用dobbo提供服务。</p>4.2&nbsp;精简版<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">考虑到数据量不大的情况，以及部署的复杂度。我们提供了两种更简便的架构</p><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">如果考虑到数据量没有那么大，可以不使用hbase，用mysql代替，即精简版1。因为毕竟hadoop集群和hbase集群的部署和维护工作量很大。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">如果并发量也不是很大的话，可以不使用消息中间件，也就是精简版2，如图所示。在hydra-collector端直接进行数据落地，当然仍然是异步的。</p></li></ul><img width="596" height="464" src="http://c.hiphotos.baidu.com/album/pic/item/c2cec3fdfc03924594575eb38694a4c27c1e25af.jpg" alt="Hydra - 京东开源的基于Dubbo的调用分布跟踪系统" style="border: 0px; margin-bottom: 8px; clear: both; max-width: 758px; vertical-align: top;" /><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">在使用mysql进行存储的时候我们并未进行分库分表，因为考虑到存储的是监控数据，时效性较高，而长期的监控数据的保留意义并不大。所以我们在主表上有明确的时间戳字段，使用者可以自行决定何时对保存的历史数据进行迁移。</p>5&nbsp;Quick&nbsp;Start5.1&nbsp;部署简介<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">Hydra分布式跟踪系统可以跟踪环境的数据量大小选择上文所述的三种部署方式</p><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">高并发，大数据量：hydra-client&nbsp;|&nbsp;Queue&nbsp;|&nbsp;hbase</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">高并发，小数据量：hydra-client&nbsp;|&nbsp;Queue&nbsp;|&nbsp;mysql</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">低并发，小数据量：hydra-client&nbsp;|&nbsp;mysql</p></li></ul><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">因为是quick&nbsp;start，这里只介绍低并发和小数据量的情况。不过这里会详细介绍如何通过配置文件的修改来切换这三种部署方式。</p>5.2&nbsp;硬件要求<ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">1或多台业务系统集群机</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">1套zookeeper单点或集群机</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">1台机器部署Hydra-manager</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">1或多台机器部署Hydra-Collector</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">1台机器部署Hydra-web</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">1台数据库服务器</p></li></ul>5.3&nbsp;软件要求<ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Dubbo:Hydra是基于alibaba的dubbo框架基准上做的服务跟踪系统，理论上原有的Dubbo框架服务群中所有应用不需要额外的配置，皆可以平滑的接入Hydra系统。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Zookeeper:各个服务点依赖于zookeeper来读取Hydra-manager和Hydra-collector获取数据交互路由点，来完成跟踪数据的推送和跟踪的控制。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Mysql:跟踪数据的持久化存储。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">Tomcat:前端web应用容器</p></li></ul>5.4&nbsp;源码获取<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">可以暂时使用master，后续版本会归并到dubbo管理端</p>5.5&nbsp;项目构建打包<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">maven项目不用多说。mvn&nbsp;clean&nbsp;install。不过不得不说的是，hydra项目中包含一些涉及数据库读写的单元测试(mysql，hbase），配置文件分别在:</p><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">modules/hydra-manager-db/src/test/resources/mysql.properties</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">modules/hydra-store/hydra-mysql/src/test/resources/mysql.properties</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">modules/hydra-store/hydra-hbase/src/test/resources/hbase-site.xml</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">modules/hydra-store/hydra-hbase/src/test/resources/hydra-hbase-test.xml</p></li></ul><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">mysql需要创建测试用数据库和测试用表，hbase需要创建测试用表</p><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">docs/table-hbase/initTable<br />(hbase建表时可以根据hbase集群的具体情况调整域分区，涉及到table-mysql中对TB_PARA_SERVICE_ID_GEN初始化数据的设计)</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">docs/table-mysql</p></li></ul><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">当然对于不需要使用hbase的同学也可以自行移除modules/hydar-store/hydra-hbase。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">当然用maven构建跳过测试也是可以的。使用mvn&nbsp;clean&nbsp;install&nbsp;-Dmaven.test.skip=true</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">需要打包的子项目会通过maven:assemblly插件打成tar.gz包在各自的target目录下。</p>5.6&nbsp;安装部署5.6.1&nbsp;Hydra-client<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">hydra-client中包含hydra与dubbo的集成，以及hydra跟踪收集的相关功能。如果需要进行dubbo服务的跟踪，只需要把这个jar包放在dubbo服务的classpath下，就会<span style="color: aqua;">自动开启跟踪功能！</span></p>5.6.2&nbsp;Hydra-manager<ol style="margin: 5px 2px 5px 50px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署：scp&nbsp;-r&nbsp;target/*.tar.gz&nbsp;username@ip:dirname</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">配置：cd&nbsp;basedir/conf&nbsp;（需要修改配置）</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">启动：cd&nbsp;basedir/bin<br />sh&nbsp;manager.sh&nbsp;start</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">停止：cd&nbsp;basedir/bin<br />sh&nbsp;manager.sh&nbsp;stop</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">输入：cd&nbsp;basedir/log<br />tail&nbsp;-f&nbsp;manager.log</p></li></ol>5.6.3&nbsp;Hydra-collector<ol style="margin: 5px 2px 5px 50px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署：scp&nbsp;-r&nbsp;target/*.tar.gz&nbsp;username@ip:dirname</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">配置：cd&nbsp;basedir/conf&nbsp;（需要修改配置）</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">启动：cd&nbsp;basedir/bin<br />sh&nbsp;collector-mysql.sh&nbsp;start&nbsp;<br />(这里注意一下，如果在hydra-collector中需要发送到Queue中，则需要启动collector.sh,jar包会加载不同的配置文件。)</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">停止：cd&nbsp;basedir/bin<br />sh&nbsp;collector-mysql.sh&nbsp;stop</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">输入：cd&nbsp;basedir/log<br />tail&nbsp;-f&nbsp;*.log</p></li></ol>5.6.4&nbsp;Hydra-web<ol style="margin: 5px 2px 5px 50px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">需要在web.xml中修改引入的配置文件为hydra-mysql.xml，注掉hydra-hbase.xml</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署：scp&nbsp;-r&nbsp;target/*.war&nbsp;username@ip:$TOMCAT_WEBAPPS</p></li></ol>6&nbsp;模拟场景6.1&nbsp;场景描述<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">我们模拟了两个测试场景，均是基于dubbo服务调用</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">场景exp1:</p><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; font-size: 12px; font-family: tahoma, helvetica, arial;">A&nbsp;--&gt;&nbsp;B&nbsp;--&gt;&nbsp;C &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</pre><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">即服务A调用服务B,服务B调用服务C。测试用例在modules/hydra-example/hydra-exmple-exp1/。熟悉dubbo的同学一定不会陌生。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">场景exp2:</p><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; font-size: 12px; font-family: tahoma, helvetica, arial;">A&nbsp;--&gt;&nbsp;B&nbsp;--&gt;&nbsp;C1&nbsp;--&gt;&nbsp;E &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt;&nbsp;C2&nbsp;--&gt;&nbsp;D1&nbsp;--&gt;&nbsp;C1&nbsp;--&gt;&nbsp;E &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt;&nbsp;D2 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</pre><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">场景2很复杂，基本涵盖了对同步调用跟踪的大多数可能遇到的场景。测试用例在modules/hydra-example/hydra-exmple-exp2/。</p>6.2&nbsp;模拟场景dubbo服务的部署<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">Hydra默认使用了hydra-exmple中的两个应用场景来做，你可以在hydra-test/hydra-test-integration打包中获得应用场景。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">获得tar.gz包或者zip包后，将服务分布式部署到不同的机器上，以模拟应用场景,一下介绍场景一的部署方法，场景二的部署方法类似。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">hydra-test-intergration&nbsp;分为windows版和linux版(默认)，见如下打包方法。</p><ul style="margin: 0px 2px 0px 45px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">打包：linux:&nbsp;mvn&nbsp;package&nbsp;-Pruntime-env-linux<br />window:&nbsp;mvn&nbsp;package&nbsp;-Pruntime-env-windows</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署:&nbsp;scp&nbsp;-r&nbsp;target/*.tar.gz&nbsp;username@ip:dirname</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">配置:&nbsp;cd&nbsp;basedir/conf<br />修改&nbsp;*exp1.properties</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">启动：&nbsp;cd&nbsp;basedir/bin<br />cd&nbsp;exp1<br />sh&nbsp;startA.sh<br />cd&nbsp;..<br />sh&nbsp;startTrigger-exp1.sh&nbsp;start</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">停止:&nbsp;cd&nbsp;basedir/bin<br />sh&nbsp;startTrigger-exp1.sh&nbsp;stop<br />All.sh&nbsp;stop</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">输出:&nbsp;cd&nbsp;basedir/log<br />tail&nbsp;-f&nbsp;*.log</p></li></ul>6.3&nbsp;部署举例<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">以下演示安装样例：</p><ol style="margin: 5px 2px 5px 50px; padding: 0px; list-style: none; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署zookeeper单点或集群环境，以保证获得最佳SOA，zookeeper的部署请参照官方文档。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署实验场景exp1，只需要部署hydra-test-integration模块打包的tar.gz包，拷贝三份分布式部署。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署一个触发器Trigger，以激活服务的调用。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署一个Manager，以管理各个跟踪点的跟踪上下文。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署一个或者多个Collector消费机集群，以搜集来自Hydra-client推送过来的跟踪数据。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px;">部署一个web应用，已提供给前端展现应用系统服务上下文。</p></li></ol><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">exp1场景说明：</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">有三个服务应用A、B、C和一个触发RPC调用的应用Trigger，服务调用关系为A-B-C，&nbsp;每隔500s触发一个调用，持续时间为1天。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">部署地址举例：</p>角色ipportZK192.168.200.110-1122181~A192.168.200.11020990B192.168.200.11120991C192.168.200.11220992Trigger192.168.200.113-Manager192.168.228.8120890Collector192.168.228.81-8220889Web192.168.228.818080MySql-DB192.168.228.8133067&nbsp;测试相关7.1&nbsp;测试说明<p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">本测试针对Hydra-Client模块进行功能测试和压力测试，以便在Hydra开发的过程中及时发现重要bug和帮助优化Hydra系统性能。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">本测试目前只针对Hydra-client的测试，重点关注业务系统接入Hydra和不接入Hydra前后性能影响，以保证Hydra系统接入端的低侵入性和稳定性。</p><p style="margin: 10px 0px; padding: 0px; font-family: arial, sans-serif, verdana, helvetica; color: #404040; line-height: 25px; background-color: #fafafa;">针对Hydra-Client的测试，在部署上，只用部署应用场景（带Hydra_client）和Benchmark触发点，然后在应用Benchmark和应用场景上埋点分析Hydra性能。<br /></p><p style="margin: 0px; padding: 0px;"><br /></p><p style="margin: 0px; padding: 0px;">资料来源：<a href="http://www.open-open.com/lib/view/open1370253915148.html" target="_blank" style="color: #4bc1c1;">http://www.open-open.com/lib/view/open1370253915148.html</a></p><div></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/423321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-03-09 16:06 <a href="http://www.blogjava.net/xiaomage234/archive/2015/03/09/423321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微观SOA：服务设计原则及其实践方式（下篇）</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418779.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 16 Oct 2014 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418779.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418779.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418779.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418779.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418779.html</trackback:ping><description><![CDATA[from:http://www.infoq.com/cn/articles/micro-soa-2<br /><br /><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">在<a href="http://www.infoq.com/cn/articles/micro-soa-1" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">上一篇文章</a>中，我说到SOA是一个特别大的话题，不但没有绝对统一的原则，而且很多原则本身的内容也具备相当模糊性和宽泛性。虽然我们可以说SOA &#8776; 模块化开发 + 分布式计算，但由于其原则的模糊性，我们仍然很难说什么应用是绝对符合SOA的，只能识别出哪些是不符合SOA的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">本篇将对8种可操作的服务设计原则进行细化的分析，作为SOA实践的参考。</p><h2>服务设计原则1：优化远程调用</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">这里的远程调用特指RPC（Remote Procedure Call）。当然更面向对象的说法应该是远程方法调用或者远程服务调用等等。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: Arial, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">由于SO接口通常要被远程访问，而网络传输，对象序列化/反序列化等开销都远远超过本地Object访问几个数量级，所以要加快系统的响应速度、减少带宽占用和提高吞吐量，选择高性能的远程调用方式经常是很重要的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是远程调用方式往往又要受限于具体的业务和部署环境，比如内网、外网、同构平台、异构平台等等。有时还要考虑它对诸如分布式事务，消息级别签名/加密，可靠异步传输等方面的支持程度（这些方面通常被称为SLA：service level agreement），甚至还包括开发者的熟悉和接受程度等等。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">因此，远程调用方式往往需要根据具体情况做出选择和权衡。</p><div id="lowerFullwidthVCR" style="margin: 0px; border: 0px; font-family: Arial, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">以Java远程Service为例分析不同场景下，传输方式的某些可能较好选择：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">内网 + 同框架Java客户端 + 大并发：多路复用的TCP长连接 + kryo （二进制序列化） （kryo也可以用Protostuff，FST等代替）</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">内网 + 不同框架Java客户端：TCP + Kryo</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">内网 + Java客户端 + 2PC分布式事务：RMI/IIOP （TCP + 二进制）</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">内网 + Java客户端 + 可靠异步调用：JMS + Kryo （TCP + 二进制）</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">内网 + 不同语言客户端：thrift（TCP + 二进制序列化）</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">外网 + 不同语言客户端 + 企业级特性：HTTP + WSDL + SOAP （文本）</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">外网 + 兼顾浏览器、手机等客户端：HTTP + JSON （文本）</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">外网 + 不同语言客户端 + 高性能：HTTP + ProtocolBuffer （二进制）</li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">简单来说，从性能上讲，tcp协议 + 二进制序列化更适合内网应用。从兼容性、简单性上来说，http协议 + 文本序列化更适合外网应用。当然这并不是绝对的。另外，tcp协议在这里并不是限定远程调用协议一定只能是位于OSI网络模型的第四层的原始tcp，它可以包含tcp之上的任何非http协议。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">所以，回答上面提到的问题，WebServices （经典的WSDL+SOAP+HTTP）虽然是最符合前述SOA设计原则的技术，但并不等同于SOA，我认为它只是满足了SOA的底线，而未必是某个具体场景下的最佳选择。这正如一个十项全能选手在每个单项上是很难和单项冠军去竞争的。更理想的SOA Service最好能在可以支持WebServices的同时，支持多种远程调用方式，适应不同场景，这也是Spring Remoting，SCA，Dubbo，Finagle等分布式服务框架的设计原则。</p><h3>远程调用技术解释：HTTP + JSON适合SOA吗？</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">JSON简单易读，通用性极佳，甚至能很好支持浏览器客户端，同时也常被手机APP使用，大有取代XML之势。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但JSON本身缺乏像XML那样被广泛接受的标准schema，而一般的HTTP + JSON的远程调用方式也缺乏像Thrift，CORBA，WebServices等等那样标准IDL（接口定义语言），导致服务端和客户端之间不能形成强的服务契约，也就不能做比如自动代码生成。所以HTTP + JSON在降低了学习门槛的同时，可能显著的增加复杂应用的开发工作量和出错可能性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">例如，新浪微博提供了基于HTTP + JSON的Open API，但由于业务操作比较复杂，又在JSON上封装实现了各种语言的客户端类库，来减少用户的工作量。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">为了解决这方面的问题，业界有很多不同方案来为HTTP + JSON补充添加IDL，如RSDL、JSON-WSP、WADL、WSDL 2.0等等，但事实上它们的接受度都不太理想。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外值得一提的是，JSON格式和XML一样有冗余，即使做GZIP压缩之类的优化，传输效率通常也不如很多二进制格式，同时压缩、解压还会引入额外的性能开销。</p><h3>远程调用技术解释：Apache Thrift多语言服务框架</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Thrift是最初来自facebook的一套跨语言的service开发框架，支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, JavaScript, Node.js, Smalltalk, Delphi等几乎所有主流编程语言，具有极好的通用性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Thrift被facebook，twitter等巨头以及开源社区都广泛使用，是非常成熟的技术。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Thrift的服务契约通过类似如下形式的IDL定义：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">struct User {     1: i32 id,     2: string name,     3: string password }  service UserService {     void store(1: User user),     UserProfile retrieve(1: i32 id) } </pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">非常类似于C语言，易读易写，比WSDL简单明了得多。比用java之类的编程语言也更方便，有时候可以把所有相关的接口和数据结构定义放到同一个文件，发布出去的时候不用再打一个压缩包之类，甚至可以直接粘贴到文档中</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Thrift还提供工具，可以基于IDL自动生成各种语言对应的服务端和客户端代码：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">[lishen@dangdang thrift]thrift --gen java user.thrift [lishen@dangdang thrift]$ thrift --gen cpp user.thrift [lishen@dangdang thrift]$ thrift --gen php user.thrift [lishen@dangdang thrift]$ thrift --gen csharp user.thrift </pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">我认为thrift是比WebServices更简单高效的技术，是在SOA中对WebServices最具有替代性的技术之一。</p><h3>远程调用技术解释：多路复用的TCP长连接</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">这是一种追求极致高性能高伸缩的方式，这里只做简要介绍。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">比较典型的是twitter的Mux RPC协议以及google的SPDY协议，在其中多个请求同时共用同一个长连接，即一个连接交替传输不同请求的字节块。它既避免了反复建立连接开销，也避免了连接的等待闲置从而减少了系统连接总数，同时还避免了TCP顺序传输中的线头阻塞（head-of-line blocking）问题。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外，国内比较著名的开源dubbo框架的默认RPC协议，以及业界许多小型开源RPC框架也都是类似的思路。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">采用多路复用机制后，一般就要求服务器端和客户端都支持额外的类似于会话层（即OSI网络模型第六层）的语义，导致它们必须要依赖于同一套RPC框架。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">其他很多RPC机制都是使用TCP短连接。即使有些RPC使用了长连接，但一个连接同一时间只能发送一个请求，然后连接就处于闲置状态，来等待接收该请求的响应，待响应完毕，该连接才能被释放或者复用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">HTTP 1.1也支持一种基于pipeline模式的长连接，其中多个HTTP请求也可共用一个连接，但它要求响应（response）也必须按照请求（request）的顺序传输返回，即FIFO先进先出。而在完全多路复用的连接中，哪个的响应先ready就可以先传输哪个，不用排队。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">当然，短连接、长连接和多路复用长连接之间不存在绝对的好坏，需要取决于具体业务和技术场景，在此不详细展开了。</p><h3>远程调用技术解释：Java高效序列化</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">最近几年，各种新的Java高效序列化方式层出不穷，不断刷新序列化性能的上限，例如Kryo，FST等开源框架。它们提供了非常高效的Java对象的序列化和反序列化实现，相比JDK标准的序列化方式（即基于Serializable接口的标准序列化，暂不考虑用诸如Externalizable接口的定制序列化），在典型场景中，其序列化时间开销可能缩短20倍以上，生成二进制字节码的大小可能缩减4倍以上。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外，这些高效Java序列化方式的开销也显著少于跨语言的序列化方式如thrift的二进制序列化，或者JSON等等</p><h3>远程调用技术解释：RMI/IIOP和分布式事务</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">RMI/IIOP是Java EE中标准的远程调用方式，IIOP是CORBA的协议，只有IIOP上的RMI才支持两阶段提交的分布式事务，同时提供和CORBA的互操作。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">当然，严格的两阶段提交事务并不高效，还可能严重影响系统伸缩性甚至可用性等等，一般只应用在非常关键的业务中。</p><h3>远程调用技术解释：Google ProtocolBuffer跨语言序列化</h3><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">ProtocolBuffer是google开发的跨语言的高效二进制序列化方式，其序列化性能和thrift比较类似。事实上thrift最初就是ProtocolBuffer的仿制品。但它和thrift最大的不同是他没有自带的RPC实现（因为google没有将RPC部分开源，但有大量第三方实现）。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">由于不和RPC方式耦合，反而使得ProtocolBuffer能被方便的集成进大量已有的系统和框架中。在国内它也被百度、淘宝等广泛的应用在Open API中，和HTTP搭配作为一种高效的跨平台跨组织的集成方式。</p><h2>服务设计原则2：消除冗余数据</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">同样由于service的远程调用开销很高，所以在它的输入参数和返回结果中，还要尽量避免携带当前业务用例不需要的冗余的字段，来减少序列化和传输的开销。同时，去掉冗余字段也可以简化接口，避免给外部用户带来不必要的业务困惑。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">比如article service中有个返回article list的方法</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">List&lt;Article&gt; getArticles(...)</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">如果业务需求仅仅是要列出文章的标题，那么在返回的article中就要避免携带它的contents等等字段。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">这里经典解决方案就是引入OO中常用的Data Transfer Object (DTO)模式，专门针对特定service的用例来定制要传输的数据字段。这里就是添加一个AriticleSummary的额外数据传输对象：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">List&lt;ArticleSummary&gt; getArticleSummaries(...)</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">额外的DTO确实是个麻烦，而一般OO程序通常则可直接返回自己的包含冗余的业务模型。</p><h2>服务设计原则3：粗粒度契约</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">同样由于远程调用开销高，同时service的外部使用者对特定业务流程的了解也比不上组织内部的人，所以service的契约（接口）通常需要是粗粒度的，其中的一个操作就可能对应到一个完整的业务用例或者业务流程，这样既能减少远程调用次数，同时又降低学习成本和耦合度。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">而OO接口通常可以是非常细粒度的，提供最好的灵活性和重用性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">例如，article service支持批量删除文章，OO接口中可以提供</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">deleteArticle(long id)</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">供用户自己做循环调用（暂不考虑后端SQL之类优化），但SO接口中，则最好提供</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">deleteArticles(Set&lt;Long&gt; ids)</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">供客户端调用，将可能的N次远程调用减少为一次。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">例如，下订单的用例，要有一系列操作</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">addItem -&gt; addTax -&gt; calculateTotalPrice -&gt; placeOrder </pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">OO中我们完全可以让用户自己来灵活选择，分别调用这些细粒度的可复用的方法。但在SO中，我们需要将他们封装到一个粗粒度的方法供用户做一次性远程调用，同时也隐藏了内部业务的很多复杂性。另外，客户端也从依赖4个方法变成了依赖1个方法，从而大大降低了程序耦合度。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">顺便值得一提的是，如果上面订单用例中每个操作本身也是远程的service（通常在内网之中），这种粗粒度封装就变成了经典的service composition（服务组合）甚至service orchestration（服务编排）了。这种情况下粗粒度service同样可能提高了性能，因为对外网客户来说，多次跨网的远程调用变成了一次跨网调用 + 多次内网调用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">对这种粗粒度service封装和组合，经典解决方案就是引入OO中常用的Facade模式，将原来的对象屏蔽到专门的&#8220;外观&#8221;接口之后。同时，这里也很可能要求我们引入新的service参数/返回值的数据结构来组合原来多个操作的对象模型，这就同样用到前述的DTO模式。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">一个简单Facade示例（FooService和BarService是两个假想的本地OO service，fa&#231;ade将它们的结果值组合返回）：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">class FooBarFacadeImpl implements FooBarFacade {     private FooService fooService;     private BarService barService;      public FooBarDto getFooBar() {         FooBarDto fb = new FooBarDto();         fb.setFoo(fooService.getFoo());         fb.setBar(barService.getBar());         return fb;     } }   </pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">当然，有的时候也可以不用facade和DTO，而在是FooService和BarService之外添加另一个本地service和domain model，这要和具体业务场景有关。</p><h2>服务设计原则4：通用契约</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">由于service不假设用户的范围，所以一般要支持不同语言和平台的客户端。但各种语言和平台在功能丰富性上有很大差异，这就决定了服务契约必须取常见语言、平台以及序列化方式的最大公约数，才能保证service广泛兼容性。由此，服务契约中不能有某些语言才具备的高级特性，参数和返回值也必须是被广泛支持的较简单的数据类型（比如不能有对象循环引用）。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">如果原有的OO接口不能满足以上要求，则在此我们同样需要上述的Facade和DTO，将OO接口转换为通用的SO契约。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">例如原有对象模型</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">class Foo {    private Pattern regex; }</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Pattern是Java特有的预编译好的，可序列化的正则表达式（可提高性能），但在没有特定框架支持下，可能不好直接被其他语言识别，所以可添加DTO：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">class FooDto {    private String regex; }</pre><h2>服务设计原则5：隔离变化</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">虽然OO和SO都追求低耦合，但SO由于使用者范围极广，就要求了更高程度的低耦合性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">比如前述的article service，OO中可以直接返回article对象，而这个article对象在OO程序内部可能做为核心的建模的domain model，甚至作为O/R mapping等等。而在SO如果还直接返回这个article，即使没有前面所说的冗余字段，复杂类型等问题，也可能让外部用户与内部系统的核心对象模型，甚至O/R mapping机制，数据表结构等等产生了一定关联度，这样一来，内部的重构经常都会可能影响到外部的用户。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">所以，这里再次对Facade和DTO产生了需求，用它们作为中介者和缓冲带，隔离内外系统，把内部系统变化对外部的冲击减少到最小程度。</p><h2>服务设计原则6：契约先行</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Service是往往涉及不同组织之间的合作，而按照正常逻辑，两个组织之间合作的首要任务，就是先签订明确的契约，详细规定双方合作的内容，合作的形式等等，这样才能对双方形成强有力的约束和保障，同时大家的工作也能够并行不悖，不用相互等待。因此SOA中，最佳的实践方式也是契约先行，即先做契约的设计，可以有商务，管理和技术等不同方面的人员共同参与，并定义出相应的WSDL或者IDL，然后在开发的时候再通过工具自动生成目标语言的对应代码。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">对于WSDL来说，做契约先行的门槛略高，如果没有好的XML工具很难手工编制。但对于Thrift IDL或者ProtocolBuffer等来说，由于它们和普通编程语言类似，所以契约设计相对是比较容易的。另外，对于简单的HTTP + JSON来说（假设不补充使用其他描述语言），由于JSON没有标准的schema，所以是没法设计具有强约束力的契约的，只能用另外的文档做描述或者用JSON做输入输出的举例。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是，契约先行，然后再生成服务提供端的代码，毕竟给service开发工作带来了较大的不便，特别是修改契约的时候导致代码需要重写。因此，这里同样可能需要引入Facade和DTO，即用契约产生的都是Facade和DTO代码，它们负责将请求适配和转发到其他内部程序，而内部程序则可以保持自己的主导性和稳定性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外，契约先行可能会给前面提到的多远程调用支持带来一些麻烦。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">当然契约先行也许并不是能被广泛接受的实践方式，就像敏捷开发中&#8220;测试先行&#8221;（也就是测试驱动开发）通常都是最佳实践，但真正施行的团队却非常之少，这方面还需要不断摸索和总结。但我们至少可以认为Echo中Java2WSDL并不被认为是SOA的最佳实践。</p><h2>服务设计原则7：稳定和兼容的契约</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">由于用户范围的广泛性，所以SO的服务契约和Java标准API类似，在公开发布之后就要保证相当的稳定性，不能随便被重构，即使升级也要考虑尽可能的向下兼容性。同时，如果用契约先行的方式，以后频繁更改契约也导致开发人员要不断重做契约到目标语言映射，非常麻烦。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">这就是说SO对契约的质量要求可能大大高于一般的OO接口，理想的情况下，甚至可能需要专人（包括商务人员）来设计和评估SO契约（不管是否用契约先行的方式），而把内部的程序实现交给不同的人，而两者用Facade和DTO做桥梁。</p><h2>服务设计原则8：契约包装</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">前述原则基本都是针对service提供端来讲的，而对service消费端而言，通过契约生成对应的客户端代码，经常就可以直接使用了。当然，如果契约本身就是Java接口之类（比如在Dubbo，Spring Remoting等框架中），可以略过代码生成的步骤。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是，service的返回值（DTO）和service接口（Facade），可能被消费端的程序到处引用到。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">这样消费端程序就较强的耦合在服务契约上了，如果服务契约不是消费端定义的，消费端就等于把自己程序的部分主导权完全让渡给了别人。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">一旦契约做更改，或者消费端要选择完全不同的service提供方（有不同的契约），甚至改由本地程序自己来实现相关功能，修改工作量就可能非常大了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外，通过契约生成的客户端代码，经常和特定传输方式是相关的（比如webservices stub），这样给切换远程调用方式也会带来障碍。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">因此，就像在通常应用中，我们要包装数据访问逻辑（OO中的DAO或者Repository模式），或者包装基础服务访问逻辑（OO中的Gateway模式）一样，在较理想的SOA设计中，我们也可以考虑包装远程service访问逻辑，由于没有恰当的名称，暂时称之为Delegate Service模式，它由消费端自己主导定义接口和参数类型，并将调用转发给真正的service客户端生成代码，从而对它的使用者完全屏蔽了服务契约，这些使用者甚至不知道这个服务到底是远程提供的的还是本地提供的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">此外，即使我们在消费端是采用某些手工调用机制（如直接构建和解析json等内容，直接收发JMS消息等等），我们同样可以用delegate service来包装相应的逻辑。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">delegate service示例1：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">// ArticlesService是消费端自定义的接口 class ArticleServiceDelegate implements ArticlesService {     // 假设是某种自动生成的service客户端stub类     private ArticleFacadeStub stub;      public void deleteArticles(List&lt;Long&gt; ids) {         stub.deleteArticles(ids);     } }   </pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">delegate service示例2：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn4.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">// ArticlesService是消费端自定义的接口 class ArticleServiceDelegate implements ArticlesService {      public void deleteArticles(List&lt;Long&gt; ids) {         // 用JMS和FastJson手工调用远程service         messageClient.sendMessage(queue, JSON.toJSONString(ids));     } }   </pre><h2>从面向对象到面向服务，再从面向服务到面向对象</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">总结上面的几个原则，虽然只是谈及有限的几个方面，但大致也可看出OO和SO在实际的设计开发中还是有不少显著的不同之处，而且我们没有打算用SO的原则来取代过去的OO设计，而是引入额外的层次、对象和OO设计模式，来补充传统的OO设计。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">其实就是形成了这种调用流程：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">service提供端：OO程序 &lt;- SOA层（Facade和DTO）&lt;- 远程消费端</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">service消费端：OO程序 -&gt; Delegate Service -&gt; SOA层（Facade和DTO 或者 其他动态调用机制）-&gt; 远程提供端</p></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Facade、DTO和Delegate Service负责做OO到SO和SO到OO的中间转换。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">现在，可以回答Echo示例中的问题：通过&#8220;透明的&#8221;配置方式，将OO程序发布为远程Service，虽然可能较好的完成了从本地对象到远程对象的跨越，但通常并不能较好的完成OO到SO的真正跨越。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">同时，透明配置方式也通常无法直接帮助遗留应用（如ERP等）转向SOA。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">当然，在较为简单和使用范围确定很有限应用（比如传统和局部的RPC）中，透明式远程service发布会带来极大的便利。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外，上面对SO的所有讨论都集中在RPC的方式，其实SO中也用message的方式做集成，它也是个大话题，暂时不在此详论了。</p><h2>为什么不能放弃面向对象？</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">SO是有它的特定场景的，比如远程的，范围不定的客户端。所以它的那些设计原则并不能被借用来指导一般性的程序开发，比如很多OO程序和SO原则完全相反，经常都要提供细粒度接口和复杂参数类型以追求使用的使用灵活性和功能的强大性。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">就具体架构而言，我认为SOA层应该是一个很薄的层次（thin layer），将OO应用或者其他遗留性应用加以包装和适配以帮助它们面向服务。其实在通常的web开发中，我们也是用一个薄的展现层（或者叫Web UI层之类）来包装OO应用，以帮助它们面向浏览器用户。因此，Fa&#231;ade、DTO等不会取代OO应用中核心的Domain Model、Service等等 （这里的service是OO中service，未必是SO的）。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">综合起来，形成类似下面的体系结构：</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn3.infoqstatic.com/resource/articles/micro-soa-2/zh/resources/soa-architecture.png" width="600" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><h2>理想和现实</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">需要特别指出的是，上面提到的诸多SO设计原则是在追求一种相对理想化的设计，以达到架构的优雅性，高效性，可重用性，可维护性，可扩展性等等。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">而在现实中任何理论和原则都可能是需要作出适当妥协的，因为现实是千差万别的，其情况远比理论复杂，很难存在放之四海而皆准的真理。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">而且很多方面似乎本来也没有必要追求完美和极致，比如如果有足够能力扩充硬件基础设施，就可以考虑传输一些冗余数据，选择最简单传输方式，并多来几次远程调用等等，以减轻设计开发的工作量。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">那么理想化的原则就没有意义了吗？比如领域驱动设计（Domain-Driven Design）被广泛认为是最理想的OO设计方式，但极少有项目能完全采用它；测试驱动开发也被认为是最佳的敏捷开发方式，但同样极少有团队能彻底采用它。但是，恐怕没有多少人在了解它们之后会否认它们巨大的意义。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">理想化的原则可以更好的帮助人们理解某类问题的本质，并做为好的出发点或者标杆，帮助那些可以灵活运用，恰当取舍的人取得更大的成绩，应付关键的挑战。这正如孔子说的&#8220;取乎其上，得乎其中；取乎其中，得乎其下；取乎其下，则无所得矣&#8221;。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">另外，值得一提的是，SOA从它的理念本身来说，就带有一些的理想主义的倾向，比如向&#8220;全世界&#8221;开放，不限定客户端等等。如果真愿意按SOA的路径走，即使你是个土豪，偷个懒比浪费网络带宽重要，但说不定你的很多用户是土鳖公司，浪费几倍的带宽就大大的影响他们的利润率。</p><h2>延伸讨论：SOA和敏捷软件开发矛盾吗？</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">SOA的服务契约要求相当的稳定性，一旦公开发布（或者双方合同商定）就不应该有经常的变更，它需要对很多方面有极高的预判。而敏捷软件开发则是拥抱变化，持续重构的。软件设计大师Martin Fowler把它们归结为计划式设计和演进式设计的不同。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">计划理论（或者叫建构理论）和演进理论是近代哲学的两股思潮，影响深远，派生出了比如计划经济和市场经济，社会主义和自由主义等等各种理论。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是，计划式设计和演进式设计并不绝对矛盾，就像计划经济和市场经济也不绝对矛盾，非此即彼，这方面需要在实践中不断摸索。前面我们讨论的设计原则和架构体系，就是将SOA层和OO应用相对隔离，分而治之，在SOA层需要更多计划式设计，而OO应用可以相对独立的演进，从而在一定程度缓解SOA和敏捷开发的矛盾。</p><h2>延伸讨论：SOA和REST是一回事吗？</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">从最本质的意义上讲，REST（Representational State Transfer）实际是一种面向资源架构（ROA），和面向服务架构（SOA）是有根本区别的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">例如，REST是基于HTTP协议，对特定资源做增（HTTP POST）、删（HTTP DELETE）、改（HTTP PUT）、查（HTTP GET）等操作，类似于SQL中针对数据表的INSERT、DELETE、UPDATE、SELECT操作，故REST是以资源（资源可以类比为数据）为中心的。而SOA中的service通常不包含这种针对资源（数据）的细粒度操作，而是面向业务用例、业务流程的粗粒度操作，所以SOA是以业务逻辑为中心的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是在实际使用中，随着许多REST基本原则被不断突破，REST的概念被大大的泛化了，它往往成为很多基于HTTP的轻量级远程调用的代名词（例如前面提到过的HTTP + JSON）。比如，即使是著名的Twitter REST API也违反不少原始REST的基本原则。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">在这个泛化的意义上讲，REST也可以说是有助于实现SOA的一种轻量级远程调用方式。</p><h2>SOA架构的进化</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">前面讨论的SOA的所有问题，基本都集中在service本身的设计开发。但SOA要真正发挥最大作用，还需要不断演进成更大的架构（也就是从微观SOA过渡到宏观SOA），在此略作说明：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">第一个层次是service架构</strong>：开发各种独立的service并满足前面的一些设计原则，我们前面基本都集中在讨论这种架构。这些独立的service有点类似于小孩的积木。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">第二个层次是service composition（组合）架构</strong>：独立的service通过不同组合来构成新的业务或者新的service。在理想情况下，可以用一种类似小孩搭积木的方式，充分发挥想象力，将独立的积木（service）灵活的拼装组合成新的形态，还能够自由的替换其中的某个构件。这体现出SOA高度便捷的重用性，大大提高企业的业务敏捷度。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">第三个层次是service inventory（清单）架构</strong>：通过标准化企业服务清单（或者叫注册中心）统一的组织和规划service的复用和组合。当积木越来越多了，如果还满地乱放而没有良好的归类整理，显然就玩不转了。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">第四个层次是service-oriented enterprise架构</strong>&#8230;&#8230;</p></li></ul><h2>总结</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">至此，我们只是简要的探讨了微观层面的SOA，特别是一些基本设计原则及其实践方式，以期能够略微展示SOA在实践中的本质，以有助于SOA更好的落地，进入日常操作层面。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">最后，打个比方：SOA不分贵贱（不分语言、平台、组织），不远万里（通过远程调用）的提供服务（service），这要求的就是一种全心全意为人民服务的精神&#8230;&#8230;</p><h2>作者简介</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">沈理，当当网架构师和技术委员会成员，主要负责当当网的SOA实施（即服务化）以及分布式服务框架的开发。以前也有在BEA、Oracle、Redhat等外企的长期工作经历，从事过多个不同SOA相关框架和容器的开发。他的邮箱：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#104;&#101;&#110;&#108;&#105;&#64;&#100;&#97;&#110;&#103;&#100;&#97;&#110;&#103;&#46;&#99;&#111;&#109;" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">shenli@dangdang.com</a></p><hr style="margin: 0px; border: 0px; padding: 0px; font-family: Arial, sans-serif; background-color: #ffffff;" /><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">感谢<a href="http://www.infoq.com/cn/author/%E9%A9%AC%E5%9B%BD%E8%80%80" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">马国耀</a>对本文的审校。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">给InfoQ中文站投稿或者参与内容翻译工作，请邮件至<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#101;&#100;&#105;&#116;&#111;&#114;&#115;&#64;&#99;&#110;&#46;&#105;&#110;&#102;&#111;&#113;&#46;&#99;&#111;&#109;" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">editors@cn.infoq.com</a>。也欢迎大家通过新浪微博（<a href="http://www.weibo.com/infoqchina" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@InfoQ</a>）或者腾讯微博（<a href="http://t.qq.com/infoqchina" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@InfoQ</a>）关注我们，并与我们的编辑和其他读者朋友交流。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/418779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-16 14:06 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/16/418779.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微观SOA：服务设计原则及其实践方式（上篇）</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418778.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 16 Oct 2014 06:05:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418778.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418778.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418778.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418778.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418778.html</trackback:ping><description><![CDATA[from:http://www.infoq.com/cn/articles/micro-soa-1<br /><br /><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">大量互联网公司都在拥抱SOA和服务化，但业界对SOA的很多讨论都比较偏向高大上。本文试图从稍微不同的角度，以相对接地气的方式来讨论SOA，集中讨论SOA在微观实践层面中的缘起、本质和具体操作方式，另外也用相当篇幅介绍了当今互联网行业中各种流行的远程调用技术等等，比较适合从事实际工作的架构师和程序员来阅读。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">为了方便阅读，本话题将分为两篇展现。本文是上篇，着眼于微观SOA的定义，并简单分析其核心原则。</p><h2>亚马逊CEO杰夫&#8226;贝佐斯：鲜为人知的SOA大师</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">由于SOA有相当的难度和门槛，不妨先从一个小故事说起，从中可以管窥一点SOA的大意和作用。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: Arial, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">按照亚马逊前著名员工Steve Yegge著名的&#8220;酒后吐槽&#8221;，2002年左右，CEO贝佐斯就在亚马逊强制推行了以下六个原则（摘自<a href="http://coolshell.cn/articles/5701.html" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">酷壳</a>）：</p><ol style="margin: 10px 0px 10px 10px; padding: 0px 0px 0px 20px; border: 0px; width: 549px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">所有团队的程序模块都要以通过Service Interface 方式将其数据与功能开放出来。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">团队间的程序模块的信息通信，都要通过这些接口。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">除此之外没有其它的通信方式。其他形式一概不允许：<strong style="margin: 0px; border: 0px; padding: 0px;">不能使用直接链结程序、不能直接读取其他团队的数据库、不能使用共享内存模式、不能使用别人模块的后门、等等，等等，唯一允许的通信方式只能是能过调用 Service Interface。</strong></li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">任何技术都可以使用。比如：HTTP、Corba、Pubsub、自定义的网络协议、等等，都可以，贝佐斯不管这些。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;">所有的Service Interface，毫无例外，都必须从骨子里到表面上设计成能对外界开放的。也就是说，团队必须做好规划与设计，<strong style="margin: 0px; border: 0px; padding: 0px;">以便未来把接口开放给全世界的程序员，没有任何例外</strong>。</li><li style="margin: 4px 0px; padding: 0px 0px 0px 10px; border: none; float: none; clear: none;"><strong style="margin: 0px; border: 0px; padding: 0px;">不这样的做的人会被炒鱿鱼</strong>。</li></ol><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">据说，亚马逊网站展示一个产品明细的页面，可能要调用200-300个Service，以便生成高度个性化的内容。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">Steve还提到：</p><div id="lowerFullwidthVCR" style="margin: 0px; border: 0px; font-family: Arial, sans-serif; background-color: #ffffff;"></div><blockquote style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding-top: 10px; padding-bottom: 10px; padding-left: 45px; border-width: 1px; border-color: #e8e8e8; clear: both; width: 553px; color: #000000; font-family: Arial, sans-serif; float: none !important; background-image: url(http://cdn3.infoqstatic.com/styles/i/gg.jpg); background-color: #f4f4f4; background-position: 0% 0%; background-repeat: no-repeat;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 553px; word-wrap: break-word !important;">Amazon已经把文化转变成了&#8220;一切以Service第一&#8221;为系统架构的公司，今天，这已经成为他们进行所有设计时的基础，包括那些绝不会被外界所知的仅在内部使用的功能。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 553px; word-wrap: break-word !important;">那时，如果没有被解雇的的恐惧他们一定不会去做。我是说，他们今天仍然怕被解雇，因为这基本上是那儿每天的生活，为那恐怖的海盗头子贝佐斯工作。不过，他们这么做的确是因为他们已经相信Service这就是正确的方向。他们对于SOA的优点和缺点没有疑问，某些缺点还很大，也不疑问。但总的来说，这是正确的，因为，SOA驱动出来的设计会产生出平台（Platform）。</p></blockquote><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">今天，我们都知道亚马逊从世界上最大图书卖场进化为了世界上最成功的云平台&#8230;&#8230;</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">贝佐斯的六原则展示出高度的远见和超强的信念，即使放到十几年后的今天，依然觉得振聋发聩&#8230;&#8230;想起一句老话：&#8220;不谋万世者，不足以谋一时；不谋全局者，不足以谋一隅。&#8221;</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">当然，像贝佐斯这种将神性与魔性集于一身的专横人物，既可能创造划时代的进步，也可能制造前所未有的灾难。</p><h2>SOA漫谈：宏观与微观</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">SOA即面向服务架构，是一个特别大的话题。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">为了方便讨论，我在此先草率的将SOA分为两个层面（大概模仿宏观和微观经济学，但这里的划分没有绝对界限）：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><strong style="margin: 0px; border: 0px; padding: 0px;">宏观SOA</strong>：面向高层次的部门级别、公司级别甚至行业级别；涉及商业、管理、技术等方面的综合的、全局的考虑；架构体系上包括服务治理（governance，如服务注册，服务监控），服务编排（orchestration，如BPM，ESB)，服务协同（choreography，更多面向跨企业集成）等等。我认为SOA本身最主要是面向宏观层面的架构，其带来益处也最能在宏观高层次上体现出来，同时大部分SOA的业界讨论也集中在这方面。</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><strong style="margin: 0px; border: 0px; padding: 0px;">微观SOA</strong>：面向有限的、局部的团队和个人；涉及独立的、具体的服务在业务、架构、开发上的考虑。</li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">很多业界专家都认为SOA概念过于抽象，不接地气，我认为主要是宏观SOA涉及面太广，经常需要做通盘考虑，而其中很多方面距离一般人又比较远。而在微观层面的SOA更容易达到涛哥过去提出的&#8220;三贴近&#8221;：贴近实际、贴近生活、贴近群众。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">同时，宏观SOA要取得成功，通常的前提也是SOA在微观层面的落地与落实，正如宏观经济学一般要有坚实的微观基础（比如大名鼎鼎的凯恩斯主义曾广受诟病的一点就是缺乏微观基础）</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">因此，我们着眼于SOA落地的目的，着重来分析微观SOA，也算是对业界主流探讨的一个小小的补充。</p><h2>SOA定义</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">按照英文维基百科定义：SOA是一种&#8220;软件&#8221;和&#8220;软件架构&#8221;的设计模式（或者叫设计原则）。它是基于相互独立的软件片段要将自身的功能通过&#8220;服务&#8221;提供给其他应用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">什么是&#8220;服务&#8221;？按照OASIS的定义：Service是一种按照既定&#8220;接口&#8220;来访问一个或多个软件功能的机制（另外这种访问要符合&#8220;服务描述&#8221;中策略和限制）</p><h2>Service示例（代码通常以java示例）</h2><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn3.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">public interface Echo {     String echo(String text); }  public class EchoImpl implements Echo {     public String echo(String text) {         return text;     } }</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">可能每个开发人员每天都在写类似的面向对象的Service，难道这就是在实施SOA吗？</p><h2>SOA设计原则</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">既然SOA是设计原则（模式），那么它包含哪些内容呢？事实上，这方面并没有最标准的答案，多数是遵从著名SOA专家Thomas Erl的归纳：</p><blockquote style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding-top: 10px; padding-bottom: 10px; padding-left: 45px; border-width: 1px; border-color: #e8e8e8; clear: both; width: 553px; color: #000000; font-family: Arial, sans-serif; float: none !important; background-image: url(http://cdn3.infoqstatic.com/styles/i/gg.jpg); background-color: #f4f4f4; background-position: 0% 0%; background-repeat: no-repeat;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 553px; word-wrap: break-word !important;">标准化的服务契约 Standardized service contract 服务的松耦合 Service loose coupling 服务的抽象 Service abstraction 服务的可重用性 Service reusability 服务的自治性 Service autonomy 服务的无状态性 Service statelessness 服务的可发现性 Service discoverability 服务的可组合性 Service composability ....</p></blockquote><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">这些原则总的来说要达到的目的是：提高软件的重用性，减少开发和维护的成本，最终增加一个公司业务的敏捷度。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是，业界著名专家如Don Box，David Orchard等人对SOA又有各自不同的总结和侧重。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">SOA不但没有绝对统一的原则，而且很多原则本身的内容也具备相当模糊性和宽泛性：例如，所谓松耦合原则需要松散到什么程度才算是符合标准的呢？这就好比一个人要帅到什么程度才算是帅哥呢？一栋楼要高到多少米才算是高楼呢？可能不同人心中都有自己的一杆秤&#8230;&#8230;部分由于这些理论上的不确定因素，不同的人理解或者实施的SOA事实上也可能有比较大的差别。</p><h2>浅析松耦合原则</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">SOA原则比较多，真正的理解往往需要逐步的积累和体会，所以在此不详细展开。这里仅以服务的松耦合为例，从不同维度来简单剖析一下这个原则，以说明SOA原则内涵的丰富性：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">实现的松耦合</strong>：这是最基本的松耦合，即服务消费端不需要依赖服务契约的某个特定实现，这样服务提供端的内部变更就不会影响到消费端，而且消费端未来还可以自由切换到该契约的其他提供方。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">时间的松耦合</strong>：典型就是异步消息队列系统，由于有中介者（broker），所以生产者和消费者不必在同一时间都保持可用性以及相同的吞吐量，而且生产者也不需要马上等到回复。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">位置的松耦合</strong>：典型就是服务注册中心和企业服务总线（ESB），消费端完全不需要直接知道提供端的具体位置，而都通过注册中心来查找或者服务总线来路由。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;"><strong style="margin: 0px; border: 0px; padding: 0px;">版本的松耦合</strong>：消费端不需要依赖服务契约的某个特定版本来工作，这就要求服务的契约在升级时要尽可能的提供向下兼容性。</p></li></ul><h2>SOA与传统软件设计</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">我们可以认为：<strong style="margin: 0px; border: 0px; padding: 0px;">SOA &#8776; 模块化开发 + 分布式计算</strong></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">将两者传统上的最佳实践结合在一起，基本上可以推导出SOA的多数设计原则。SOA从软件设计（暂不考虑业务架构之类）上来讲，自身的新东西其实不算很多。</p><h2>SOA原则的应用</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">基于SOA的原则，也许我们很难说什么应用是绝对符合SOA的，但是却能剔除明显不符合SOA的应用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">用上述标准化契约，松耦合和可重用这几个原则来尝试分析一下上面Echo示例：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">Echo的服务契约是用Java接口定义，而不是一种与平台和语言无关的标准化协议，如WSDL，CORBA IDL。当然可以抬杠，Java也是行业标准，甚至全国牙防组一致认定的东西也是行业标准。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">Java接口大大加重了与Service客户端的耦合度，即要求客户端必须也是Java，或者JVM上的动态语言（如Groovy、Jython）等等&#8230;&#8230;</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">同时，Echo是一个Java的本地接口，就要求调用者最好在同一个JVM进程之内&#8230;&#8230;</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">Echo的业务逻辑虽然简单独立，但以上技术方面的局限就导致它无法以后在其他场合被轻易重用，比如分布式环境，异构平台等等。</p></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">因此，我们可以认为Echo并不太符合SOA的基本设计原则。</p><h2>透明化的转向SOA？</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">修改一下上面的Echo，添加Java EE的@WebServices注解（annotation）</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 10px 10px 10px 5px; border: 1px solid #e8e8e8; font-family: 'Courier New', Courier, monospace; color: #314e64; line-height: 18px; width: 597.796875px; overflow: auto; clear: none; font-size: 11px; float: none !important; background: url(http://cdn3.infoqstatic.com/styles/i/green_border.jpg) -29px 0px repeat-y #f4f4f4;">@WebServices public class EchoImpl implements Echo {     public String echo(String text) {         return text;     } }</pre><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">现在将Echo发布为Java WebServices，并由底层框架自动生成WSDL来作为标准化的服务契约，这样就能与远程的各种语言和平台互操作了，较好的解决了上面提到的松耦合和可重用的问题。按照一般的理解，Echo似乎就成为比较理想的SOA service了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但是&#8230;&#8230;即使这个极端简化的例子，也会引出不少很关键的问题，它们决定SOA设计开发的某些难度：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">将一个普通的Java对象通过添加注解&#8220;透明的&#8221;变成WebServices就完成了从面向对象到面向服务的跨越？</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">通过Java接口生成WSDL服务契约是好的方式吗？</li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;">WebServices是最合适远程访问技术吗？</li></ul><h2>面向对象和面向服务的对比</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">面向对象（OO）和面向服务（SO）在基础理念上有大量共通之处，比如都尽可能追求抽象、封装和低耦合。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">但SO相对于OO，又有非常不同的典型应用场景，比如：</p><ul style="margin: 0px 0px 15px 10px; padding: 0px; list-style-position: initial; list-style-image: initial; border: 0px; clear: left; font-family: Arial, sans-serif; background-color: #ffffff;"><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">多数OO接口（interface）都只被有限的人使用（比如团队和部门内），而SO接口（或者叫契约）一般来说都不应该对使用者的范围作出太多的限定和假设（可以是不同部门，不同企业，不同国家）。还记得贝佐斯原则吗？&#8220;团队必须做好规划与设计，以便未来把接口开放给全世界的程序员，没有任何例外&#8221;。</p></li><li style="margin: 0px 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none;"><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 1.5; clear: none; width: 585px;">多数OO接口都只在进程内被访问，而SO接口通常都是被远程调用。</p></li></ul><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">简单讲，就是SO接口使用范围比一般OO接口可能广泛得多。我们用网站打个比方：一个大型网站的web界面就是它整个系统入口点和边界，可能要面对全世界的访问者（所以经常会做国际化之类的工作），而系统内部传统的OO接口和程序则被隐藏在web界面之后，只被内部较小范围使用。而理想的SO接口和web界面一样，也是变成系统入口和边界，可能要对全世界开发者开放，因此SO在设计开发之中与OO相比其实会有很多不同。</p><h2>小结</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">在前述比较抽象的SOA大原则的基础上，我们可尝试推导一些较细化和可操作的原则，在具体实践中体现SO的独特之处。请关注本系列文章的下篇！</p><h2>作者简介</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;"><strong style="margin: 0px; border: 0px; padding: 0px;">沈理</strong>，当当网架构师和技术委员会成员，主要负责当当网的SOA实施（即服务化）以及分布式服务框架的开发。以前也有在BEA、Oracle、Redhat等外企的长期工作经历，从事过多个不同SOA相关框架和容器的开发。他的邮箱：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#104;&#101;&#110;&#108;&#105;&#64;&#100;&#97;&#110;&#103;&#100;&#97;&#110;&#103;&#46;&#99;&#111;&#109;" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">shenli@dangdang.com</a></p><hr style="margin: 0px; border: 0px; padding: 0px; font-family: Arial, sans-serif; background-color: #ffffff;" /><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; clear: none; width: 610px; font-family: Arial, sans-serif; background-color: #ffffff;">感谢<a href="http://www.infoq.com/cn/author/%E9%A9%AC%E5%9B%BD%E8%80%80" style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">马国耀</a>对本文的审校。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/418778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-16 14:05 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/16/418778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Alibaba Dubbo框架同步调用原理分析</title><link>http://www.blogjava.net/xiaomage234/archive/2014/05/09/413465.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 09 May 2014 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/05/09/413465.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/413465.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/05/09/413465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/413465.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/413465.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">由于Dubbo底层采用Socket进行通信，自己对通信理理论也不是很清楚，所以顺便把通信的知识也学习一下。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><strong><span style="color: #ff0000;">n&nbsp;&nbsp;</span><span style="color: #ff0000;">通信理论</span></strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">计算机与外界的信息交换称为通信。基本的通信方法有并行通信和串行通信两种。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">1.一组信息（通常是字节）的各位数据被同时传送的通信方法称为并行通信。并行通信依靠并行I／O接口实现。并行通信速度快，但传输线根数多，只适用于近距离（相距数公尺）的通信。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">2.一组信息的各位数据被逐位顺序传送的通信方式称为串行通信。串行通信可通过串行接口来实现。串行通信速度慢，但传输线少，适宜长距离通信。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">串行通信按信息传送方向分为以下3种：</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">1)&nbsp;&nbsp; 单工</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">只能一个方向传输数据</span></p><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><img alt="【原创】Alibaba Dubbo框架同步调用原理分析-1 - sun - 学无止境" src="http://img6.ph.126.net/4Z8Fj86s0IeWJ_P7tQ5fmA==/63613344753753206.gif" style="border: none; max-width: 100%;" /></span></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">2)&nbsp;&nbsp; 半双工</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">信息能双向传输，但不能同时双向传输</span></p><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><img alt="【原创】Alibaba Dubbo框架同步调用原理分析-1 - sun - 学无止境" src="http://img1.ph.126.net/pTny7rAMQwEs0bLRrUmASw==/2860348713350831781.jpg" style="border: none; max-width: 100%;" /></span></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">3)&nbsp;&nbsp; 全双工</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">能双向传输并且可以同时双向传输</span></p><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><img alt="【原创】Alibaba Dubbo框架同步调用原理分析-1 - sun - 学无止境" src="http://img4.ph.126.net/70UaD513hU-oXOxhQHB1Hw==/570831252786361674.jpg" style="border: none; max-width: 100%;" />&nbsp;</span></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><strong><span style="color: #ff0000;">n&nbsp;&nbsp;</span><span style="color: #ff0000;">Socket</span></strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">Socket&nbsp;是一种应用接口, TCP/IP&nbsp;是网络传输协议，虽然接口相同,&nbsp;但是不同的协议会有不同的服务性质。创建Socket&nbsp;连接时，可以指定使用的传输层协议，Socket&nbsp;可以支持不同的传输层协议（TCP&nbsp;或UDP&nbsp;），当使用TCP&nbsp;协议进行连接时，该Socket&nbsp;连接就是一个TCP&nbsp;连接。Soket&nbsp;跟TCP/IP&nbsp;并没有必然的联系。Socket&nbsp;编程接口在设计的时候，就希望也能适应其他的网络协议。所以，socket&nbsp;的出现只是可以更方便的使用TCP/IP&nbsp;协议栈而已。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">引自：<a href="http://hi.baidu.com/lewutian/blog/item/b28e27fd446d641d09244d08.html" rel="nofollow" style="color: #336699; text-decoration: none;">http://hi.baidu.com/lewutian/blog/item/b28e27fd446d641d09244d08.html</a></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><strong>上一个通信理论其实是想说Socket(TCP)通信是全双工的方式</strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><strong><span style="color: #ff0000;">n&nbsp; Dubbo</span><span style="color: #ff0000;">远程同步调用原理分析</span></strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">从Dubbo开源文档上了解到一个调用过程如下图</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><a href="http://code.alibabatech.com/wiki/display/dubbo/User+Guide#UserGuide-APIReference" rel="nofollow" style="color: #336699; text-decoration: none;">http://code.alibabatech.com/wiki/display/dubbo/User+Guide#UserGuide-APIReference</a></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">另外文档里有说明：<strong>Dubbo缺省协议采用单一长连接和NIO异步通讯</strong>，适合于小数据量大并发的服务调用，以及服务消费者机器数远大于服务提供者机器数的情况。</span></p><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><img alt="【原创】Alibaba Dubbo框架同步调用原理分析-1 - sun - 学无止境" src="http://img3.ph.126.net/4VW8afXcj6QhQrZfYNQnBw==/1545297622158648103.jpg" style="border: none; max-width: 100%;" /><br /></span><p><span style="font-size: 16px;">Dubbo缺省协议，使用基于mina1.1.7+hessian3.2.1的tbremoting交互。</span></p><ul><li><span style="font-size: 16px;">连接个数：单连接</span></li><li><span style="font-size: 16px;">连接方式：长连接</span></li><li><span style="font-size: 16px;">传输协议：TCP</span></li><li><span style="font-size: 16px;">传输方式：NIO异步传输</span></li><li><span style="font-size: 16px;">序列化：Hessian二进制序列化</span></li><li><span style="font-size: 16px;">适用范围：传入传出参数数据包较小（建议小于100K），消费者比提供者个数多，单一消费者无法压满提供者，</span><span style="font-size: 16px; color: red;">尽量不要用dubbo协议传输大文件或超大字符串</span><span style="font-size: 16px;">。</span></li><li><span style="font-size: 16px;">适用场景：常规远程服务方法调用</span></li></ul><span style="font-size: 16px;"><br /></span></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">&nbsp;通常，一个典型的同步远程调用应该是这样的：</span></p><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><img alt="【原创】Alibaba Dubbo框架同步调用原理分析-1 - sun - 学无止境" src="http://img0.ph.126.net/zmrEN_ZlqIF6LCg1HMR6cQ==/1109011408257132580.jpg" style="border: none; max-width: 100%;" /></span></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">1， 客户端线程调用远程接口，向服务端发送请求，同时当前线程应该处于&#8220;暂停&#8220;状态，即线程不能向后执行了，必需要拿到服务端给自己的结果后才能向后执行</span></p><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">2， 服务端接到客户端请求后，处理请求，将结果给客户端</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">3， 客户端收到结果，然后当前线程继续往后执行</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><br /></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">Dubbo里使用到了Socket（采用apache mina框架做底层调用）来建立长连接，发送、接收数据，底层使用apache mina框架的IoSession进行发送消息。</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><br /></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">查看Dubbo文档及源代码可知，Dubbo底层使用Socket发送消息的形式进行数据传递，结合了mina框架，使用IoSession.write()方法，这个方法调用后对于整个远程调用(从发出请求到接收到结果)来说是一个异步的，即对于当前线程来说，将请求发送出来，线程就可以往后执行了，至于服务端的结果，是服务端处理完成后，再以消息的形式发送给客户端的。于是这里出现了2个问题：</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><ul><li><span style="font-size: 16px;">当前线程怎么让它&#8220;暂停&#8221;，等结果回来后，再向后执行？</span></li><li><span style="font-size: 16px;">正如前面所说，Socket通信是一个全双工的方式，如果有多个线程同时进行远程方法调用，这时建立在client server之间的socket连接上会有很多双方发送的消息传递，前后顺序也可能是乱七八糟的，server处理完结果后，将结果消息发送给client，client收到很多消息，怎么知道哪个消息结果是原先哪个线程调用的？</span></li></ul></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><hr /></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">分析源代码，基本原理如下：</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><ol><li><span style="font-size: 16px;">client一个线程调用远程接口，生成一个唯一的ID（比如一段随机字符串，UUID等），Dubbo是使用AtomicLong从0开始累计数字的</span></li><li><span style="font-size: 16px;">将打包的方法调用信息（如调用的接口名称，方法名称，参数值列表等），和处理结果的回调对象callback，全部封装在一起，组成一个对象object</span></li><li><span style="font-size: 16px;">向专门存放调用信息的全局ConcurrentHashMap里面put(ID, object)</span></li><li><span style="font-size: 16px;">将ID和打包的方法调用信息封装成一对象connRequest，使用IoSession.write(connRequest)异步发送出去</span></li><li><span style="font-size: 16px;">当前线程再使用callback的get()方法试图获取远程返回的结果，在get()内部，则使用synchronized获取回调对象callback的锁， 再先检测是否已经获取到结果，如果没有，然后调用callback的wait()方法，释放callback上的锁，让当前线程处于等待状态。</span></li><li><span style="font-size: 16px;">服务端接收到请求并处理后，将结果（此结果中包含了前面的ID，即回传）发送给客户端，客户端socket连接上专门监听消息的线程收到消息，分析结果，取到ID，再从前面的ConcurrentHashMap里面get(ID)，从而找到callback，将方法调用结果设置到callback对象里。</span></li><li><span style="font-size: 16px;">监听线程接着使用synchronized获取回调对象callback的锁（因为前面调用过wait()，那个线程已释放callback的锁了），再notifyAll()，唤醒前面处于等待状态的线程继续执行（callback的get()方法继续执行就能拿到调用结果了），至此，整个过程结束。</span></li></ol></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><strong><span style="color: #ff0000;">这里还需要画一个大图来描述，后面再补了</span></strong></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">需要注意的是，这里的callback对象是每次调用产生一个新的，不能共享，否则会有问题；另外ID必需至少保证在一个Socket连接里面是唯一的。</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><hr /></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">现在，前面两个问题已经有答案了，</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><ul><li><span style="font-size: 16px;">当前线程怎么让它&#8220;暂停&#8221;，等结果回来后，再向后执行？</span></li></ul><span style="font-family: 宋体; font-size: 16px;">&nbsp; &nbsp; &nbsp;<strong>答：</strong>先生成一个对象obj，在一个全局map里put(ID,obj)存放起来，再用synchronized获取obj锁，再调用obj.wait()让当前线程处于等待状态，然后另一消息监听线程等到服务端结果来了后，再map.get(ID)找到obj，再用synchronized获取obj锁，再调用obj.notifyAll()唤醒前面处于等待状态的线程。<br /></span><ul><li><span style="font-size: 16px;">正如前面所说，Socket通信是一个全双工的方式，如果有多个线程同时进行远程方法调用，这时建立在client server之间的socket连接上会有很多双方发送的消息传递，前后顺序也可能是乱七八糟的，server处理完结果后，将结果消息发送给client，client收到很多消息，怎么知道哪个消息结果是原先哪个线程调用的？</span></li></ul></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;">&nbsp; &nbsp; &nbsp;<strong>答：</strong>使用一个ID，让其唯一，然后传递给服务端，再服务端又回传回来，这样就知道结果是原先哪个线程的了。</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><br /></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 16px;"><span style="color: #ff0000;">这种做法不是第一次见了，10年在上一公司里，也是远程接口调用，不过走的消息中间件rabbitmq，同步调用的原理跟这类似，详见：</span><a href="http://sunjun041640.blog.163.com/blog/static/25626832201032911332857/" target="_blank" style="color: #336699; text-decoration: none;"><font color="#336699">rabbitmq 学习-9- RpcClient发送消息和同步接收消息原理</font><br /><br /></a></span><p><span style="font-size: 16px;">关键代码：</span></p><table border="1" cellspacing="0" cellpadding="0" style="color: #333333; font-size: 14px; line-height: 26px;"><tbody><tr><td valign="top"><p><strong>com.taobao.remoting.impl.DefaultClient.java</strong></p><p><strong>//同步调用远程接口</strong></p><p>public Object invokeWithSync(Object appRequest, RequestControl control) throws RemotingException, InterruptedException {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte protocol = getProtocol(control);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!TRConstants.isValidProtocol(protocol)) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new RemotingException("Invalid serialization protocol [" + protocol + "] on invokeWithSync.");</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResponseFuture future = invokeWithFuture(appRequest, control);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return future.get();&nbsp;<strong>&nbsp;//获取结果时让当前线程等待，ResponseFuture其实就是前面说的callback</strong></p><p>}</p><p>public ResponseFuture&nbsp;<strong>invokeWithFuture</strong>(Object appRequest, RequestControl control) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte protocol = getProtocol(control);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long timeout = getTimeout(control);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ConnectionRequest request = new ConnectionRequest(appRequest);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.setSerializeProtocol(protocol);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Callback2FutureAdapter adapter = new Callback2FutureAdapter(request);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.sendRequestWithCallback(request, adapter, timeout);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return adapter;</p><p>}</p></td></tr></tbody></table><p><span style="font-size: 16px;">&nbsp;</span></p><table border="1" cellspacing="0" cellpadding="0" style="color: #333333; font-size: 14px; line-height: 26px;"><tbody><tr><td valign="top"><p><span style="font-family: arial;"><strong>Callback2FutureAdapter implements ResponseFuture</strong></span></p><p><span style="font-family: arial;">public Object get() throws RemotingException, InterruptedException {</span></p><p><span style="font-family: arial;">synchronized (this) { &nbsp;// 旋锁</span></p><p><span style="font-family: arial;">&nbsp; &nbsp;while (!isDone) { &nbsp;<span style="color: #ff0000;"><strong>// 是否有结果了</strong></span></span></p><p><span style="font-family: arial;">wait();<strong><span style="color: #ff0000;">&nbsp;//没结果是释放锁，让当前线程处于等待状态</span></strong></span></p><p><span style="font-family: arial;">&nbsp; &nbsp;}</span></p><p><span style="font-family: arial;">}</span></p><p><span style="font-family: arial;">if (errorCode == TRConstants.RESULT_TIMEOUT) {</span></p><p><span style="font-family: arial;">&nbsp; &nbsp;throw new TimeoutException("Wait response timeout, request["</span></p><p><span style="font-family: arial;">&nbsp; &nbsp;+ connectionRequest.getAppRequest() + "].");</span></p><p><span style="font-family: arial;">}</span></p><p><span style="font-family: arial;">else if (errorCode &gt; 0) {</span></p><p><span style="font-family: arial;">&nbsp; &nbsp;throw new RemotingException(errorMsg);</span></p><p><span style="font-family: arial;">}</span></p><p><span style="font-family: arial;">else {</span></p><p><span style="font-family: arial;">&nbsp; &nbsp;return appResp;</span></p><p><span style="font-family: arial;">}</span></p><p><span style="font-family: arial;">}</span></p><p><strong>客户端收到服务端结果后，回调时相关方法，即设置isDone = true并notifyAll()</strong></p><p>public void handleResponse(Object _appResponse) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; appResp = _appResponse;&nbsp;<strong>//将远程调用结果设置到callback中来</strong></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setDone();</p><p>}</p><p>public void onRemotingException(int _errorType, String _errorMsg) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errorCode = _errorType;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errorMsg = _errorMsg;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setDone();</p><p>}</p><p>private void setDone() {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isDone = true;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (this) {&nbsp;<strong>//获取锁，因为前面wait()已经释放了callback的锁了</strong></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; notifyAll();<strong>&nbsp;// 唤醒处于等待的线程</strong></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>}</p></td></tr></tbody></table><p><span style="font-size: 16px;">&nbsp;</span></p><table border="1" cellspacing="0" cellpadding="0" style="color: #333333; font-size: 14px; line-height: 26px;"><tbody><tr><td valign="top"><p><strong>com.taobao.remoting.impl.DefaultConnection.java</strong></p><p><strong>&nbsp;</strong></p><p><strong>// 用来存放请求和回调的MAP</strong></p><p>private final ConcurrentHashMap&lt;Long, Object[]&gt; requestResidents;</p><p><strong>&nbsp;</strong></p><p><strong>//发送消息出去</strong></p><p>void sendRequestWithCallback(ConnectionRequest connRequest, ResponseCallback callback, long timeoutMs) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long requestId = connRequest.getId();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long waitBegin = System.currentTimeMillis();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long waitEnd = waitBegin + timeoutMs;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object[] queue = new Object[4];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int idx = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queue[idx++] = waitEnd;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queue[idx++] = waitBegin;&nbsp;&nbsp; //用于记录日志</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queue[idx++] = connRequest; //用于记录日志</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queue[idx++] = callback;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; requestResidents.put(requestId, queue); // 记录响应队列</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write(connRequest);</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 埋点记录等待响应的Map的大小</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StatLog.addStat("TBRemoting-ResponseQueues", "size", requestResidents.size(),</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1L);</p><p>}</p><p>public void write(final Object connectionMsg) {</p><p><strong>//mina里的IoSession.write()发送消息</strong></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WriteFuture writeFuture = ioSession.write(connectionMsg);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 注册FutureListener，当请求发送失败后，能够立即做出响应</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writeFuture.addListener(new MsgWrittenListener(this, connectionMsg));</p><p>}</p><p>&nbsp;</p><p>/**</p><p>* 在得到响应后，删除对应的请求队列，并执行回调</p><p>* 调用者：MINA线程</p><p>*/</p><p>public void putResponse(final ConnectionResponse connResp) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final long requestId = connResp.getRequestId();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object[] queue = requestResidents.remove(requestId);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (null == queue) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object appResp = connResp.getAppResponse();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String appRespClazz = (null == appResp) ? "null" : appResp.getClass().getName();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; StringBuilder sb = new StringBuilder();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb.append("Not found response receiver for requestId=[").append(requestId).append("],");</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb.append("from [").append(connResp.getHost()).append("],");</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb.append("response type [").append(appRespClazz).append("].");</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; LOGGER.warn(sb.toString());</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int idx = 0;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; idx++;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long waitBegin = (Long) queue[idx++];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ConnectionRequest connRequest = (ConnectionRequest) queue[idx++];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResponseCallback callback = (ResponseCallback) queue[idx++];</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ** 把回调任务交给业务提供的线程池执行 **</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Executor callbackExecutor = callback.getExecutor();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; callbackExecutor.execute(new CallbackExecutorTask(connResp, callback));</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long duration = System.currentTimeMillis() - waitBegin; // 实际读响应时间</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; logIfResponseError(connResp, duration, connRequest.getAppRequest());</p><p>}</p></td></tr></tbody></table><p><span style="font-size: 16px;">&nbsp;</span></p><table border="1" cellspacing="0" cellpadding="0" style="color: #333333; font-size: 14px; line-height: 26px;"><tbody><tr><td valign="top"><p><strong>CallbackExecutorTask</strong></p><p>static private class CallbackExecutorTask implements Runnable {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ConnectionResponse resp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ResponseCallback callback;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final Thread createThread;</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CallbackExecutorTask(ConnectionResponse _resp, ResponseCallback _cb) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; resp = _resp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; callback = _cb;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; createThread = Thread.currentThread();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 预防这种情况：业务提供的Executor，让调用者线程来执行任务</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (createThread == Thread.currentThread()</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &amp;&amp; callback.getExecutor() != DIYExecutor.getInstance()) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuilder sb = new StringBuilder();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append("The network callback task [" + resp.getRequestId() + "] cancelled, cause:");</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append("Can not callback task on the network io thhread.");</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LOGGER.warn(sb.toString());</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (TRConstants.RESULT_SUCCESS == resp.getResult()) {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; callback.handleResponse(resp.getAppResponse());&nbsp;<strong>//设置调用结果</strong></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; callback.onRemotingException(resp.getResult(), resp</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getErrorMsg());&nbsp;&nbsp;<strong>//处理调用异常</strong></p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p>}</p></td></tr></tbody></table><p><span style="font-size: 16px;">&nbsp;</span></p><p><span style="font-size: 16px;"><strong>另外：</strong></span></p><p><span style="font-size: 16px;"><strong>1， 服务端在处理客户端的消息，然后再处理时，使用了线程池来并行处理，不用一个一个消息的处理</strong></span></p><p><span style="font-size: 16px;"><strong>同样，客户端接收到服务端的消息，也是使用线程池来处理消息，再回调</strong></span></p><p>&nbsp;</p><p>转载自：<a href="http://sunjun041640.blog.163.com/blog/static/256268322011111882453405/" style="color: #336699; text-decoration: none;">http://sunjun041640.blog.163.com/blog/static/256268322011111882453405/</a></p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/413465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-05-09 15:49 <a href="http://www.blogjava.net/xiaomage234/archive/2014/05/09/413465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>蚂蚁变大象：浅谈常规网站是如何从小变大的</title><link>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413302.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 06 May 2014 02:07:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413302.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/413302.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413302.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/413302.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/413302.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 2005年，我开始和朋友们开始拉活儿做网站，当时第一个网站是在linux上用jsp搭建的，到后来逐步的引入了多种框架，如webwork、hibernate等。在到后来，进入公司，开始用c/c++，做分布式计算和存储。（到那时才解开了我的一个疑惑：C语言除了用来写HelloWorld，还能干嘛？^_^）。总而言之，网站根据不同的需求，不同的请求压力，不同的业务模型，需要不同的架构来给予支持。我从我的...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/05/06/413302.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/413302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-05-06 10:07 <a href="http://www.blogjava.net/xiaomage234/archive/2014/05/06/413302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CAP原理和BASE思想</title><link>http://www.blogjava.net/xiaomage234/archive/2013/04/23/398291.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 23 Apr 2013 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2013/04/23/398291.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/398291.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2013/04/23/398291.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/398291.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/398291.html</trackback:ping><description><![CDATA[<h1><div><span style="font-size: 10pt;">分布式领域CAP理论，</span></div><div><span style="font-size: 10pt;">Consistency(一致性), 数据一致更新，所有数据变动都是同步的</span></div><div><span style="font-size: 10pt;">Availability(可用性), 好的响应性能</span></div><div><span style="font-size: 10pt;">Partition tolerance(分区容错性) 可靠性</span></div><div></div><div><span style="font-size: 10pt;">定理：任何分布式系统只可同时满足二点，没法三者兼顾。</span></div><div><span style="font-size: 10pt;">忠告：架构师不要将精力浪费在如何设计能满足三者的完美分布式系统，而是应该进行取舍。</span></div><div></div><div><span style="font-size: 10pt;">关系数据库的ACID模型拥有 高一致性 + 可用性 很难进行分区：</span></div><div><span style="font-size: 10pt;">Atomicity原子性：一个事务中所有操作都必须全部完成，要么全部不完成。</span></div><div><span style="font-size: 10pt;">Consistency一致性. 在事务开始或结束时，数据库应该在一致状态。</span></div><div><span style="font-size: 10pt;">Isolation隔离层. 事务将假定只有它自己在操作数据库，彼此不知晓。</span></div><div><span style="font-size: 10pt;">Durability. 一旦事务完成，就不能返回。</span></div><div><span style="font-size: 10pt;">跨数据库事务：2PC (two-phase commit)， 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的，JavaEE中的JTA事务可以支持2PC。因为2PC是反模式，尽量不要使用2PC，使用BASE来回避。</span></div><div></div><div><span style="font-size: 10pt;">BASE模型反ACID模型，完全不同ACID模型，牺牲高一致性，获得可用性或可靠性：</span></div><div><span style="font-size: 10pt;">Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)</span></div><div><span style="font-size: 10pt;">Soft state软状态 状态可以有一段时间不同步，异步。</span></div><div><span style="font-size: 10pt;">Eventually consistent最终一致，最终数据是一致的就可以了，而不是时时高一致。</span></div><div></div><div><span style="font-size: 10pt;">BASE思想的主要实现有</span></div><div><span style="font-size: 10pt;">1.按功能划分数据库</span></div><div><span style="font-size: 10pt;">2.sharding碎片&nbsp;</span></div><div></div><div><span style="font-size: 10pt;">BASE思想主要强调基本的可用性，如果你需要High 可用性，也就是纯粹的高性能，那么就要以一致性或容错性为牺牲，BASE思想的方案在性能上还是有潜力可挖的。</span></div><div></div><div><span style="font-size: 10pt;">现在NoSQL运动丰富了拓展了BASE思想，可按照具体情况定制特别方案，比如忽视一致性，获得高可用性等等，NOSQL应该有下面两个流派：</span></div><div><span style="font-size: 10pt;">1. Key-Value存储，如Amaze Dynamo等，可根据CAP三原则灵活选择不同倾向的数据库产品。</span></div><div><span style="font-size: 10pt;">2. 领域模型 + 分布式缓存 + 存储 （Qi4j和NoSQL运动），可根据CAP三原则结合自己项目定制灵活的分布式方案，难度高。</span></div><div></div><div><span style="font-size: 10pt;">这两者共同点：都是关系数据库SQL以外的可选方案，逻辑随着数据分布，任何模型都可以自己持久化，将数据处理和数据存储分离，将读和写分离，存储可以是异步或同步，取决于对一致性的要求程度。</span></div><div></div><div><span style="font-size: 10pt;">不同点：NOSQL之类的Key-Value存储产品是和关系数据库头碰头的产品BOX，可以适合非Java如PHP RUBY等领域，是一种可以拿来就用的产品，而领域模型 + 分布式缓存 + 存储是一种复杂的架构解决方案，不是产品，但这种方式更灵活，更应该是架构师必须掌握的。</span></div></h1><img src ="http://www.blogjava.net/xiaomage234/aggbug/398291.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2013-04-23 16:18 <a href="http://www.blogjava.net/xiaomage234/archive/2013/04/23/398291.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>