您好,登錄后才能下訂單哦!
這篇文章主要介紹了RPC設計的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
RPC全程遠程方法調用,已經在各大小公司被廣泛使用,種類也是很多比如:Dubbo,Spring cloud那一套,GRPC,Thrift,可能還有很多公司自研的等等;每個公司都可能根據自己的業務需求,場景選擇自己合適的RPC框架;但大體的考察維度無非就這么幾個:性能,可擴展性,跨平臺,功能性,可監控,使用性;所以我們如果要設計一個RPC框架,可以從這幾個角度去考慮。
作為微服務中的核心組件,在一個系統中RPC的調用量往往是很高的,所以性能是一個很重要的考慮點;既然是遠程調用,必然牽扯到網絡連接,而I/O模型的選擇直接影響到性能,網絡的長連接短連接,序列化方式也都影響性能;
常見的Unix5種I/O模型分別是:阻塞I/O,非阻塞I/O,I/O復用(select,poll,epoll等支持I/O多路復用),信號驅動I/O,異步I/O;從早期的阻塞I/O方式只能創建大量的線程來保證每個用戶互不影響,到現在廣泛使用的I/O多路復用模型,再到異步I/O;從select模型到現在主流的epoll模型,性能有了質的升級;當然我們沒必要自己去實現,可以直接使用網絡通訊框架Netty,Mina等;
短連接表示每次通訊完就關閉連接,而長連接通訊完繼續保持連接,這樣下次再通訊就不需要重新建立連接了,如果通訊頻繁,很明顯長連接性能更高;但是長連接需要做一些額外的工作,比如保活處理;另外就是如果客戶端太多的話,服務器端是無法支撐的。
網絡傳輸中的數據都需要經過序列化和反序列化處理,所以這一塊的性能也很重要;常見的序列化包括:json和二進制方式,json常見的如fastjson,jackson等,二進制如protobuf,thrift ,kryo等;這個可以分別從序列化的性能,大小,以及使用方便性考慮;當然穩定性和安全性也需要考慮,比如fastjson頻繁爆出安全漏洞;
這里主要講的是應用層協議,RPC一般都會自定義協議,當然也有直接使用現有協議的比如http協議;自定義協議可以自己掌控,協議可以做的很小很精簡,當然解碼和編碼需要自己去實現;如果使用現有的http協議,相對來說整個協議包是比較大的,但是已經是一種規范了,很多東西可以直接拿來用,更加通用;
可擴展性可以從兩個角度來看,一個是服務提供方和消費方的負載均衡策略;另一個就是用戶可以對框架進行自定義擴展;
RPC的兩個核心組件服務提供方和消費方,需要提供橫向擴展的機制,用以達到更高的負責,比如Spring Cloud、Dubbo提供的注冊中心,然后再結合容錯機制達到負載均衡的效果,很容易達到橫向擴展;
一個好的框架是支持用戶自定義的,用戶根據自己的需求實現自定義擴展;JDK提供了SPI機制,很常見的一個場景就是數據庫驅動;另外Dubbo在此基礎上提供了更加強大的SPI機制;這種擴展對RPC來說是多方面的,可以是底層的通訊框架擴展,序列化擴展,注冊中心擴展,容錯機制擴展,協議擴展等等;
現在開發語言多種多樣,如果能做成跨平臺,當然是一大優勢,但是可能往往為了跨平臺,會在一些地方做權衡讓步,當然難度也更大;所以我們在實現一個RPC時需要明確自己的定位,就是針對某一種語言的還是跨平臺支持;常見的支持跨平臺的RPC框架如GRPC,Thrift;
實現機制可以參考一下,都有自己的一套接口定義語言IDL然后通過不同的代碼生成器,生成各種編程語言消費端和服務器端代碼,來保證不同語言直接的相關通信。
作為一個RPC框架,除了最核心的通信模塊,序列化模塊之外,功能性模塊也很重要,往往為開發者節省了大量的時間,開發者可能因為RPC的某個功能而選擇用此框架;常見的功能包括:容錯機制,負載均衡機制,同步異步調用,結果緩存,路由規則,服務降級,多版本,線程模型等;
在錯綜復雜的網絡環境中,遠程調用失敗再正常不過了,容錯機制就顯得非常有必要了,常見的容錯機制比如:失敗重試,快速失敗,失敗直接忽略,并行調用多個服務器只要一個成功即返回等;用戶可以根據需求選擇自己合適的容錯方案;
上面提到服務提供方和消費方的可擴展性,消費方面對多個提供方的時候需要有一定的負載均衡策略,來保證系統的穩定性;常見的策略如:隨機,輪詢,最少活躍調用數,一致性hash等;
常見的同步調用有些場景無法滿足需求,比如同時需要調用多個遠程方法,而這其中可能有些執行比較慢的;這時候異步調用就顯得重要了,可以同時異步發送多個請求,等待時間就是響應最慢的請求;具體可以通過Future,CompletableFuture來實現;
緩存一直是性能的不二法寶,某些場景下可能對服務提供方響應的數據實時要求性并不高,這時候如果可以在服務提供端提供結果的緩存機制,那么在性能上是一個很大的提升;可以自己設計一個本地緩存,當然也可以直接整合第三方緩存框架比如ehcache,jcache等;
服務提供方往往是很多的,用戶可能有一些特殊的需求,可以按照自己定義個規則來做路由,比如我們經常做的灰度發布,結合RPC提供的路由規則來實現會很簡單;此規則可能是條件表達式,腳本,標簽等,我們設計的RPC框架需要有一個給用戶定義規則的地方,比如通過注冊中心來實時推送,另外還需要相關的引擎來處理規則,比如腳本引擎;
系統的高可用性原則中,很重要的一條就是降級處理,在一些非核心的功能中,可以在出現超時/故障時或者直接設置為降級服務,給一個統一的響應,這樣可以把寶貴的資源留給那些核心的功能;可以參考Dubbo的實現,向注冊中心寫入動態配置覆蓋規則,從而實現實時降級處理;
接口升級時常有的事情,我們可能會為了兼容之前的版本絞盡腦汁,但有時候還是無能為力,這時候多版本就顯得很重要了,可以讓兩個版本同時存在,等到合適的機會在慢慢升級;像dubbo這種服務的維度就是服務名+版本號,所以很好實現多版本;而Spring Cloud維度沒有到版本號,可以通過路由規則去實現;
在系統的高可用原則中,線程隔離是一條重要的原則,為什么要做隔離,可以拿Dubbo及其底層通信框架netty為例,netty作為通信框架本身是有自己的線程模型,如果業務處理線程直接使用底層的通信線程模型,這樣就會出現因為業務阻塞而導致通信線程模型阻塞;這時Dubbo提供自己的線程模型就尤為重要,可以做到線程隔離,業務線程不影響通信線程;
當然作為一個RPC框架實現的功能可以很多,這里主要講一些我們平常用的比較多的功能;
一個運行穩定的系統,沒有一個專門的監控平臺是不行的,當然RPC也不例外,常見的比如dubbo的monitor模塊,Spring Cloud Admin等;對于一個RPC我們主要監控:服務提供者有哪些,服務消費者有哪些,以及它們的狀態,最好還有一些統計功能比如一段時間內的調用量,成功率,失敗率,平均響應時間,最大響應時間,最大并發量等等;
最后說一下,我們設計出來的框架最終還是要給用戶使用的,所以用戶是否可以方便的使用也是一個很重要的點,某些框架可能就是因為使用繁瑣導致最終被棄用;比如注解的方式相比較xml的方式就簡單不少;還有比如服務維度來說:dubbo維度是接口,而Spring cloud維度是應用,整體來看Spring cloud使用起來更加方便;當然簡單的API,文檔以及Demo對開發者來說也是必不可少的;
感謝你能夠認真閱讀完這篇文章,希望小編分享的“RPC設計的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。