分布式服務框架目前已經是互聯網公司實現SOA服務化架構的必備基礎設施,對于一般的開發而言,自己要獨立實現一個分布式服務框架,還是有相當的難度的。本書圍繞如何從零開始實現一個可用的分布式服務框架,介紹了實現分布式服務框架所需技術的方方面面。對于從事開發行業的程序員有很大的現實價值。能夠從中學習到很多的實用技術,了解并掌握實現分布式服務框架所需的思想以及技術。
一個長期戰斗在一線的美團-大眾點評技術專家
詳細講述了分布式服務框架的底層實現細節
清楚梳理了分布式服務框架周邊的知識點
從零開始構建了一個分布式服務框架
實戰操練的代碼透漏出作者身經百戰的深厚功力
技術原理和內部實現分析提升技術理解和洞察力
目前企業真正使用微服務非常少,而使用分布式服務框架比較多,實現相對簡單,作者所在公司美團在分布式服務框架實現方面具有豐富的經驗。
《架構探險:從零開始寫分布式服務框架》能順利地帶領你走出架構險境,讓你對分布式服務框架所涉及的技術了然于胸,并能合理地利用這些技術,搭建符合自身需求的分布式服務框架。
李業兵
先后在支付寶運營支撐事業部、去哪兒網酒店事業部任職高級開發工程師。于2015年加入貓眼電影(原美團網旗下電影事業部),負責交易業務線架構與開發工作。
擅長電商交易領域系統設計與架構,在電商交易領域系統架構設計方面積累了較為豐富的實踐經驗。
對高并發系統設計、服務化架構、互聯網中間件開發保持著濃厚的興趣。
第1章 常用的RPC框架 1
1.1 RPC框架原理 1
1.2 RMI介紹 2
1.2.1 原生RMI代碼示例 3
1.2.2 RMI穿透防火墻 5
1.3 CXF/Axis2介紹 7
1.3.1 CXF介紹 7
1.3.2 Axis2介紹 14
1.4 Thrift介紹 21
1.4.1 Thrift工作原理介紹 23
1.4.2 Thrift IDL語法說明 26
1.4.3 基于Apache Thrift的Java版完整案例 28
1.4.4 基于Java注解的簡化實現 36
1.5 gRPC介紹 42
1.5.1 protobuf3語法介紹 43
1.5.2 gRPC使用示例 45
1.6 HTTP Client介紹 53
1.6.1 構建HttpClient對象 54
1.6.2 構建URI對象 55
1.6.3 構建請求對象(HttpGet、HttpPost) 56
1.6.4 HttpClient發起調用及獲取調用返回結果 56
1.7 實現自己的RPC框架 61
1.8 RPC框架與分布式服務框架的區別 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.2 Java默認的序列化 77
3.3 XML序列化框架介紹 80
3.4 JSON序列化框架介紹 82
3.5 Hessian序列化框架介紹 87
3.6 protobuf序列化框架介紹 88
3.7 protostuff序列化框架介紹 93
3.8 Thrift序列化框架介紹 98
3.9 Avro序列化框架介紹 100
3.9.1 Avro介紹 100
3.9.2 Avro IDL語言介紹 101
3.9.3 Schema定義介紹 103
3.9.4 Maven配置及使用IDL與Schema自動生成代碼 103
3.9.5 Avro序列化/反序列化實現 105
3.10 JBoss Marshalling序列化框架介紹 110
3.11 序列化框架的選型 112
3.12 實現自己的序列化工具引擎 113
3.13 本章小結 118
第4章 實現分布式服務框架服務的與引入 119
4.1 Spring Framework框架概述 119
4.1.1 Spring Framework介紹 119
4.1.2 Spring Framework周邊生態項目介紹 121
4.2 FactoryBean的秘密 122
4.2.1 FactoryBean的作用及使用場景 123
4.2.2 FactoryBean實現原理及示例說明 124
4.3 Spring框架對于已有RPC框架集成的支持 127
4.3.1 Spring支持集成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.2 ZooKeeper實現服務的注冊中心原理 161
5.2.1 ZooKeeper介紹 161
5.2.2 部署ZooKeeper 161
5.2.3 ZkClient使用介紹 164
5.2.4 ZooKeeper實現服務注冊中心 173
5.3 集成ZooKeeper實現自己的服務注冊與發現 175
5.3.1 服務注冊中心服務提供方 175
5.3.2 服務注冊中心服務消費方 176
5.3.3 服務注冊中心實現 178
5.4 本章小結 189
第6章 分布式服務框架底層通信實現 190
6.1 Java I/O模型及I/O類庫的進化 190
6.1.1 Linux下實現的I/O模型 190
6.1.2 Java語言實現的I/O模型 194
6.1.3 Java Classic I/O(Blocking I/O)介紹 194
6.1.4 Java Non-blocking I/O(NIO)介紹 211
6.1.5 NIO2及Asynchronous I/O介紹 233
6.2 Netty使用介紹 255
6.2.1 Netty開發入門 256
6.2.2 Netty粘包/半包問題解決 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
7.2 負載均衡常用算法
負載均衡常用算法主要有隨機、加權隨機、輪詢、加權輪詢、源地址hash等。
7.2.1 軟負載隨機算法實現
隨機算法原理為:獲取服務列表大小范圍內的隨機數,將該隨機數作為列表索引,從服務提供列表中獲取服務提供者。
為負載均衡策略算法定義接口如下:
public interface ClusterStrategy {
public ProviderService select(List 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 select(List providerServices) {
int MAX_LEN = providerServices.size();
int index = RandomUtils.nextInt(0, MAX_LEN - 1);
return providerServices.get(index);
}
}
實現原理:獲得服務提供者列表大小區間之間的隨機數,作為服務提供者列表的索引來獲取服務。
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 select(List providerServices) {
//存放加權后的服務提供者列表
List providerList = Lists.newArrayList();
for (ProviderService provider : providerServices) {
int weight = provider.getWeight();
for (int i = 0; i < weight; i ) {
providerList.add(provider.copy());
}
}
int MAX_LEN = providerList.size();
int index = RandomUtils.nextInt(0, MAX_LEN - 1);
return providerList.get(index);
}
}
實現原理:首先根據加權數放大服務提供者列表,比如服務提供者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 select(List providerServices) {
ProviderService service = null;
try {
lock.tryLock(10, TimeUnit.MILLISECONDS);
//若計數大于服務提供者個數,將計數器歸0
if (index >= providerServices.size()) {
index = 0;
}
service = providerServices.get(index);
index ;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
//兜底,保障程序健壯性,若未取到服務,則直接取第1個
if (service == null) {
service = providerServices.get(0);
}
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 select(List providerServices) {
ProviderService service = null;
try {
lock.tryLock(10, TimeUnit.MILLISECONDS);
//存放加權后的服務提供者列表
List providerList = Lists.newArrayList();
for (ProviderService provider : providerServices) {
int weight = provider.getWeight();
for (int i = 0; i < weight; i ) {
providerList.add(provider.copy());
}
}
//若計數大于服務提供者個數,將計數器歸0
if (index >= providerList.size()) {
index = 0;
}
service = providerList.get(index);
index ;
return service;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
//兜底,保障程序健壯性,若未取到服務,則直接取第1個
return providerServices.get(0);
}
}
實現原理:首先根據加權數放大服務提供者列表,再在放大后的服務提供者基礎上使用輪詢算法獲取服務提供者。
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 select(List providerServices) {
//獲取調用方IP
String localIP = IPHelper.localIp();
//獲取源地址對應的hashcode
int hashCode = localIP.hashCode();
//獲取服務列表大小
int size = providerServices.size();
return providerServices.get(hashCode % size);
}
}
實現原理:使用調用方IP地址的hash值,將服務列表大小取模后的值作為服務列表索引,根據該索引取值。
隨著微服務的流行,支撐微服務的分布式服務框架成為大家優先發展的重點。服務化的基本原理掌握起來相對比較容易,但是要從零構建一個分布式服務框架卻比較困難,涉及通信、線程并發、服務調度等。本書詳細講解了構建服務框架所需的各種技術及框架選型,手把手教初學者搭建一套完整的分布式服務框架,如果你想掌握分布式服務框架底層的技術細節,自己開發一套適合本公司和領域的服務框架,本書是一個非常不錯的選擇!
——華為架構師,《分布式服務框架原理與實踐》《Netty指南》作者 李林鋒
簡潔明了的文字把技術介紹得深入淺出,實戰操練的代碼透漏出作者身經百戰的深厚功力,通過本書不僅可以快速地了解和上手分布式服務框架開發技術,還能通過技術原理和內部實現的分析介紹,提升我們對技術的理解和洞察力。
——貓眼電影技術負責人 陳清陽
基于服務調用相關知識,業界已產出了不少技術書籍。本書汲取各家之精華,不同技術層級的人通過不同的章節都能獲得極大的收獲。更為難能可貴的是,作者是一個長期戰斗在工程一線,一步一步成長起來的美團-大眾點評技術專家,設計過大量的工程框架并主導開發實現,經受住了多種復雜業務形態的考驗。憑借著作者本人多年的積累,凝聚出了書中豐富的示例和經驗總結。通過這些示例和經驗總結,內容逐漸深入,多方位揭示了服務間通信的各項技術關鍵點,能有效地幫助讀者從新手成長為專家。
——美團點評高級技術專家(原美團點評技術委員會委員) 黃波
本書比較地介紹了分布式系統開發的各方面知識,循序漸進,實例代碼比較多,非常適合初入分布式開發并且有Java開發經驗的人員參考學習。
——香格里拉酒店集團副總裁(原去哪兒網高級系統架構師) 孫立
其實我們都在架構中探險,或許自己目前正身陷險境,我們希望得到一本“寶典”,教會自己如何找到架構的成功捷徑。李業兵老師寫的這本《架構探險:從零開始寫分布式服務框架》就能順利地帶領我們走出險境,讓我們對分布式服務框架所涉及的技術了然于胸,并能合理地利用這些技術,搭建符合自身需求的分布式服務框架。
——特贊科技 CTO 黃勇
程序員就是要不停地學習學習,開卷有益,推薦購買!
感覺還不錯…
入門還是挺不錯的
非常完美,加油