- Service Mesh實戰(zhàn):用Istio軟負載實現(xiàn)服務網(wǎng)格
- 周遙
- 282字
- 2019-07-29 18:22:34
1.3 服務化時期
1.3.1 應用到服務
重復建設(shè)在軟件工程思想中向來就是不可取的,工程師們設(shè)想將共同的功能組件抽象出來,形成獨立的“應用”,不過這里的關(guān)鍵問題就是這些“應用”沒有直觀上的入口,因此用傳統(tǒng)的思想來定義并不妥。為此工程師們想出了“服務(Service)”一詞來描述這種功能性的組件,它們?yōu)閼锰峁┩ㄓ霉δ苄缘闹危胺铡庇诰唧w應用。
如今“服務”這個詞在軟件工程中已經(jīng)泛化,可以說,凡是向其他組件提供“支撐”功能的系統(tǒng)都可以稱為服務,甚至還出現(xiàn)“軟件即服務”(SaaS)這樣的概念。在這種概念下,軟件不再是整體打包一次性賣給消費者,而是消費者在使用時按需獲取,而且服務還會不定期升級,消費者無須感知,并可以按使用時長或者資源的消耗率來計算費用。
“服務”思想其實就是把其他應用當成了消費者,為其提供特定功能。上述應用架構(gòu)中的“登錄、采集用戶基本信息”等功能可以抽象成一個名為“用戶中心”的服務組件。以此類推,還可以繼續(xù)抽象出“消息中心”“索引搜索”“文件存儲”“緩存系統(tǒng)”等通用服務組件,總的原則就是盡量提取公共的部分以避免重復的開發(fā)工作。
之后,功能的開發(fā)也即服務的開發(fā)了。
1.3.2 遠程調(diào)用
服務拆分后,就像天上的繁星一樣分散到不同網(wǎng)絡(luò)的各角落了,那么現(xiàn)在的問題是如何互相訪問呢?前面說過了,服務與應用不同,沒有可視化的頁面可以訪問,而且調(diào)用者是計算機程序而不是人類用戶,工程師們需要一個程序之間的通信協(xié)議,就好像下面的對話一樣明了方便。
“我需要用戶A的記錄,請給我它的結(jié)構(gòu)及數(shù)據(jù)”
“好,這是A的記錄的結(jié)果及數(shù)據(jù),請拿好”
“遠程過程調(diào)用(Remote Procedure Call,簡稱RPC)”協(xié)議應運而生,其作用就是讓應用(服務)之間的程序調(diào)用變得像本地一樣簡單,這種技術(shù)完全屏蔽了各種網(wǎng)絡(luò)拓撲的復雜性,只要知道對方的“地址”就可以發(fā)起調(diào)用。
RPC在Java生態(tài)中,最早出現(xiàn)在1.1版本中的RMI(Remote Method Invocation)中。Oracle后來又提出的EJB那一套,基于JAX-RPC接口——JAX-RPC基于SOAP(簡單對象訪問協(xié)議),調(diào)用地址都是由“類目服務器(Name Server)”來注冊管理的。
在這種方案下,訪問某個遠程服務需通過以下類似代碼:
1: public class HelloClient { 2: public static void main(String args[]){ 3: try { 4: //在RMI服務注冊表中查找名稱為RHello的對象,并調(diào)用其上的方法 5: IHello rhello =(IHello)Naming.lookup(〝rmi://localhost:8888/RHello〝); 6: System.out.println(rhello.helloWorld()); 7: System.out.println(rhello.sayHelloToSomeBody(〝熔巖〝)); 8: } catch(NotBoundException e){ 9: e.printStackTrace(); 10: } catch(MalformedURLException e){ 11: e.printStackTrace(); 12: } catch(RemoteException e){ 13: e.printStackTrace(); 14: } 15: } 16: }
可以看到上述代碼中有一個URI,這就是該服務的地址,消費端通過它可以發(fā)起訪問以獲得數(shù)據(jù)。
1.3.3 虛擬IP地址
可不要認為RPC就只是調(diào)用。這里有個前提,就是服務端得把自己的地址注冊上去,但是在集群環(huán)境下有多臺機器,如何處理呢?這些地址URI又怎么告訴消費方呢?另外,當服務不可用時,誰又去把這些注冊信息拿掉呢?
這里工程師們想到的解決方案就是前面提到的負載均衡設(shè)備概念中的“虛擬IP地址(簡稱VIP)”,只需要在注冊的時候填寫VIP,那么在調(diào)用的時候,請求經(jīng)過負載均衡設(shè)備,其就會自動地將流量均分到下屬已經(jīng)注冊的機器中,并且在應用上下線的時候,會自動對下發(fā)的機器列表進行調(diào)整。
在增加了RPC功能后,工程師們終于可以將公共的服務單獨部署,現(xiàn)在整個架構(gòu)如圖1.5所示。

圖1.5 “服務化后的部署架構(gòu)”
1.3.4 復雜的調(diào)用關(guān)系
歷史的車輪繼續(xù)向前,業(yè)務量再一次發(fā)生了巨大的增長,請求不斷涌進來,新的應用不斷增加,這使得公共服務也變得越來越多,整個調(diào)用網(wǎng)由最開始的十幾條線變成成百上千條甚至上萬條,甚至到了后期,已經(jīng)沒人能弄清楚到底有多少條調(diào)用關(guān)系了。
圖1.6就是某企業(yè)的全局調(diào)用關(guān)系,可以看到,這里面的調(diào)用鏈錯綜復雜。

圖1.6 “某公司的服務調(diào)用關(guān)系”
1.3.5 服務治理
復雜的服務訂閱關(guān)系必須要很好地維護起來,否則在出現(xiàn)問題的時候可能完全不知從何入手,所以這個時候,一種叫“服務治理(Service Governance)”的軟負載產(chǎn)品出現(xiàn)了。它的基礎(chǔ)工作跟注冊中心一樣是維護一個訂閱關(guān)系,不過在訂閱關(guān)系的數(shù)據(jù)之上,還提供了更多高級功能,比如:根據(jù)負載情況選擇最優(yōu)服務節(jié)點、多版本鏈路支持、訂閱關(guān)系鑒權(quán)限流降級以及灰度發(fā)布等。
經(jīng)典的RPC框架Dubbo就有一個專門的服務治理子系統(tǒng),其底層采用ZooKeeper作為數(shù)據(jù)存儲,如今經(jīng)常提到的Spring Cloud則是采用名為Eureka的自研產(chǎn)品。
Dubbo的“服務治理”采用的是ZooKeeper,由于其自身數(shù)據(jù)結(jié)構(gòu)的設(shè)計,其服務關(guān)系存儲采用的是樹狀結(jié)構(gòu),如圖1.7所示:

圖1.7 “Dubbo在ZooKeeper中的數(shù)據(jù)存儲結(jié)構(gòu)”
這種存儲結(jié)構(gòu)的優(yōu)點在于可以很容易地監(jiān)聽數(shù)據(jù)變化,例如需要監(jiān)聽“服務A”對應的“提供者”變化情況時,只需要將監(jiān)聽點掛載到服務A的“提供者”父節(jié)點即可。同理,如果需要同時監(jiān)聽“提供者”與“消費者”,只需要將監(jiān)聽掛載到“服務”節(jié)點即可。然而不足也是很明顯的,例如需要進行關(guān)聯(lián)查詢時,樹狀的層次結(jié)構(gòu)就不那么方便了。比如需要查詢機器M1訂閱的所有服務,這種情況下只能逐一遍歷,其時間復雜度為O(n),其中n為服務數(shù)量,并不高效,再加上ZooKeeper強一致的設(shè)計,從性能與功能上來講,我個人認為都不適合作為“服務發(fā)現(xiàn)”來使用。
現(xiàn)今,工程師們普遍傾向使用etcd來實現(xiàn)“注冊中心”,其特點是采用KV存儲,對于結(jié)構(gòu)性查詢,更加輕量、易運維,優(yōu)勢更佳。
訂閱關(guān)系可不僅在RPC中,任何鏈路,只要存在服務一說,都會涉及這個概念,比如著名的開源消息框架RocketMQ,也會使用一個目錄服務器(官方名稱是nameserver)來維護Topic與Broker之間的映射關(guān)系。
服務治理維護的數(shù)據(jù),從根本上說就是“提供者”與“消費者”之前的映射關(guān)系,例如有3臺機器在提供服務A,則標記為Aprovider= {M1, M2, M3},同時有2個消費者在調(diào)用A的服務,則記為Asubscriber= {N1, N2},可以看見這兩條數(shù)據(jù)均為矢量數(shù)據(jù),因此如何較好地結(jié)構(gòu)化存儲,是鏈路關(guān)系維護的關(guān)鍵。
當然可以嘗試將其存儲在數(shù)據(jù)庫中,但這里的問題是,訂閱關(guān)系通常是實時變化的,而且需要通知功能。比如提供A服務的M1這臺機器宕機,消費者Asubscriber需要監(jiān)聽到這種變化,否則會將請求路由到一個已經(jīng)宕機或者下線的服務上,導致錯誤的請求。更復雜的情況是,可能一個關(guān)系變化會連鎖式地影響到其他鏈路。
例如B服務其實就是A服務的一個消費者N3,而B服務本身又有消費者,那么當M1出現(xiàn)故障時,Aprovider變成{M2, M3},這時B的流量入口從之前的三臺下降到了兩臺,B服務的鏈路能力是有下降的,即整條鏈路的吞吐量都受到了影響。如何及時、直觀地反映問題,到如今也是個棘手的問題,這點更是彈性調(diào)度不可或缺的基礎(chǔ)。
可以說軟負載中的“服務治理”發(fā)展到今天已經(jīng)遠不只“服務注冊”那么簡單了。
1.3.6 旁路負載
由于“服務治理”系統(tǒng)的存在,工程師們再也不用為應用之間復雜的調(diào)用關(guān)系而擔驚受怕了,分布式得以空前發(fā)展。
因為“服務治理”通常都提供健康檢測功能,已經(jīng)能夠很好地維護服務對應的機器列表,所以之前講到的VIP(虛擬IP地址)便變得不那么必需了。這個時候工程師們想出了一種“旁路負載”(亦稱透明負載)的軟負載架構(gòu),它的特點是并不直接通過代理流量來分發(fā)負載流量,而是在RPC客戶端中直接埋入負載及其他鏈路邏輯,這樣就省下了網(wǎng)關(guān)代理這層,但是由于對外需要統(tǒng)一暴露接口,因此對外的網(wǎng)關(guān)仍然需要保留。
當然,對外的網(wǎng)關(guān)已經(jīng)不是簡單的流量負載均衡,像“接口版本管理、攻擊防御、請求重定向”等功能也被加入了,這個時候它有了一個更貼切的名字,叫“API網(wǎng)關(guān)”。像讀者熟知的Spring Cloud框架,其Zuul組件充當?shù)谋闶恰癆PI網(wǎng)關(guān)”的角色。
最終系統(tǒng)架構(gòu)便變成了圖1.8的樣子:

圖1.8 “采取旁路負載后的架構(gòu)”
如此一來,系統(tǒng)內(nèi)部的訪問阻礙已經(jīng)減少到很少了,同時隨著Docker容器化及DevOps思想的迅速崛起,服務的粒度可以拆分得比以前更細,讓需求開發(fā)更加獨立、互不影響,這就是之后出現(xiàn)的微服務一說。
- 中文版SketchUp 2022完全實戰(zhàn)技術(shù)手冊
- Photoshop CC 網(wǎng)店視覺設(shè)計
- 爸媽微信e時代
- IBM Lotus Notes 8.5 User Guide
- After Effects CC影視后期制作實戰(zhàn)從入門到精通
- 突破平面Premiere Pro 2022短視頻與視頻制作
- Moldflow 2010完全自學與速查手冊(模流分析·成本控制)
- Photoshop CS6中文版基礎(chǔ)培訓教程
- 3ds Max 2014從入門到精通
- ADOBE FLASH PROFESSIONAL CS6 標準培訓教材
- Instant MuseScore
- Tomcat 6 Developer's Guide
- Spark Cookbook 中文版
- Photoshop+CorelDRAW平面設(shè)計案例實戰(zhàn):從入門到精通(視頻自學全彩版)
- Joomla! E/Commerce with VirtueMart