久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

設計一個RPC系統的方法是什么

182次閱讀
沒有評論

共計 6529 個字符,預計需要花費 17 分鐘才能閱讀完成。

這篇文章主要講解了“設計一個 RPC 系統的方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學習“設計一個 RPC 系統的方法是什么”吧!

認識 RPC(遠程調用)

我們在各種操作系統、編程語言生態圈中,多少都會接觸過“遠程調用”的概念。一般來說,他們指的是用簡單的一行代碼,通過網絡調用另外一個計算機上的某段程序。比如:

RMI——Remote Method Invoke:調用遠程的方法。“方法”一般是附屬于某個對象上的,所以通常 RMI 指對在遠程的計算機上的某個對象,進行其方法函數的調用。

RPC——Remote Procedure Call:遠程過程調用。指的是對網絡上另外一個計算機上的,某段特定的函數代碼的調用。

遠程調用本身是網絡通信的一種概念,他的特點是把網絡通信封裝成一個類似函數的調用。網絡通信在遠程調用外,一般還有其他的幾種概念:數據包處理、消息隊列、流過濾、資源拉取等待。下面比較一下他們差異:

方案編程方式信息封裝傳輸模型典型應用遠程調用調用函數,輸入參數,獲得返回值。使用編程語言的變量、類型、函數發出請求,獲得響應 Java RMI 數據包處理調用 Send()/Recv(),使用字節碼數據,編解碼,處理內容把通信內容構造成二進制的協議包發送 / 接收 UDP 編程消息隊列調用 Put()/Get(),使用“包”對象,處理其包含的內容消息被封裝成語言可用的對象或結構對某隊列,存入一個消息;取出一個消息 ActiveMQ 流過濾讀取一個流,或寫出一個流,對流中的單元包即刻處理單元長度很小的統一數據結構連接;發送 / 接收;處理網絡視頻資源拉取輸入一個資源 ID,獲得資源內容請求或響應都包含:頭部 + 正文請求后等待響應 WWW

針對遠程調用的特點——調用函數。業界在各種語言下都開發過類似的方案,同時也有些方案是試圖做到跨語言的。盡管遠程調用在編程方式上,看起來似乎是最簡單易用的,但是也有明顯的缺點。所以了解清楚遠程調用的優勢和缺點,是決定是否要開發、或者使用遠程調用這種模型的關鍵問題。

遠程調用的優勢有:

屏蔽了網絡層。因此在傳輸協議和編碼協議上,我們可以選擇不同的方案。比如 WebService 方案就是用的 HTTP 傳輸協議 +SOAP 編碼協議;而 REST 的方案往往使用 HTTP+JSON 協議。Facebook 的 Thrift 甚至可以定制任何不同的傳輸協議和編碼協議,你可以用 TCP+Google Protocol Buffer,也可以用 UDP+JSON……。由于屏蔽了網絡層,你可以根據實際需要來獨立的優化網絡部分,而無需涉及業務邏輯的處理代碼,這對于需要在各種網絡環境下運行的程序來說,非常有價值。

函數映射協議。你可以直接用編程語言來書寫數據結構和函數定義,取代編寫大量的編碼協議格式和分包處理邏輯。對于那些業務邏輯非常復雜的系統,比如網絡游戲,可以節省大量定義消息格式的時間。而且函數調用模型非常容易學習,不需要學習通信協議和流程,讓經驗較淺的程序員也能很容易的開始使用網絡編程。

遠程調用的缺點:

增加了性能消耗。由于把網絡通信包裝成“函數”,需要大量額外的處理。比如需要預生產代碼,或者使用反射機制。這些都是額外消耗 CPU 和內存的操作。而且為了表達復雜的數據類型,比如變長的類型 string/map/list,這些都要數據包中增加更多的描述性信息,則會占用更多的網絡包長度。

不必要的復雜化。如果你僅僅是為了某些特定的業務需求,比如傳送一個固定的文件,那么你應該用 HTTP/FTP 協議模型。如果為了做監控或者 IM 軟件,用簡單的消息編碼收發會更快速高效。如果是為了做代理服務器,用流式的處理會很簡單。另外,如果你要做數據廣播,那么消息隊列會很容易做到,而遠程調用這幾乎無法完成。

因此,遠程調用最適合的場景是:業務需求多變,網絡環境多變。

RPC 方案的核心問題

由于遠程調用的使用接口是“函數”,所以要如何構建這個“函數”,就產生了三個方面需要決策的問題:

如何表示“遠程”的信息。所謂遠程,就是指網絡上另外一個位置,那么網絡地址就是必須要輸入的部分。在 TCP/IP 網絡下,IP 地址和端口號代表了運行中程序的一個入口。所以指定 IP 地址和端口是發起遠程調用所必需的。然而,一個程序可能會運行很多個功能,可以接收多個不同含義的遠程調用。這樣如何去讓用戶指定這些不同含義的遠程調用入口,就成為了另外一個問題。當然最簡單的是每個端口一種調用,但是一個 IP 最多支持 65535 個端口,而且別的網絡功能也可能需要端口,所以這種方案可能會不夠用,同時一個數字代表一個功能也不太好理解,必須要查表才能明白。所以我們必須想別的方法。在面向對象的思想下,有些方案提出了:以不同的對象來歸納不同的功能組合,先指定對象,再指定方法。這個想法非常符合程序員的理解方式,EJB 就是這種方案的。一旦你確定了用對象這種模型來定義遠程調用的地址,那么你就需要有一種指定遠程對象的方法,為了指定對象,你必須要能把對象的一些信息,從被調用方(服務器端)傳輸給調用方(客戶端)。最簡單的方案就是客戶端輸入一串字符串作為對象的“名字”,發給服務器端,查找注冊了這個“名字”的對象,如果找到了,服務器端就會用某種技術“傳輸”這個對象給客戶端,然后客戶端就可以調用他的方法了。當然這種傳輸不可能是把整個服務器上的對象數據拷貝給客戶端,而是用一些符號或者標志的方法,來代表這個服務器上的對象,然后發給客戶端。如果你不是使用面向對象的模型,那么遠程的一個函數,也是必須要定位和傳輸的,因為你調用的函數必須先能找到,然后成為客戶端側的一個接口,才能調用。針對“遠程對象”(這里說的對象包括面向對象的對象或者僅僅是 函數)如何表達才能在網絡上定位;以及定位成功之后以什么形式供客戶端調用,都是“遠程調用”設計方案中第一個重要的問題。

函數的接口形式應該如何表示。遠程調用由于受到網絡通信的約束,所以往往不能完全的支持編程語言的所有特性。比如 C 語言函數中的指針類型參數,就無法通過網絡傳遞出去。因此遠程調用的函數定義,能用語言中的什么特性,不能用什么特性,是需要在設計方案是規定下來的。這種規定如果太嚴格,會影響使用者的易用性;如果太寬泛,則可能導致遠程調用的性能低下。如何去設計一種方式,把編程語言中的函數,描述成一個遠程調用的函數,也是需要考慮的問題。很多方案采用了配置文件這種通用的方式,而另外一些方案可以直接在源代碼中里面加特殊的注釋。一般來說,編譯型語言如 C /C++ 只能采用源代碼根據配置文件生成的方案,虛擬機型語言如 C#/JAVA 可以采用反射機制結合配置文件(設置是在源代碼中用特殊注釋來代替配置文件)的方案,如果是腳本語言就更簡單,有時候連配置文件都不需要,因為腳本自己就可以充當。總之遠程調用的接口要滿足怎樣的約束,也是一個需要仔細考慮的問題。

用什么方法來實現網絡通信。遠程調用最重要的實現細節,就是關于網絡通信。用何種通信方式來承載遠程調用的問題,細化下來就是兩個子問題:用什么樣的服務程序提供網絡功能?用什么樣的通信協議?遠程調用系統可以自己直接對 TCP/IP 編程來實現通信,也可以委托一些其他軟件,比如 Web 服務器、消息隊列服務器等等……也可以使用不同的網絡通信框架,如 Netty/Mina 這些開源框架。通信協議則一般有兩層:一個是傳輸協議,比如 TCP/UDP 或者高層一點的 HTTP,或者自己定義的傳輸協議;另外一個是編碼協議,就是如何把一個編程語言中的對象,序列化和反序列化成為二進制字節流的方案,流行的方案有 JSON、Google Protocol Buffer 等等,很多開發語言也有自己的序列化方案,如 JAVA/C# 都自帶。以上這些技術細節,應該選擇使用哪些,直接關系到遠程調用系統的性能和環境兼容性。

以上三個問題,就是遠程調用系統必須考慮的核心選型。根據每個方案所面對的約束不同,他們都會在這三個問題上做出取舍,從而適應其約束。但是現在并不存在一個“萬能”或者“通用”的方案,其原因就是:在如此復雜的一個系統中,如果要照顧的特性越多,需要付出的成本(易用性代價、性能開銷)也會越多。下面,我們可以研究下業界現存的各種遠程調用方案,看他們是如何在這三個方面做平衡和選擇的。

業界方案舉例:

CORBA 是一個“古老”的,雄心勃勃的方案,他試圖在完成遠程調用的同時,還完成跨語言的通信的任務,因此其復雜程度是最高的,但是它的設計思想,也被后來更多的其他方案所學習。在通信對象的定位上,它使用 URL 來定義一個遠程對象,這是在互聯網時代非常容易接受的。其對象的內容則限定在 C 語言類型上,并且只能傳遞值,這也是非常容易理解的。為了能讓不同語言的程序通信,所以就必須要在各種編程語言之外獨立設計一種僅僅用于描述遠程接口的語言,這就是所謂的 IDL:Interface Description Language 接口描述語言。用這個方法,你就可以先用一種超然于所有語言之外的語言來定義接口,然后使用工具自動生成各種編程語言的代碼。這種方案對于編譯型語言幾乎是唯一選擇。CORBA 并沒有對通信問題有任何約定,而是留給具體語言的實現者去處理,這也許是他沒有廣泛流行的原因之一。實際上 CORBA 有一個非常著名的繼承者,他就是 Facebook 公司的 Thrift 框架。Thrift 也是使用一種 IDL 編譯生成多種語言的遠程調用方案,并且用 C ++/JAVA 等多種語言完整的實現了通信承載,所以在開源框架中是特別有號召力的一個。Thrfit 的通信承載還有個特點,就是能組合使用各種不同的傳輸協議和編碼協議,比如 TCP/UDP/HTTP 配合 JSON/BIN/PB……這讓它幾乎可以選擇任何的網絡環境。Thrift 的模型類似下圖,這里有的 stub 表示“樁代碼”,就是客戶端直接使用的函數形式程序;skeleton 表示“骨架代碼”,是需要程序員編寫具體提供遠程服務功能的模板代碼,一般對模版做填空或者繼承(擴展)即可。這個 stub-skeleton 模型幾乎是所有遠程調用方案的標配。

JAVA RMI 是 JAVA 虛擬機自帶的一個遠程調用方案。它也是可以使用 URL 來定位遠程對象,使用 JAVA 自帶的序列化編碼協議傳遞參數值。在接口描述上,由于這是一個僅限于 JAVA 環境下的方案,所以直接用 JAVA 語言的 Interface 類型作為定義語言。用戶通過實現這個接口類型來提供遠程服務,同時 JAVA 會根據這個接口文件自動生成客戶端的調用代碼供調用者使用。他的底層通信實現,還是用 TCP 協議實現的。在這里,Interface 文件就是 JAVA 語言的 IDL,同時也是 skeleton 模板,供開發者來填寫遠程服務內容。而 stub 代碼則由于 JAVA 的反射功能,由虛擬機直接包辦了。這個方案由于 JAVA 虛擬機的支持,使用起來非常簡單,完全按照標志的 JAVA 編程方法就可以輕松解決問題,但是這也僅僅能在 JAVA 環境下運行,限制了其適用的范圍。魚與熊掌不可兼得,易用性和適用性往往是互相沖突的。這和 CORBA/Thrift 追求最大范圍的適用性有很大的差別,也導致了兩者在易用性上的不同。

Windows RPC:Windows 中對 RPC 支持是比較早和比較完善的。首先它通過 GUID 來查詢對象,然后使用 C 語言類型作為參數值的傳遞。由于 Windows 的 API 主要是 C 語言的,所以對于 RPC 功能來說,還是要用一種 IDL 來描述接口,最后生成.h 和.c 文件來生產 RPC 的 stub 和 skeleton 代碼。而通信機制,由于是操作系統自帶的,所以使用內核 LPC 機制承載,這一點還是對使用者來說比較方便的。但是也限制了只能用于 Windows 程序之間做調用。

WebService REST:在互聯網時代,程序需要通過互聯網來互相調用。而互聯網上最流行的協議是 HTTP 協議和 WWW 服務,因此使用 HTTP 協議的 Web Service 就順理成章的成為跨系統調用的最流行方案。由于可以使用大多數互聯網的基礎設施,所以 Web Service 的開發和實現幾乎是毫無難度的。一般來說,它都會使用 URL 來定位遠程對象,而參數則通過一系列預定義的類型(主要是 C 語言基礎類型),以及對象序列化方式來傳遞。接口生成方面,你可以自己直接對 HTTP 做解析,也可以使用諸如 WSDL 或者 SOAP 這樣的規范。在 REST 的方案中,則限定了只有 PUT/GET/DELETE/POST 四種操作函數,其他都是參數。

總結一下上面的這些 RPC 方案,我們發現,針對遠程調用的三個核心問題,一般業界有以下幾個選擇:

遠程對象定位:使用 URL;或者使用名字服務來查找。

遠程調用參數傳遞:使用 C 的基本類型定義;或者使用某種預訂的序列化(反序列化)方案

接口定義:使用某種特定格式的技術,直接按預先約定一種接口定義文件;或者使用某種描述協議 IDL 來生成這些接口文件。

通信承載:有使用特定 TCP/UDP 之類的服務器,也有可以讓用戶自己開發定制的通信模型;還有使用 HTTP 或者消息隊列這一類更加高級的傳輸協議。

方案選型

在我們確定了遠程調用系統方案幾個可行選擇后,自然就要明確一下各個方案的優缺點,這樣才能選擇真正合適需求的設計:

對于遠程對象的描述:使用 URL 是互聯網通行的標準,比較方便用戶理解,也容易添加日后需要擴展到內容,因為 URL 本身是一個由多個部分組合的字符串;而名字服務則老式一些,但是依然有他的好處,就是名字服務可以附帶負載均衡、容災擴容、自定義路由等一系列特性,對于需求復雜的定位比較容易實現。

遠程調用的接口描述:如果只限制于某個語言、操作系統、平臺上,直接利用“隱喻”方式的接口描述,或者以“注解”類型注釋手段來標注源代碼,實現遠程調用接口的定義,是最方便不過的。但是,如果需要兼容編譯型語言,如 C /C++,就一定要用某種 IDL 來生成這些編譯語言的源代碼了。

通信承載:給用戶自己定制通信模塊,能提供最好的適用性,但是也讓用戶增加了使用的復雜程度。而 HTTP/ 消息隊列這種承載方式,在系統的部署、運維、編程上都會比較簡單,缺點就是對于性能、傳輸特性的定制空間就比較小。

分析完核心問題,我們還需要考慮一些適用性場景:

面向對象還是面向過程:如果我們只是考慮做面向過程的遠程調用,只需要定位到“函數”即可。而如果是面向對象的,則需要定位到“對象”。由于函數是無狀態的,所以其定位過程可以簡單到一個名字即可,而對象則需要動態的查找到其 ID 或句柄。

跨語言還是單一語言:單一語言的方案中,頭文件或接口定義完全用一種語言處理即可,如果是跨語言的,就少不免要 IDL

混合式通信承載還是使用 HTTP 服務器承載:混合式承載可能可以用到 TCP/UDP/ 共享內存等底層技術,可以提供最優的性能,但是使用起來必然非常麻煩。使用 HTTP 服務器的話,則非常簡單,因為 WWW 服務的開源軟件、庫眾多,而且客戶端使用瀏覽器或者一些 JS 頁面即可調試,缺點是其性能較低。

假設我們現在要為某種業務邏輯非常多變的領域,如企業業務應用領域,或游戲服務器端領域,去設計一個遠程調用系統,我們可能應該如下選擇:

使用名字服務定位遠程對象:由于企業服務是需要高可用性的,使用名字服務能在查詢名字時識別和選擇可用性服務對象。J2EE 方案中的 EJB(企業 JavaBean)就是用名字服務的。

使用 IDL 來生成接口定義:由于企業服務或游戲服務,其開發語言可能不是統一的,又或者需要高性能的編程語言如 C /C++,所以只能使用 IDL。

使用混合式通信承載:雖然企業服務看起來無需在很復雜的網絡下運行,但是不同的企業的網絡環境又可能是千差萬別的,所以要做一個通用的系統,最好還是不怕麻煩提供混合式的通信承載,這樣可以在 TCP/UDP 等各種協議中選擇。

感謝各位的閱讀,以上就是“設計一個 RPC 系統的方法是什么”的內容了,經過本文的學習后,相信大家對設計一個 RPC 系統的方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關知識點的文章,歡迎關注!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-04發表,共計6529字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 彩票| 雷波县| 登封市| 双流县| 镇巴县| 延安市| 华坪县| 定边县| 温州市| 三江| 会宁县| 琼结县| 彰武县| 林芝县| 双城市| 安陆市| 迁安市| 东宁县| 邵东县| 富民县| 莆田市| 唐河县| 敦煌市| 威宁| 长乐市| 顺昌县| 嵊州市| 昆山市| 亳州市| 孙吴县| 穆棱市| 吉木萨尔县| 罗平县| 娄底市| 浠水县| 尉氏县| 启东市| 宜君县| 泉州市| 忻城县| 宝坻区|