新書推薦:
《
新民说·现实政治史:从马基雅维利到基辛格
》
售價:HK$
102.4
《
宽容是件奢侈品(人生360度·一分钟经典故事)
》
售價:HK$
45.8
《
甲骨拼合六集
》
售價:HK$
342.7
《
视觉美食家:商业摄影实战与创意解析
》
售價:HK$
135.7
《
中国经济发展的新阶段:机会与选择
》
售價:HK$
102.4
《
DK月季玫瑰百科
》
售價:HK$
216.2
《
为你想要的生活
》
售價:HK$
67.9
《
关键改变:如何实现自我蜕变
》
售價:HK$
79.4
編輯推薦:
★一个长期战斗在一线的美团-大众点评技术专家
★详细讲述了分布式服务框架的底层实现细节
★清楚梳理了分布式服务框架周边的知识点
★从零开始构建了一个分布式服务框架
★实战操练的代码透漏出作者身经百战的深厚功力
★技术原理和内部实现分析提升技术理解和洞察力
★目前企业真正使用微服务非常少,而使用分布式服务框架比较多,实现相对简单,作者所在公司美团在分布式服务框架实现方面具有丰富的经验。
★《架构探险:从零开始写分布式服务框架》能顺利地带领你走出架构险境,让你对分布式服务框架所涉及的技术了然于胸,并能合理地利用这些技术,搭建符合自身需求的分布式服务框架。
內容簡介:
分布式服务框架目前已经是互联网公司实现SOA服务化架构的必备基础设施,对于一般的开发而言,自己要独立实现一个分布式服务框架,还是有相当的难度的。本书围绕如何从零开始实现一个可用的分布式服务框架,介绍了实现分布式服务框架所需技术的方方面面。对于从事开发行业的程序员有很大的现实价值。能够从中学习到很多的实用技术,了解并掌握实现分布式服务框架所需的思想以及技术。
關於作者:
李业兵
先后在支付宝运营支撑事业部、去哪儿网酒店事业部任职高级开发工程师。于2015年加入猫眼电影(原美团网旗下电影事业部),负责交易业务线架构与开发工作。
擅长电商交易领域系统设计与架构,在电商交易领域系统架构设计方面积累了较为丰富的实践经验。
对高并发系统设计、服务化架构、互联网中间件开发保持着浓厚的兴趣。
目錄 :
第1章常用的RPC框架1
1.1RPC框架原理1
1.2RMI介绍2
1.2.1原生RMI代码示例3
1.2.2RMI穿透防火墙5
1.3CXFAxis2介绍7
1.3.1CXF介绍7
1.3.2Axis2介绍14
1.4Thrift介绍21
1.4.1Thrift工作原理介绍23
1.4.2Thrift IDL语法说明26
1.4.3基于Apache Thrift的Java版完整案例28
1.4.4基于Java注解的简化实现36
1.5gRPC介绍42
1.5.1protobuf3语法介绍43
1.5.2gRPC使用示例45
1.6HTTP Client介绍53
1.6.1构建HttpClient对象54
1.6.2构建URI对象55
1.6.3构建请求对象(HttpGet、HttpPost)56
1.6.4HttpClient发起调用及获取调用返回结果56
1.7实现自己的RPC框架61
1.8RPC框架与分布式服务框架的区别68
1.9本章小结68
第2章分布式服务框架总体架构与功能69
2.1面向服务的体系架构(SOA)69
2.1.1面向服务架构范式69
2.1.2服务拆分原则71
2.2分布式服务框架现实需求72
2.3分布式服务框架总体架构及所需的技术概述72
2.4本章小结74
第3章分布式服务框架序列化与反序列化实现75
3.1序列化原理及常用的序列化介绍75
3.2Java默认的序列化77
3.3XML序列化框架介绍80
3.4JSON序列化框架介绍82
3.5Hessian序列化框架介绍87
3.6protobuf序列化框架介绍88
3.7protostuff序列化框架介绍93
3.8Thrift序列化框架介绍98
3.9Avro序列化框架介绍100
3.9.1Avro介绍100
3.9.2Avro IDL语言介绍101
3.9.3Schema定义介绍103
3.9.4Maven配置及使用IDL与Schema自动生成代码103
3.9.5Avro序列化反序列化实现105
3.10JBoss Marshalling序列化框架介绍110
3.11序列化框架的选型112
3.12实现自己的序列化工具引擎113
3.13本章小结118
第4章实现分布式服务框架服务的发布与引入119
4.1Spring Framework框架概述119
4.1.1Spring Framework介绍119
4.1.2Spring Framework周边生态项目介绍121
4.2FactoryBean的秘密122
4.2.1FactoryBean的作用及使用场景123
4.2.2FactoryBean实现原理及示例说明124
4.3Spring框架对于已有RPC框架集成的支持127
4.3.1Spring支持集成RPC框架介绍127
4.3.2基于RmiProxyFactoryBean 实现RMI与Spring的集成128
4.3.3基于HttpInvokerProxyFactoryBean实现HTTP Invoker与Spring的集成131
4.3.4基于HessianProxyFactoryBean实现Hessian与Spring的集成133
4.4实现自定义服务框架与Spring的集成136
4.4.1实现远程服务的发布136
4.4.2实现远程服务的引入144
4.5在Spring中定制自己的XML标签150
4.6本章小结158
第5章分布式服务框架注册中心159
5.1服务注册中心介绍159
5.2ZooKeeper实现服务的注册中心原理161
5.2.1ZooKeeper介绍161
5.2.2部署ZooKeeper161
5.2.3ZkClient使用介绍164
5.2.4ZooKeeper实现服务注册中心173
5.3集成ZooKeeper实现自己的服务注册与发现175
5.3.1服务注册中心服务提供方175
5.3.2服务注册中心服务消费方176
5.3.3服务注册中心实现178
5.4本章小结189
第6章分布式服务框架底层通信实现190
6.1Java IO模型及IO类库的进化190
6.1.1Linux下实现的IO模型190
6.1.2Java语言实现的IO模型194
6.1.3Java Classic IO(Blocking IO)介绍194
6.1.4Java Non-blocking IO(NIO)介绍211
6.1.5NIO2及Asynchronous IO介绍233
6.2Netty使用介绍255
6.2.1Netty开发入门256
6.2.2Netty粘包半包问题解决265
6.3使用Netty构建服务框架底层通信320
6.3.1构建分布式服务框架Netty服务端320
6.3.2构建分布式服务框架服务调用端Netty客户端330
6.4本章小结347
第7章分布式服务框架软负载实现348
7.1软负载的实现原理348
7.2负载均衡常用算法349
7.2.1软负载随机算法实现349
7.2.2软负载加权随机算法实现350
7.2.3软负载轮询算法实现351
7.2.4软负载加权轮询算法实现352
7.2.5软负载源地址hash算法实现354
7.3实现自己的软负载机制355
7.4软负载在分布式服务框架中的应用357
7.5本章小结361
第8章分布式服务框架服务治理362
8.1服务治理介绍362
8.2服务治理的简单实现364
8.2.1服务分组路由实现364
8.2.2简单服务依赖关系分析实现374
8.2.3服务调用链路跟踪实现原理380
8.3本章小结380
附录A如何配置运行本书完成的分布式服务框架381
內容試閱 :
推荐序
2015年,我写了自己的第一本书《架构探险:从零开始写Java Web框架》,书中记录了一款轻量级Java Web框架的整个开发过程。我将该框架取名为Smart Framework,因为我认为Java Web框架应该更容易上手,运行得更快,更加轻量级。
为何我要写架构探险?
我希望有更多看过这本书的朋友,能够对Java Web框架的底层原理更加清楚,不仅能熟练使用框架,而且还能知道框架底层都做了些什么,做到知其然,知其所以然,我认为所有的开发者都应该这样要求自己。
此外,我认为学习技术的最有效方式就是分享,只有分享才能让自己得到更快的进步。但在分享之前,我们需要花时间去不断学习,这个学习过程也许是痛苦的,但当自己将所学技能分享出去的时候却是快乐的。不仅如此,我们通过分享还会收到大家更多的反馈,这些反馈能够帮助我们得到更加全面的成长。
架构和探险有何关系?
架构说简单点就是一堆技术、框架、工具的组合,至于怎么组合,这就非常考验架构师的经验和水平。一个优秀的架构,可以让开发效率变得更加高效,为企业节省更多的成本。程序员可将自己更多的精力放在业务需求的实现上,不会被底层的复杂技术细节所干扰。
架构师(或从事架构工作的人)就像是探险者一样,他们走在团队的前面,为大家铺路,带领大家找到成功捷径。此外,做架构工作不能照搬别人所谓的最佳实践,而要根据自身实际情况,因地制宜地灵活选择,设计最为合理的架构。架构的目的是为了让业务变得更加容易落地,降低开发成本与统一开发规范。架构师的职责就是避免大家踩坑,他们需要将自己的经验总结下来,并带领大家走最正确的路。架构师不只是在体验探险的凶险和快乐,而是把探险所积累的经验沉淀下来,让后面更多的人从中受益。
架构探险是一种信仰
其实我们都在架构中探险,或许自己目前正身陷险境,我们希望得到一本宝典,教会自己应该如何找到架构的成功捷径。李业兵老师写的这本《架构探险:从零开始写分布式服务框架》就能顺利地带领我们走出险境,让我们对分布式服务框架所涉及的技术了然于胸,并能合理地利用这些技术,搭建符合自身需求的分布式服务框架。
这本书传递了架构探险的精神,让我更加深刻地感受到,其实架构探险是一种信仰,它指引我们在架构之路上继续前进。
黄勇特赞科技CTO
2017年6月
前言
缘起
随着互联网浪潮风起云涌,互联网行业发展非常迅猛。此时将所有业务集中实现在一个应用上的做法已经满足不了公司及业务发展的需要了。基于面向服务体系架构来构建系统成了互联网架构师构建系统的不二选择,而面向服务体系架构能够落地的基础技术之一就是分布式服务框架。
要完全掌握分布式服务框架存在一定的技术门槛,市面上不乏一些非常出色的开源分布式服务框架。但对于新手而言,直接通过阅读源码来掌握分布式服务框架原理也并不是一件特别容易的事。
现在市面上也有专门的书籍来介绍分布式服务框架,但大都是从理论和方法论的角度来描述其原理的。有句俗语:有些事,难不难,做了才知道;有些山,陡不陡,爬了才知道。对于程序员来说,总是想通过具体的代码来了解一个分布式服务框架的实现细节,这样更为直观和深刻。为了帮助部分想了解分布式服务框架内部实现原理,甚至想自己实现一个分布式服务框架的读者,我写了这样一本介绍如何从零开始写一个分布式服务框架的书,希望能够对想了解分布式服务框架实现细节的读者有所帮助。
内容大纲
全书一共8章。按照分布式服务框架的各个组成部分及各个组成部分所需的知识点或者这些知识点适当的延伸来组织每一章节的内容。建议读者按照全书章节的组织顺序来阅读。
第1章主要介绍日常开发常用的RPC框架,包括RMI、CXF、Axis2、Thrift、gRPC、HttpClient,并就每一种RPC框架给出了实际可运行的代码示例,以及自己实现的一个简易版的RPC框架。
第2章对于基于服务体系架构做了介绍,对分布式服务框架总体架构及实现分布式服务框架所需的技术做了概要性介绍。
第3章介绍9种序列化反序列化方案,每一种序列化反序列化方案均给出了相应的代码示例,并给出了具体的选型建议。同时,将这9种序列化反序列化实现集成在一起,实现了可配置化的序列化反序列化工具引擎,最终整合在分布式服务框架实现内部。
第4章对Spring做了概要性介绍。有针对性地对FactoryBean周边知识及如何使用FactoryBean实现分布式服务的发布和引入做了详细介绍并给出代码实现。
第5章介绍ZooKeeper常用知识及如何使用ZooKeeper实现服务的注册与发现,并给出了具体的代码实现。
第6章围绕系统之间底层通信相关的知识点来组织,从Java IO 体系(阻塞IO、NIO、NIO2)到Netty相关知识均做了详细介绍。最后就使用Netty实现分布式服务框架底层通信给出了代码实现。
第7章介绍常用的软负载算法,并针对每一种算法给出了代码实现。同时将实现的多种软负载算法集成可配置的软负载工具引擎,最终整合在分布式服务框架实现内部。
第8章介绍分布式服务框架服务治理相关的概念及方法论,并就部分服务治理功能给出了具体实现。
全书完整地实现了一个可以实际运行的分布式服务框架,全书所有代码均提供下载。
致谢
首先感谢我的妻子,在写书这段时间,宝宝的出生给了我人生中最好的礼物,宝宝的咿呀学语、一个不经意的笑容都能给我莫大的支持和鼓励。
同时,感谢猫眼电影公司的同事和领导,给了我宽松的学习与工作氛围,学到了很多知识,也得到了很多成长的机会。
最后,感谢辛苦劳作的编辑,本书能够出版有你们很大的一份功劳。
写在最后
这本书偏向实战,会有很多代码实现细节的描述,全书完整的代码实现会另给下载链接。本书所实现的分布式服务框架并未经历严苛生产环境的考验,定有很多不足之处,希望日后有机会再继续完善。写书对我来说是一个比较大的挑战,因为一个技术点,自己能理解和会用文字表达出来让别人也能理解是完全不同的层次。心中特别忐忑,担心因为自己对知识理解不够深入,以及文字表达水平不够,导致对读者有所误导。书中难免有错误和疏漏之处,在此恳请读者批评指正。
李业兵
前言
缘起
随着互联网浪潮风起云涌,互联网行业发展非常迅猛。此时将所有业务集中实现在一个应用上的做法已经满足不了公司及业务发展的需要了。基于面向服务体系架构来构建系统成了互联网架构师构建系统的不二选择,而面向服务体系架构能够落地的基础技术之一就是分布式服务框架。
要完全掌握分布式服务框架存在一定的技术门槛,市面上不乏一些非常出色的开源分布式服务框架。但对于新手而言,直接通过阅读源码来掌握分布式服务框架原理也并不是一件特别容易的事。
现在市面上也有专门的书籍来介绍分布式服务框架,但大都是从理论和方法论的角度来描述其原理的。有句俗语:有些事,难不难,做了才知道;有些山,陡不陡,爬了才知道。对于程序员来说,总是想通过具体的代码来了解一个分布式服务框架的实现细节,这样更为直观和深刻。为了帮助部分想了解分布式服务框架内部实现原理,甚至想自己实现一个分布式服务框架的读者,我写了这样一本介绍如何从零开始写一个分布式服务框架的书,希望能够对想了解分布式服务框架实现细节的读者有所帮助。
内容大纲
全书一共8章。按照分布式服务框架的各个组成部分及各个组成部分所需的知识点或者这些知识点适当的延伸来组织每一章节的内容。建议读者按照全书章节的组织顺序来阅读。
第1章主要介绍日常开发常用的RPC框架,包括RMI、CXF、Axis2、Thrift、gRPC、HttpClient,并就每一种RPC框架给出了实际可运行的代码示例,以及自己实现的一个简易版的RPC框架。
第2章对于基于服务体系架构做了介绍,对分布式服务框架总体架构及实现分布式服务框架所需的技术做了概要性介绍。
第3章介绍9种序列化反序列化方案,每一种序列化反序列化方案均给出了相应的代码示例,并给出了具体的选型建议。同时,将这9种序列化反序列化实现集成在一起,实现了可配置化的序列化反序列化工具引擎,最终整合在分布式服务框架实现内部。
第4章对Spring做了概要性介绍。有针对性地对FactoryBean周边知识及如何使用FactoryBean实现分布式服务的发布和引入做了详细介绍并给出代码实现。
第5章介绍ZooKeeper常用知识及如何使用ZooKeeper实现服务的注册与发现,并给出了具体的代码实现。
第6章围绕系统之间底层通信相关的知识点来组织,从Java IO 体系(阻塞IO、NIO、NIO2)到Netty相关知识均做了详细介绍。最后就使用Netty实现分布式服务框架底层通信给出了代码实现。
第7章介绍常用的软负载算法,并针对每一种算法给出了代码实现。同时将实现的多种软负载算法集成可配置的软负载工具引擎,最终整合在分布式服务框架实现内部。
第8章介绍分布式服务框架服务治理相关的概念及方法论,并就部分服务治理功能给出了具体实现。
全书完整地实现了一个可以实际运行的分布式服务框架,全书所有代码均提供下载。
致谢
首先感谢我的妻子,在写书这段时间,宝宝的出生给了我人生中最好的礼物,宝宝的咿呀学语、一个不经意的笑容都能给我莫大的支持和鼓励。
同时,感谢猫眼电影公司的同事和领导,给了我宽松的学习与工作氛围,学到了很多知识,也得到了很多成长的机会。
最后,感谢辛苦劳作的编辑,本书能够出版有你们很大的一份功劳。
写在最后
这本书偏向实战,会有很多代码实现细节的描述,全书完整的代码实现会另给下载链接。本书所实现的分布式服务框架并未经历严苛生产环境的考验,定有很多不足之处,希望日后有机会再继续完善。写书对我来说是一个比较大的挑战,因为一个技术点,自己能理解和会用文字表达出来让别人也能理解是完全不同的层次。心中特别忐忑,担心因为自己对知识理解不够深入,以及文字表达水平不够,导致对读者有所误导。书中难免有错误和
7.2 负载均衡常用算法
负载均衡常用算法主要有随机、加权随机、轮询、加权轮询、源地址hash等。
7.2.1 软负载随机算法实现
随机算法原理为:获取服务列表大小范围内的随机数,将该随机数作为列表索引,从服务提供列表中获取服务提供者。
为负载均衡策略算法定义接口如下:
public interface ClusterStrategy {
public ProviderService selectList providerServices;
}
其中接口方法入参providerServices为服务提供者列表。
软负载随机算法的实现过程如下。
import ares.remoting.framework.cluster.ClusterStrategy;
import ares.remoting.framework.model.ProviderService;
import org.apache.commons.lang3.RandomUtils;
import java.util.List;
public class RandomClusterStrategyImpl implements ClusterStrategy {
@Override
public ProviderService selectList providerServices {
int MAX_LEN = providerServices.size;
int index = RandomUtils.nextInt0, MAX_LEN - 1;
return providerServices.getindex;
}
}
实现原理:获得服务提供者列表大小区间之间的随机数,作为服务提供者列表的索引来获取服务。
7.2.2 软负载加权随机算法实现
加权随机算法在随机算法的基础上针对权重做了处理。软负载加权随机算法实现代码如下。
import ares.remoting.framework.cluster.ClusterStrategy;
import ares.remoting.framework.model.ProviderService;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.RandomUtils;
import java.util.List;
public class WeightRandomClusterStrategyImpl implements ClusterStrategy {
@Override
public ProviderService selectList providerServices {
存放加权后的服务提供者列表
List providerList = Lists.newArrayList;
for ProviderService provider : providerServices {
int weight = provider.getWeight;
for int i = 0; i providerList.addprovider.copy;
}
}
int MAX_LEN = providerList.size;
int index = RandomUtils.nextInt0, MAX_LEN - 1;
return providerList.getindex;
}
}
实现原理:首先根据加权数放大服务提供者列表,比如服务提供者A加权数为3,放大之后变为A,A,A,存放在新的服务提供者列表,然后对新的服务提供者列表应用随机算法。
7.2.3 软负载轮询算法实现
轮询算法,将服务调用请求按顺序轮流分配到服务提供者后端服务器上,均衡对待每一台服务提供者机器。软负载轮询算法实现代码如下。
import ares.remoting.framework.cluster.ClusterStrategy;
import ares.remoting.framework.model.ProviderService;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PollingClusterStrategyImpl implements ClusterStrategy {
计数器
private int index = 0;
private Lock lock = new ReentrantLock;
@Override
public ProviderService selectList providerServices {
ProviderService service = null;
try {
lock.tryLock10, TimeUnit.MILLISECONDS;
若计数大于服务提供者个数,将计数器归0
if index = providerServices.size {
index = 0;
}
service = providerServices.getindex;
index;
} catch InterruptedException e {
e.printStackTrace;
} finally {
lock.unlock;
}
兜底,保证程序健壮性,若未取到服务,则直接取第1个
if service == null {
service = providerServices.get0;
}
return service;
}
}
实现原理:依次按顺序获取服务提供者列表中的数据,并使用计数器记录使用过的数据索引,若数据索引到最后一个数据,则计数器归零,重新开始新的循环。
7.2.4 软负载加权轮询算法实现
加权轮询算法是在轮询算法的基础上对权重做了处理。软负载加权轮询算法实现代码如下。
import ares.remoting.framework.cluster.ClusterStrategy;
import ares.remoting.framework.model.ProviderService;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class WeightPollingClusterStrategyImpl implements ClusterStrategy {
计数器
private int index = 0;
private Lock lock = new ReentrantLock;
@Override
public ProviderService selectList providerServices {
ProviderService service = null;
try {
lock.tryLock10, TimeUnit.MILLISECONDS;
存放加权后的服务提供者列表
List providerList = Lists.newArrayList;
for ProviderService provider : providerServices {
int weight = provider.getWeight;
for int i = 0; i providerList.addprovider.copy;
}
}
若计数大于服务提供者个数,将计数器归0
if index = providerList.size {
index = 0;
}
service = providerList.getindex;
index;
return service;
} catch InterruptedException e {
e.printStackTrace;
} finally {
lock.unlock;
}
兜底,保证程序健壮性,若未取到服务,则直接取第1个
return providerServices.get0;
}
}
实现原理:首先根据加权数放大服务提供者列表,再在放大后的服务提供者基础上使用轮询算法获取服务提供者。
7.2.5 软负载源地址hash算法实现
源地址hash算法实际是利于请求来源的IP的hashcode对服务提供者列表大小取模,得到服务提供者列表索引,进而获取到服务提供者。软负载源地址hash算法实现代码如下。
import ares.remoting.framework.Helper.IPHelper;
import ares.remoting.framework.cluster.ClusterStrategy;
import ares.remoting.framework.model.ProviderService;
import java.util.List;
public class HashClusterStrategyImpl implements ClusterStrategy {
@Override
public ProviderService selectList providerServices {
获取调用方IP
String localIP = IPHelper.localIp;
获取源地址对应的hashcode
int hashCode = localIP.hashCode;
获取服务列表大小
int size = providerServices.size;
return providerServices.gethashCode % size;
}
}
实现原理:使用调用方IP地址的hash值,将服务列表大小取模后的值作为服务列表索引,根据该索引取值。