1. 程式人生 > >遠端過程呼叫(RPC)詳解

遠端過程呼叫(RPC)詳解

本文介紹了什麼是遠端過程呼叫(RPC),RPC 有哪些常用的方法,RPC 經歷了哪些發展階段,以及比較了各種 RPC 技術的優劣。

什麼是 RPC

RPC 是遠端過程呼叫(Remote Procedure Call)的縮寫形式,Birrell 和 Nelson 在 1984 發表於 ACM Transactions on Computer Systems 的論文《Implementing remote procedure calls》對 RPC 做了經典的詮釋。RPC 是指計算機 A 上的程序,呼叫另外一臺計算機 B 上的程序,其中 A 上的呼叫程序被掛起,而 B 上的被呼叫程序開始執行,當值返回給 A 時,A 程序繼續執行。呼叫方可以通過使用引數將資訊傳送給被呼叫方,而後可以通過傳回的結果得到資訊。而這一過程,對於開發人員來說是透明的。

圖1 描述了資料報在一個簡單的RPC傳遞的過程

圖1 描述了資料報在一個簡單的RPC傳遞的過程

遠端過程呼叫採用客戶機/伺服器(C/S)模式。請求程式就是一個客戶機,而服務提供程式就是一臺伺服器。和常規或本地過程呼叫一樣,遠端過程呼叫是同步操作,在遠端過程結果返回之前,需要暫時中止請求程式。使用相同地址空間的低權程序或低權執行緒允許同時執行多個遠端過程呼叫。

RPC 的基本操作

讓我們看看本地過程呼叫是如何實現的。考慮下面的 C 語言的呼叫:

count = read(fd, buf, nbytes);

其中,fd 為一個整型數,表示一個檔案。buf 為一個字元陣列,用於儲存讀入的資料。 nbytes 為另一個整型數,用於記錄實際讀入的位元組數。如果該呼叫位於主程式中,那麼在呼叫之前堆疊的狀態如圖2(a)所示。為了進行呼叫,呼叫方首先把引數反序壓入堆疊,即為最後一個引數先壓入,如圖2(b)所示。在 read 操作執行完畢後,它將返回值放在某個暫存器中,移出返回地址,並將控制權交回給呼叫方。呼叫方隨後將引數從堆疊中移出,使堆疊還原到最初的狀態。

圖2 過程呼叫中的引數傳遞

圖2 過程呼叫中的引數傳遞

RPC 背後的思想是儘量使遠端過程呼叫具有與本地呼叫相同的形式。假設程式需要從某個檔案讀取資料,程式設計師在程式碼中執行 read 呼叫來取得資料。在傳統的系統中, read 例程由連結器從庫中提取出來,然後連結器再將它插入目標程式中。 read 過程是一個短過程,一般通過執行一個等效的 read 系統呼叫來實現。即,read 過程是一個位於使用者程式碼與本地作業系統之間的介面。

雖然 read 中執行了系統呼叫,但它本身依然是通過將引數壓入堆疊的常規方式呼叫的。如圖2(b)所示,程式設計師並不知道 read 幹了啥。

RPC 是通過類似的途徑來獲得透明性。當 read 實際上是一個遠端過程時(比如在檔案伺服器所在的機器上執行的過程),庫中就放入 read 的另外一個版本,稱為客戶存根(client stub)。這種版本的 read 過程同樣遵循圖2(b)的呼叫次序,這點與原來的 read 過程相同。另一個相同點是其中也執行了本地作業系統呼叫。唯一不同點是它不要求作業系統提供資料,而是將引數打包成訊息,而後請求此訊息傳送到伺服器,如圖3所示。在對 send 的呼叫後,客戶存根呼叫 receive 過程,隨即阻塞自己,直到收到響應訊息。

圖3 客戶與伺服器之間的RPC原理

圖3 客戶與伺服器之間的RPC原理

當訊息到達伺服器時,伺服器上的作業系統將它傳遞給伺服器存根(server stub)。伺服器存根是客戶存根在伺服器端的等價物,也是一段程式碼,用來將通過網路輸入的請求轉換為本地過程呼叫。伺服器存根一般先呼叫 receive ,然後被阻塞,等待訊息輸入。收到訊息後,伺服器將引數由訊息中提取出來,然後以常規方式呼叫伺服器上的相應過程(如圖3所示)。從伺服器角度看,過程好像是由客戶直接呼叫的一樣:引數和返回地址都位於堆疊中,一切都很正常。伺服器執行所要求的操作,隨後將得到的結果以常規的方式返回給呼叫方。以 read 為例,伺服器將用資料填充 read 中第二個引數指向的緩衝區,該快取區是屬於伺服器存根內部的。

呼叫完後,伺服器存根要將控制權教會給客戶發出呼叫的過程,它將結果(緩衝區)打包成訊息,隨後呼叫 send 將結果返回給客戶。事後,伺服器存根一般會再次呼叫 receive,等待下一個輸入的請求。

客戶機器接收到訊息後,客戶作業系統發現該訊息屬於某個客戶程序(實際上該程序是客戶存根,知識作業系統無法區分二者)。作業系統將訊息複製到相應的快取區中,隨後解除對客戶程序的阻塞。客戶存根檢查該訊息,將結果提取出來並複製給呼叫者,而後以通常的方式返回。當呼叫者在 read 呼叫進行完畢後重新獲得控制權時,它所知道的唯一事就是已經得到了所需的資料。它不指導操作是在本地作業系統進行,還是遠端完成。

整個方法,客戶方可以簡單地忽略不關心的內容。客戶所涉及的操作只是執行普通的(本地)過程呼叫來訪問遠端服務,它並不需要直接呼叫 send 和 receive 。訊息傳遞的所有細節都隱藏在雙方的庫過程中,就像傳統庫隱藏了執行實際系統呼叫的細節一樣。

概況來說,遠端過程呼叫包含如下步驟:

  1. 客戶過程以正常的方式呼叫客戶存根;
  2. 客戶存根生成一個訊息,然後呼叫本地作業系統;
  3. 客戶端作業系統將訊息傳送給遠端作業系統;
  4. 遠端作業系統將訊息交給伺服器存根;
  5. 伺服器存根調將引數提取出來,而後呼叫伺服器;
  6. 伺服器執行要求的操作,操作完成後將結果返回給伺服器存根;
  7. 伺服器存根將結果打包成一個訊息,而後呼叫本地作業系統;
  8. 伺服器作業系統將含有結果的訊息傳送給客戶端作業系統;
  9. 客戶端作業系統將訊息交給客戶存根;
  10. 客戶存根將結果從訊息中提取出來,返回給呼叫它的客戶存根。

以上步驟就是將客戶過程對客戶存根發出的本地呼叫轉換成對伺服器過程的本地呼叫,而客戶端和伺服器都不會意識到中間步驟的存在。

RPC 的主要好處是雙重的。首先,程式設計師可以使用過程呼叫語義來呼叫遠端函式並獲取響應。其次,簡化了編寫分散式應用程式的難度,因為 RPC 隱藏了所有的網路程式碼存根函式。應用程式不必擔心一些細節,比如 socket、埠號以及資料的轉換和解析。在 OSI 參考模型,RPC 跨越了會話層和表示層。

實現遠端過程呼叫

要實現遠端過程呼叫,需考慮以下幾個問題。

如何傳遞引數

傳遞值引數

傳遞值引數比較簡單,下圖圖展示了一個簡單 RPC 進行遠端計算的例子。其中,遠端過程 add(i,j) 有兩個引數 i 和 j, 其結果是返回 i 和 j 的算術和。

圖4 通過RPC進行遠端計算的步驟

圖4 通過RPC進行遠端計算的步驟

通過 RPC 進行遠端計算的步驟有:

  1. 將引數放入訊息中,並在訊息中新增要呼叫的過程的名稱或者編碼。
  2. 訊息到達伺服器後,伺服器存根堆該訊息進行分析,以判明需要呼叫哪個過程,隨後執行相應的呼叫。
  3. 伺服器執行完畢後,伺服器存根將伺服器得到的結果打包成訊息送回客戶存根,客戶存根將結果從訊息中提取出來,把結果值返回給客戶端。

當然,這裡只是做了簡單的演示,在實際分散式系統中,還需要考慮其他情況,因為不同的機器對於數字、字元和其他型別的資料項的表示方式常有差異。比如整數型,就有 Big Endian 和 Little Endian 之分。

傳遞引用引數

傳遞引用引數相對來說比較困難。單純傳遞引數的引用(也包含指標)是完全沒有意義的,因為引用地址傳遞給遠端計算機,其指向的記憶體位置可能跟遠端系統上完全不同。如果你想支援傳遞引用引數,你必須傳送引數的副本,將它們放置在遠端系統記憶體中,向他們傳遞一個指向伺服器函式的指標,然後將物件傳送回客戶端,複製它的引用。如果遠端過程呼叫必須支援引用複雜的結構,比如樹和連結串列,他們需要將結構複製到一個無指標的表示裡面(比如,一個扁平的樹),並傳輸到在遠端端來重建資料結構。

如何表示資料

在本地系統上不存在資料不相容的問題,因為資料格式總是相同的。而在分散式系統中,不同遠端機器上可能有不同的位元組順序,不同大小的整數,以及不同的浮點表示。對於 RPC,如果想與異構系統通訊,我們就需要想出一個“標準”來對所有資料型別進行編碼,並可以作為引數傳遞。例如,ONC RPC 使用 XDR (eXternal Data Representation) 格式 。這些資料表示格式可以使用隱式或顯式型別。隱式型別,是指只傳遞值,而不傳遞變數的名稱或型別。常見的例子是 ONC RPC 的 XDR 和 DCE RPC 的 NDR。顯式型別,指需要傳遞每個欄位的型別以及值。常見的例子是 ISO 標準 ASN.1 (Abstract Syntax Notation)、JSON (JavaScript Object Notation)、Google Protocol Buffers、以及各種基於 XML 的資料表示格式。

如何選用傳輸協議

有些實現只允許使用一個協議(例如 TCP )。大多數 RPC 實現支援幾個,並允許使用者選擇。

出錯時,會發生什麼

相比於本地過程呼叫,遠端過程調用出錯的機會將會更多。由於本地過程呼叫沒有過程呼叫失敗的概念,專案使用遠端過程呼叫必須準備測試遠端過程呼叫的失敗或捕獲異常。

遠端呼叫的語義是什麼

呼叫一個普通的過程語義很簡單:當我們呼叫時,過程被執行。遠端過程完全一次性呼叫成功是非常難以實現。執行遠端過程可以有如下結果:

  • 如果伺服器崩潰或程序在執行伺服器程式碼之前就死了,那麼遠端過程會被執行0次;
  • 如果一切工作正常,遠端過程會被執行1次;
  • 如果伺服器返回伺服器存根後在傳送響應前就奔潰了,遠端過程會被執行1次或者多次。客戶端接收不到返回的響應,可以決定再試一次,因此出現多次執行函式。如果沒有再試一次,函式執行一次;
  • 如果客戶機超時和重新傳輸,那麼遠端過程會被執行多次。也有可能是原始請求延遲了。兩者都可能會執行或不執行。

RPC 系統通常會提供至少一次或最多一次的語義,或者在兩者之間選擇。如果需要了解應用程式的性質和遠端過程的功能是否安全,可以通過多次呼叫同一個函式來驗證。如果一個函式可以執行任何次數而不影響結果,這是冪等(idempotent)函式的,如每天的時間、數學函式、讀取靜態資料等。否則,它是一個非冪等(nonidempotent)函式,如新增或修改一個檔案)。

遠端呼叫的效能怎麼樣

毫無疑問,一個遠端過程呼叫將會比常規的本地過程呼叫慢得多,因為產生了額外的步驟以及網路傳輸本身存在延遲。然而,這並不應該阻止我們使用遠端過程呼叫。

遠端呼叫安全嗎?

使用 RPC,我們必須關注各種安全問題:

  • 客戶端傳送訊息到遠端過程,那個過程是可信的嗎?
  • 客戶端傳送訊息到遠端計算機,那個遠端機器是可信的嗎?
  • 伺服器如何驗證接收的訊息是來自合法的客戶端嗎?伺服器如何識別客戶端?
  • 訊息在網路中傳播如何防止時被其他程序嗅探?
  • 可以由其他程序訊息被攔截和修改時遍歷網路從客戶端到伺服器或伺服器端?
  • 協議能防止重播攻擊嗎?
  • 如何防止訊息在網路傳播中被意外損壞或截斷?

遠端過程呼叫的優點

遠端過程呼叫有諸多的優點:

  • 你不必擔心傳輸地址問題。伺服器可以繫結到任何可用的埠,然後用 RPC 名稱服務來註冊埠。客戶端將通過該名稱服務來找到對應的埠號所需要的程式。而這一切對於程式設計師來說是透明的。
  • 系統可以獨立於傳輸提供者。自動生成伺服器存根使其可以在系統上的任何一個傳輸提供者上可用,包括 TCP 和 UDP,而這些,客戶端可以動態選擇的。當代碼傳送以後,接收訊息是自動生成的,而不需要額外的程式設計程式碼。
  • 應用程式在客戶端只需要知道一個傳輸地址——名稱服務,負責告訴應用程式去哪裡連線伺服器函式集。
  • 使用函式呼叫模型來代替 socket 的傳送/接收(讀/寫)介面。使用者不需要處理引數的解析。

RPC API

任何 RPC 實現都需要提供一組支援庫。這些包括:

  • 名稱服務操作:
    註冊和查詢繫結資訊(埠、機器)。允許一個應用程式使用動態埠(作業系統分配的);
  • 繫結操作:使用適當的協議建立客戶機/伺服器通訊(建立通訊端點);
  • 終端操作:註冊端點資訊(協議、埠號、機器名)到名稱服務並監聽過程呼叫請求。這些函式通常被自動生成的主程式——伺服器存根(骨架)所呼叫;
  • 安全操作:系統應該提供機制保證客戶端和伺服器之間能夠相互驗證,兩者之間提供一個安全的通訊通道;
  • 國際化操作(可能):這是很少的一部分 RPC 包可能包括了轉換時間格式、貨幣格式和特定於語言的在字串表的字串的功能;
  • 封送處理/資料轉換操作:函式將資料序列化為一個普通的的位元組陣列,通過網路進行傳遞,並能夠重建;
  • 存根記憶體管理和垃圾收集:存根可能需要分配記憶體來儲存引數,特別是模擬引用傳遞語義。RPC 包需要分配和清理任何這樣的分配。他們也可能需要為建立網路緩衝區而分配記憶體。RPC 包支援物件,RPC 系統需要一種跟蹤遠端客戶端是否仍有引用物件或一個物件是否可以刪除。
  • 程式標識操作:允許應用程式訪問(或處理) RPC 介面集的識別符號,這樣的伺服器提供的介面集可以被用來交流和使用。
  • 物件和函式的標識操作:
    允許將遠端函式或遠端物件的引用傳遞給其他程序。並不是所有的 RPC 系統都支援。

所以,判斷一種通訊方式是否是 RPC,就看它是否提供上述的 API。

第一代 RPC

ONC RPC(以前稱為 Sun RPC)

Sun 公司是第一個提供商業化 RPC 庫和 RPC 編譯器。在1980年代中期 Sun 計算機提供 RPC,並在 Sun Network File System(NFS) 得到支援。該協議被主要以 Sun 和 AT&T 為首的 Open Network Computing (開放網路計算)作為一個標準來推動。這是一個非常輕量級 RPC 系統可用在大多數 POSIX 和類 POSIX 作業系統中使用,包括 Linux、SunOS、OS X 和各種釋出版本的 BSD。這樣的系統被稱為 Sun RPC 或 ONC RPC。

ONC RPC 提供了一個編譯器,需要一個遠端過程介面的定義來生成客戶機和伺服器的存根函式。這個編譯器叫做 rpcgen。在執行此編譯器之前,程式設計師必須提供介面定義。包含函式宣告的介面定義,通過版本號進行分組,並被一個獨特的程式編碼來標識。該程式編碼能夠讓客戶來確定所需的介面。版本號是非常有用的,即使客戶沒有更新到最新的程式碼仍然可以連線到一個新的伺服器,只要該伺服器還支援舊介面。

引數通過網路轉化成一種隱式型別序列化格式被稱為 XDR (eXternal Data Representation)。這將確保引數能夠傳送到異構系統可以被正常使用,及時這些系統可能使用了不同的位元組順序,不同大小的整數,或不同的浮點或字串表示。最後,Sun RPC 提供了一個實現必要的支援 RPC 協議和 socket 例程的執行時庫。

所有的程式設計師都需要寫是一個客戶端程式(client.c),伺服器功能(server.c)和 RPC 介面定義(date.x)。當 RPC 介面定義(字尾為.x 的檔案,例如 date.x)是用 rpcgen 編譯的,會建立三個或四個檔案。下面是 date.x 的例子:

  • date.h:包含專案的定義、版本和宣告的函式。客戶端和伺服器端功能應該包括這個檔案。
  • date_svc.c :C 語言程式碼來實現伺服器存根。
  • date_clnt.c :C 語言程式碼來實現客戶端存根。
  • date_xdr.c :包含 XDR 例程來將資料轉化為 XDR 格式。如果這個檔案生成,它應該編譯並用來連結在客戶端和伺服器的函式。

建立客戶端和伺服器可執行檔案的第一步是定義在檔案 date.x 裡的編譯資料。之後,客戶端和伺服器端函式可能被編譯,並連結各自 rpcgen 生成的存根函式。

在舊版本里,傳輸協議只能將字串“tcp”或字串“udp”來指定各自的 IP 服務 RPC,且僅限於 Linux 實現的 RPC。為了使介面更加靈活,UNIX 系統從版本 4 (SunOS 從版本 5)開始網路選擇程式允許一個更普通的規範。他們搜尋檔案(/etc/netconfig),來查詢第一個滿足您需求的提供者。最後一個引數可以是:

  • “netpath”:搜尋 NETPATH 環境變數用於首選傳輸提供者的序列;
  • “circuit_n”:找到第一個在 NETPATH 列表中的虛擬電路提供者;
  • “datagram_n”:找到第一個 NETPATH 列表中的資料報提供者;
  • “visible”:找到第一個在 /etc/netconfig 的可見傳輸提供者;
  • “circuit_v”:找到第一個在 /etc/netconfig 的可見虛擬電路傳輸提供者;
  • “datagram_v”:找到第一個在 /etc/netconfig 的可見資料報傳輸提供者;

每個遠端過程呼叫最初僅限於接受一個輸入引數。系統只是後來修改為支援多個引數。支援單一引數 RPC 在一些 rpcgen 的版本中仍然是預設的,比如蘋果的 OS X。傳遞多個引數必須通過定義一個結構,包含所需的引數,初始化它,並傳遞這個結構。

遠端過程呼叫返回一個指標指向結果而不是期望的結果。伺服器函式必須修改來能接受一個 RPC 定義(.x 檔案)中宣告的值的指標作為輸入,並返回一個結果值的指標。在伺服器上,一個指標必須是指向靜態資料的指標。否則,當過程返回或釋放過程的框架所指出的區域將未定義。在客戶端,返回指標可以讓我們區分一個失敗的 RPC(空指標)和一個空返回從伺服器(間接空指標)。

RPC 過程的名稱若在 RPC 定義檔案中做了定義,則會轉換為小寫,並在字尾價下劃線,後跟一個版本號。例如,BIN_DATE 轉成為引用函式 bin_date_1 。您的伺服器必須實現 bin_date_1。

當我們執行這個程式時,會發生什麼?

伺服器

當我們啟動伺服器,伺服器存根程式碼(程式)在後臺執行執行。它建立一個 socket 並可繫結任何本地埠到 socket。然後呼叫一個在 RPC 庫的函式 svc_register,來註冊程式編號和版本。這個是用來聯絡 port mapper(埠對映器)。port mapper 是一個獨立的程序,通常是在系統啟動時啟動。它跟蹤埠號、版本號以及程式編號。在 UNIX 系統版本4中,這個程序稱為 rpcbind。在 Linux 、OS X 和 BSD 系統,它被稱為 portmap。

圖5 ONC RPC 中的函式查詢

圖5 ONC RPC 中的函式查詢

客戶端

當我們開始客戶端程式時,它首先用遠端系統的名稱、程式編號、版本號和協議來呼叫 clnt_create 。它接觸遠端系統上的埠對映器,來為系統找到合適的埠。

然後客戶端呼叫 RPC 存根函式(在本例中為 bin_date_1)。該函式傳送一條訊息(如,資料報)到伺服器(使用早些時候發現的埠號)並等待響應。對於資料報服務來說,若沒有接收到響應,它將重新發送一個固定的次數請求。

訊息接著被遠端系統接收到,它呼叫伺服器函式(bin_date_1)並將返回值返回給客戶端存根。客戶端存根而後返回到客戶端發出呼叫的程式碼。

分散式計算環境中的 RPC(DCE RPC)

DCE(Distributed Computing Environment,分散式計算環境)是一組由OFS(Open Software Foundation,開放軟體基金會)設計的元件,用來提供支援分散式應用和分散式環境。與 X/Open 合併後,這組織成為了 The Open Group (開放式開發組)。DCE 提供的元件包括一個分散式檔案服務、時間服務、目錄服務以及其他服務。當然,我們感興趣的是 DCE 的遠端過程呼叫。它非常類似於 Sun RPC。介面是由 Interface Definition Notation (IDN) 定義的。類似於 Sun RPC,介面定義就像函式原型。

Sun RPC 不足之處在於,伺服器的標識是一個“獨特”的 32-bit 數字。雖然這是一個比在 socket 中 16-bit 可用空間更大的空間,但仍然無法滿足數字唯一性的需求。DCE RPC 考慮到了這一缺陷,它無需程式設計師來處理編碼。在編寫應用程式時的第一步是從 uuidgen 程式獲得一個惟一的 ID。這個程式會生成一個包含 ID 介面的原型 IDN 檔案,並保證永遠不會再次使用。它是一個 128-bit 的值,其中包含一個位置程式碼和建立時間的編碼。然後使用者編輯原型檔案,填寫遠端過程宣告。

在這一步後,IDN 的編譯器 dceidl(類似於 rpcgen)會生成一個頭、客戶機存根和伺服器存根。

Sun RPC 的另一個缺陷是,客戶端必須知道伺服器在哪臺機器上。當它要訪問時,必須要詢問機器上的 RPC 名稱服務程式編碼所對應的埠號。DCE 支援將多個機器組織成為管理實體,稱為 cells。cell 目錄伺服器使得每臺機器知道如何與另外一臺負責維護 cell 資訊服務機器互動。

在 Sun RPC 中,伺服器只能用本地名稱服務(埠對映器)來註冊其程式編號到埠對映。而在 DCE 中,伺服器用 RPC 守護程序(名稱伺服器)來註冊其端點(埠)到本地機器,並且用 cell 目錄伺服器註冊其程式名字到機器的對映。當客戶機想要與一個 RPC 伺服器建立通訊,它首先要求其 cell 目錄伺服器來定位伺服器所在的機器。然後客戶端從 RPC 守護程序處獲得機器上伺服器程序的埠號。DCE 的跨 cell 還支援更復雜的搜尋。

DCE RPC 定義了 NDR (Network Data Representation) 用於對網路進行編碼來封送資訊。與用一個單一的規範來表示不同的資料型別相比,NDR 支援多規範(multi-canonical)格式。允許客戶端來選擇使用哪種格式,理想的情況是不需要將它從本地型別來轉換。如果這不同於伺服器的本地資料表示,伺服器將仍然需要轉換,但多規範格式可以避免當客戶端和伺服器都共享相同的本地格式的情況下轉換為其他外部格式。例如,在一個規定了大端位元組序網路資料格式的情況下,客戶端和伺服器只支援小端位元組序,那麼客戶端必須將每個資料從小端位元組序轉為大端位元組序,而當伺服器接受到訊息後,將每個資料轉回小端位元組序。多規範網路資料表示將允許客戶端傳送網路訊息包含小端位元組序格式的資料。

圖6  DCE RPC 中的函式查詢

圖6 DCE RPC 中的函式查詢

第二代 RPC:支援物件

面向物件的語言開始在1980年代末興起,很明顯,當時的 Sun ONC 和 DCE RPC 系統都沒有提供任何支援諸如從遠端類例項化遠端物件、跟蹤物件的例項或提供支援多型性。現有的 RPC 機制雖然可以運作,但他們仍然不支援自動、透明的方式的面向物件程式設計技術。

微軟 DCOM(COM+)

1992年4月,微軟釋出 Windows 3.1 包括一種機制稱為 OLE (Object Linking and Embedding)。這允許一個程式動態連結其他庫來支援的其他功能。如將一個電子表格嵌入到 Word 文件。OLE 演變成了 COM (Component Object Model)。一個 COM 物件是一個二進位制檔案。使用 COM 服務的程式來訪問標準化介面的 COM 物件而不是其內部結構。COM 物件用全域性唯一識別符號(GUID)來命名,用類的 ID 來識別物件的類。幾種方法來建立一個 COM 物件(例如 CoGetInstanceFromFile)。COM 庫在系統登錄檔中查詢相應的二進位制程式碼(一個 DLL 或可執行檔案),來建立物件,並給呼叫者返回一個介面指標。COM 的著眼點是在於同一臺計算機上不同應用程式之間的通訊需求.

DCOM( Distributed Component Object Model)是 COM 的擴充套件,它支援不同的兩臺機器上的元件間的通訊,而且不論它們是執行在區域網、廣域網、還是 Internet 上。藉助 DCOM 你的應用程式將能夠進行任意空間分佈。DCOM 於1996年在 Windows NT4.0 中引入的,後來更名為 COM+。由於 DCOM 是為了支援訪問遠端 COM 物件,需要建立一個物件的過程,此時需要提供伺服器的網路名以及類 ID。微軟提供了一些機制來實現這一點。最透明的方式是遠端計算機的名稱固定在登錄檔(或 DCOM 類儲存)裡,與特定類 ID 相關聯。以此方式,應用程式不知道它正在訪問一個遠端物件,並且可以使用與訪問本地 COM 物件相同的介面指標。另一方面,應用程式也可指定一個機器名作為引數。

由於 DCOM 是 COM 這個元件技術的無縫升級,所以你能夠從你現有的有關 COM 得知識中獲益,你的以前在 COM 中開發的應用程式、元件、工具都可以移入分散式的環境中。DCOM 將為你遮蔽底層網路協議的細節,你只需要集中精力於你的應用。

DCOM 最大的缺點是這是微軟獨家的解決辦法,在跨防火牆方面的工作做得不是很好(大多數RPC系統也有類似的問題),因為防火牆必須允許某些埠來允許 ORPC 和 DCOM 通過。

CORBA

雖然 DCE 修復的一些 Sun RPC 的缺點,但某些缺陷依然存在。例如,如果伺服器沒有執行,客戶端是無法連線到遠端過程進行呼叫的。管理員必須要確保在任何客戶端試圖連線到伺服器之前將伺服器啟動。如果一個新服務或介面新增到了系統,客戶端是不能發現的。最後,面嚮物件語言期望在函式呼叫中體現多型性,即不同型別的資料的函式的行為應該有所不同,而這點恰恰是傳統的 RPC 所不支援的。

CORBA (Common Object Request Broker Architecture) 就是為了解決上面提到的各種問題。是由 OMG 組織制訂的一種標準的面向物件應用程 序體系規範。或者說 CORBA體系結構是物件管理組織(OMG)為解決分散式處理環境(DCE)中,硬體和軟體系統的互連而提出的一種解決方案。OMG 成立於1989年,作為一個非營利性組織,集中致力於開發在技術上具有先進性、在商業上具有可行性並且獨立於廠商的軟體互聯規範,推廣面向物件模型技術,增強軟體的可移植性(Portability)、可重用性(Reusability)和互操作性(Interoperability)。該組織成立之初,成員包括 Unisys、Sun、Cannon、Hewlett-Packard 和 Philips 等在業界享有聲譽的軟硬體廠商,目前該組織擁有800多家成員。

CORBA 體系的主要內容包括以下幾部分:

  • 物件請求代理 (Object Request Broker,ORB):負責物件在分佈環境中透明地收發請求和響應,它是構建分佈物件應用、在異構或同構環境下實現應用間互操作的基礎。
  • 物件服務(Object Services):為使用和實現物件而提供的基本物件集合,這些服務應獨立於應用領域。主要的 CORBA 服務有:名錄服務(Naming Service)、事件服務(Event Service)、生命週期服務(Life Cycle Service)、關係服務(Relationship Service)以及事務服務(Transaction Service)等。這些服務幾乎包括分佈系統和麵向物件系統的各個方面,每個組成部分都非常複雜。
  • 公共設施(Common Facilitites):向終端使用者提供一組共享服務介面,例如系統管理、組合文件和電子郵件等。
  • 應用介面(Application Interfaces)。由銷售商提供的可控制其介面的產品,相應於傳統的應用層表示,處於參考模型的最高層。
  • 領域介面(Domain Interfaces):為應用領域服務而提供的介面,如OMG 組織為 PDM 系統制定的規範。

當客戶端發出請求時,ORB 做了如下事情:

  • 在客戶端編組引數;
  • 定位伺服器物件。如果有必要的話,它會在伺服器建立一個過程來處理請求;
  • 如果伺服器是遠端是,就使用 RPC 或 socket 來傳送請求;
  • 在伺服器上將引數解析成為伺服器格式;
  • 在伺服器上組裝返回值;
  • 如果伺服器是遠端的,就將返回值傳回;
  • 在客戶端對返回結果進行解析;

IDL(Interface Definition Language) 是用於指定類的名字、屬性和方法。它不包含物件的實現。IDL 編譯器生成程式碼來處理編組、解封以及ORB與網路之間的互動。它會生成客戶機和伺服器存根。IDL 是程式語言中立,支援包括C、C++、Java、Perl、Python、Ada、COBOL、Smalltalk、Objective C 和 LISP 等語言。一個示例IDL如下所示:

Module StudentObject {
    Struct StudentInfo {
        String name;
        int id;
        float gpa;
    };
    exception Unknown {};
    interface Student {
        StudentInfo getinfo(in string name)
            raises(unknown);
        void putinfo(in StudentInfo data);
    };
};

IDL資料型別包括:

  • 基本型別:long, short, string, float, …
  • 構造型別:struct、union、列舉、序列
  • 物件引用
  • any 型別:一個動態型別的值

程式設計中最常見的實現方式是通過物件引用來實現請求。下面是一個使用 IDL 的例子:

Student st = ... // get object reference
try {
    StudentInfo sinfo = st.getinfo("Fred Grampp");
} catch (Throwable e) {
    ... // error
}

在 CORBA 規範中,沒有明確說明不同廠商的中介軟體產品要實現所有的服務功能,並且允許廠商開發自己的服務型別。因此, 不同廠商的 ORB 產品對 CORBA 服務的支援能力不同,使我們在針對待開發系統的功能進行中介軟體產品選擇時,有更多的選擇餘地。

CORBA 的不足有:

  • 儘管有多家供應商提供CORBA產品,但是仍找不到能夠單獨為異種網路中的所有環境提供實現的供應商。不同的 CORBA 實現之間會出現缺乏互操作性的現象,從而造成一些問題;而且,由於供應商常常會自行定義擴充套件,而 CORBA 又缺乏針對多執行緒環境的規範,對於像 C 或 C++ 這樣的語言,原始碼相容性並未完全實現。
  • CORBA 過於複雜,要熟悉 CORBA,並進行相應的設計和程式設計,需要許多個月來掌握,而要達到專家水平,則需要好幾年。

更多有關 CORBA 的優缺點,可以參閱 Michi Henning 的《The rise and fall of CORBA》。

Java RMI

CORBA 旨在提供一組全面的服務來管理在異構環境中(不同語言、作業系統、網路)的物件。Java 在其最初只支援通過 socket 來實現分散式通訊。1995年,作為 Java 的締造者,Sun 公司開始建立一個 Java 的擴充套件,稱為 Java RMI(Remote Method Invocation,遠端方法呼叫)。Java RMI 允許程式設計師建立分散式應用程式時,可以從其他 Java 虛擬機器(JVM)呼叫遠端物件的方法。

一旦應用程式(客戶端)引用了遠端物件,就可以進行遠端呼叫了。這是通過 RMI 提供的命名服務(RMI 註冊中心)來查詢遠端物件,來接收作為返回值的引用。Java RMI 在概念上類似於 RPC,但能在不同地址空間支援物件呼叫的語義。

與大多數其他諸如 CORBA 的 RPC 系統不同,RMI 只支援基於 Java 來構建,但也正是這個原因, RMI 對於語言來說更加整潔,無需做額外的資料序列化工作。Java RMI 的設計目標應該是:

  • 能夠適應語言、整合到語言、易於使用;
  • 支援無縫的遠端呼叫物件;
  • 支援伺服器到 applet 的回撥;
  • 保障 Java 物件的安全環境;
  • 支援分散式垃圾回收;
  • 支援多種傳輸。

分散式物件模型與本地 Java 物件模型相似點在於:

  • 引用一個物件可以作為引數傳遞或作為返回的結果;
  • 遠端物件可以投到任何使用 Java 語法實現的遠端介面的集合上;
  • 內建 Java instanceof 操作符可以用來測試遠端物件是否支援遠端介面。

不同點在於:

  • 遠端物件的類是與遠端介面進行互動,而不是與這些介面的實現類互動;
  • Non-remote 引數對於遠端方法呼叫來說是通過複製,而不是通過引用;
  • 遠端物件是通過引用來傳遞,而不是複製實際的遠端實現;
  • 客戶端必須處理額外的異常。

介面和類

所有的遠端介面都繼承自 java.rmi.Remote 介面。例如:

public interface bankaccount extends Remote
{
    public void deposit(float amount)
        throws java.rmi.RemoteException;

    public void withdraw(float amount)
        throws OverdrawnException,
        java.rmi.RemoteException;
}

注意,每個方法必須在 throws 裡面宣告 java.rmi.RemoteException 。 只要客戶端呼叫遠端方法出現失敗,這個異常就會丟擲。

遠端物件類

Java.rmi.server.RemoteObject 類提供了遠端物件實現的語義包括hashCode、equals 和 toString。 java.rmi.server.RemoteServer 及其子類提供讓物件實現遠端可見。java.rmi.server.UnicastRemoteObject 類定義了客戶機與伺服器物件例項建立一對一的連線.

存根

Java RMI 通過建立存根函式來工作。存根由 rmic 編譯器生成。自 Java 1.5 以來,Java 支援在執行時動態生成存根類。編譯器 rmic 會提供各種編譯選項。

定位物件

引導名稱服務提供了用於儲存對遠端物件的命名引用。一個遠端物件引用可以儲存使用類 java.rmi.Naming 提供的基於 URL 的方法。例如,

BankAccount acct = new BankAcctImpl();
String url = "rmi://java.sun.com/account";
// bind url to remote object
java.rmi.Naming.bind(url, acct);

// look up account
acct = (BankAccount)java.rmi.Naming.lookup(url);

圖7 Java RMI 工作流程

圖7 Java RMI 工作流程

RMI 架構

RMI 是一個三層架構(圖8)。最上面是 Stub/Skeleton layer(存根/骨架層)。方法呼叫從 Stub、Remote Reference Layer (遠端引用層)和 Transport Layer(傳輸層)向下,傳遞給主機,然後再次經傳 Transport Layer 層,向上穿過 Remote Reference Layer 和 Skeleton ,到達伺服器物件。 Stub 扮演著遠端伺服器物件的代理的角色,使該物件可被客戶啟用。Remote Reference Layer 處理語義、管理單一或多重物件的通訊,決定呼叫是應發往一個伺服器還是多個。Transport Layer 管理實際的連線,並且追蹤可以接受方法呼叫的遠端物件。伺服器端的 Skeleton 完成對伺服器物件實際的方法呼叫,並獲取返回值。返回值向下經 Remote Reference Layer 、伺服器端的 Transport Layer 傳遞迴客戶端,再向上經 Transport Layer 和 Remote Reference Layer 返回。最後,Stub 程式獲得返回值。

要完成以上步驟需要有以下幾個步驟:

  • 生成一個遠端介面;
  • 實現遠端物件(伺服器端程式);
  • 生成 Stub 和 Skeleton(伺服器端程式);
  • 編寫伺服器程式 ;
  • 編寫客戶程式 ;
  • 註冊遠端物件;
  • 啟動遠端物件

圖8 Java RMI 架構

圖8 Java RMI 架構

RMI 分散式垃圾回收

根據 Java 虛擬機器的垃圾回收機制原理,在分散式環境下,伺服器程序需要知道哪些物件不再由客戶端引用,從而可以被刪除(垃圾回收)。在 JVM中,Java 使用引用計數。當引用計數歸零時,物件將會垃圾回收。在RMI,Java 支援兩種操作:dirty 和 clean。本地 JVM 定期傳送一個 dirty 到伺服器來說明該物件仍在使用。定期重發 dirty 的週期是由伺服器租賃時間來決定的。當客戶端沒有需要更多的本地引用遠端物件時,它傳送一個 clean 呼叫給伺服器。不像 DCOM,伺服器不需要計算每個客戶機使用的物件,只是簡單的做下通知。如果它租賃時間到期之前沒有接收到任何 dirty 或者 clean 的訊息,則可以安排將物件刪除。

第三代 RPC 以及 Web Services

由於網際網路的興起,Web 瀏覽器成為占主導地位的用於訪問資訊的模型。現在的應用設計的首要任務大多數是提供使用者通過瀏覽器來訪問,而不是程式設計訪問或操作資料。

網頁設計關注的是內容。解析展現方面往往是繁瑣的。傳統 RPC 解決方案可以工作在網際網路上,但問題是,他們通常嚴重依賴於動態埠分配,往往要進行額外的防火牆配置。

Web Services 成為一組協議,允許服務被髮布、發現,並用於技術無關的形式。即服務不應該依賴於客戶的語言、作業系統或機器架構。

Web Services 的實現一般是使用 Web 伺服器作為服務請求的管道。客戶端訪問該服務,首先是通過一個 HTTP 協議傳送請求到伺服器上的 Web 伺服器。Web 伺服器配置識別 URL 的一部分路徑名或檔名字尾並將請求傳遞給特定的瀏覽器外掛模組。這個模組可以除去頭、解析資料(如果需要),並根據需要呼叫其他函式或模組。對於這個實現流,一個常見的例子是瀏覽器對於 Java Servlet 的支援。HTTP 請求會被轉發到 JVM 執行的服務端程式碼來執行處理。

XML-RPC

XML-RPC 是1998年作為一個 RPC 訊息傳遞協議,將請求和響應封裝解析為人類可讀的 XML格式。XML 格式基於 HTTP 協議,緩解了傳統企業的防火牆需要為 RPC 伺服器應用程式開啟額外的埠的問題。

下面是一個 XML-RPC 訊息的例子:

<methodCall>
    <methodName>
        sample.sumAndDifference
    </methodName>
    <params>
        <param><value><int> 5 </int></value></param>
        <param><value><int> 3 </int></value></param>
    </params>
</methodCall>

這個例子中,方法 sumAndDifference 有兩個整數引數 5 和 3。

XML-RPC 支援的基本資料型別是:int、string、boolean、double 和 dateTime.iso8601。此外,還有 base64 型別用於編碼任意二進位制資料。array 和 struct 允許定義陣列和結構。

XML-RPC 不限制語任何特定的語言,也不是一套完整的軟體來處理遠端過程,諸如存根生成、物件管理和服務查詢都不在協議內。現在有很多庫針可以針對不同的語言,比如 Apache XML-RPC 可以用於 Java、Python 和 Perl。

XML-RPC 是一個簡單的規範(約7頁),沒有雄心勃勃的目標——它只關注訊息,而並不處理諸如垃圾收集、遠端物件、遠端過程的名稱服務和其他方面的問題。然而,即使沒有廣泛的產業支援,簡單的協議卻能廣泛採用。

SOAP

SOAP(Simple Object Access Protocol,簡單物件訪問協議),是以 XML-RPC 規範作為建立 SOAP 的依據,成立於1998年,獲得微軟和 IBM 的大力支援。該協議在建立初期只作為一種物件訪問協議,但由於 SOAP 的發展,其協議已經不單只是用於簡單的訪問物件,所以這種 SOAP 縮寫已經在標準的1.2版後被廢止了。1.2版在2003年6月24日成為 W3C 的推薦版本。SOAP 指定 XML 作為無狀態的訊息交換格式,包括了 RPC 式的過程呼叫。

SOAP 只是一種訊息格式,並未定義垃圾回收、物件引用、存根生成和傳輸協議。

下面是一個簡單的例子:

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
          env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
          env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <n:name>Åke Jógvan Øyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itinerary
    xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>New York</p:departing>
     <p:arriving>Los Angeles</p:arriving>
     <p:departureDate>2001-12-14</p:departureDate>
     <p:departureTime>late afternoon</p:departureTime>
     <p:seatPreference>aisle</p:seatPreference>
   </p:departure>
   <p:return>
     <p:departing>Los Angeles</p:departing>
     <p:arriving>New York</p:arriving>
     <p:departureDate>2001-12-20</p:departureDate>
     <p:departureTime>mid-morning</p:departureTime>
     <p:seatPreference/>
   </p:return>
  </p:itinerary>
  <q:lodging
   xmlns:q="http://travelcompany.example.org/reservation/hotels">
   <q:preference>none</q:preference>
  </q:lodging>
 </env:Body>
</env:Envelope>

其中<soap:Envelope>是 SOAP 訊息中的根節點,是 SOAP 訊息中必須的部分。<soap:Header>是 SOAP 訊息中可選部分,是指訊息頭。<soap:Body>是 SOAP 中必須部分,是指訊息體。

上面例子的 SOAP 訊息結構如下:

圖9 SOAP 訊息結構

圖9 SOAP 訊息結構

SOAP 它只是提供了一個標準化的訊息結構,為了實現它往往需要用 WSDL 來描述 Web Services 的方法。WSDL (Web Services Description Language) 是基於 XML 的一種用於描述 Web Services 以及如何訪問 Web Services 的語言。

WSDL 文件包括以下幾個部分:

  • 型別(Types):定義了 Web Services 使用的資料型別;
  • 訊息(n/a):描述使用訊息的資料元素或引數;
  • 介面(Interface):描述服務提供的操作。這包括操作以及每個操作所使用的輸入和輸出訊息;
  • 繫結(Binding):為每個埠定義訊息格式和協議細節。例如,它可以定義 RPC 式的訊息;
  • 服務(Service):系統功能相關的集合,包括其關聯的介面、操作、訊息等;
  • 終點(Endpoint):定義了地址或者 Web Services 的連線點;
  • 操作(Operation):定義了 SOAP 的動作,以及訊息編碼的方式。

下面是一個 WSDL 2.0 版本的例子:

<?xml version="1.0" encoding="UTF-8"?>
<description xmlns="http://www.w3.org/ns/wsdl" 
             xmlns:tns="http://www.tmsws.com/wsdl20sample" 
             xmlns:whttp="http://schemas.xmlsoap.org/wsdl/http/"
             xmlns:wsoap="http://schemas.xmlsoap.org/wsdl/soap/"
             targetNamespace="http://www.tmsws.com/wsdl20sample">

<documentation>
    This is a sample WSDL 2.0 document. 
</documentation>

   <!-- Abstract type -->
   <types>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns="http://www.tmsws.com/wsdl20sample"
                targetNamespace="http://www.example.com/wsdl20sample">

         <xs:element name="request"> ... </xs:element>
         <xs:element name="response"> ... </xs:element>
      </xs:schema>
   </types>

   <!-- Abstract interfaces -->
   <interface name="Interface1">
      <fault name="Error1" element="tns:response"/>
      <operation name="Get" pattern="http://www.w3.org/ns/wsdl/in-out">
         <input messageLabel="In" element="tns:request"/>
         <output messageLabel="Out" element="tns:response"/>
      </operation>
   </interface>

   <!-- Concrete Binding Over HTTP -->
   <binding name="HttpBinding" interface="tns:Interface1" 
            type="http://www.w3.org/ns/wsdl/http">
      <operation ref="tns:Get" whttp:method="GET"/>
   </binding>

   <!-- Concrete Binding with SOAP-->
   <binding name="SoapBinding" interface="tns:Interface1" 
            type="http://www.w3.org/ns/wsdl/soap" 
            wsoap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/"
            wsoap:mepDefault="http://www.w3.org/2003/05/soap/mep/request-response">
      <operation ref="tns:Get" />
   </binding>

   <!-- Web Service offering endpoints for both bindings-->
   <service name="Service1" interface="tns:Interface1">
      <endpoint name="HttpEndpoint" 
                binding="tns:HttpBinding" 
                address="http://www.example.com/rest/"/>
      <endpoint name="SoapEndpoint" 
                binding="tns:SoapBinding" 
                address="http://www.example.com/soap/"/>
   </service>
</description>

Microsoft .NET Remoting

從微軟的產品角度來看,可以說 .NET Remoting 就是 DCOM 的一種升級,它改善了很多功能,並極好的融合到 .NET 平臺下。Microsoft .NET Remoting 提供了一種允許物件通過應用程式域與另一物件進行互動的框架。

.NET Remoting 提供了一種允許物件通過應用程式域與另一物件進行互動的框架。這種框架提供了多種服務,包括啟用和生存期支援,以及負責與遠端應用程式進行訊息傳輸的通訊通道。格式化程式用於在訊息通過通道傳輸之前,對其進行編碼和解碼。應用程式可以在注重效能的場合使用二進位制編碼,在需要與其他遠端處理框架進行互動的場合使用 XML 編碼。在從一個應用程式域向另一個應用程式域傳輸訊息時,所有的 XML 編碼都使用 SOAP 協議。出於安全性方面的考慮,遠端處理提供了大量掛鉤,使得在訊息流通過通道進行傳輸之前,安全接收器能夠訪問訊息和序列化流

.NET Remoting 物件

有三類物件可以配置為 .NET Remoting 物件。您可以根據應用程式的需要來選擇物件型別:

  • Single Call(單一呼叫物件):
    Single Call 能且只能為一個請求提供服務。在需要物件完成的工作量有限的情況下 Single Call 非常有用。Single Call 物件通常不要求儲存狀態資訊,並且不能在方法呼叫之間保留狀態資訊。但是,Single Call物件可以配置為負載平衡模式。
  • Singleton Objects(單一元素物件):
    Singleton Objects 可以為多個客戶端提供服務,因此可以通過儲存客戶端呼叫的狀態資訊來實現資料共享。當客戶端之間需要明確地共享資料,並且不能忽略建立和維護物件的開銷時,這類物件非常有用。
  • Client-Activated Objects (CAO,客戶端啟用的物件):
    CAO 是伺服器端的物件,將根據來自客戶端的請求啟用這些物件。這種啟用伺服器物件的方法與傳統的 COM coclass 啟用方法非常相似。當客戶端使用“new”運算子提交對伺服器物件的請求時,會向遠端應用程式傳送一個啟用請求訊息。隨後,伺服器建立被請求類的例項,並向呼叫它的客戶端應用程式返回 ObjRef。然後,使用此 ObjRef 在客戶端上建立代理。客戶端的方法呼叫將在代理上執行。客戶端啟用的物件可以為特定的客戶端(不能跨越不同的客戶端物件)儲存方法呼叫之間的狀態資訊。每個“new”呼叫都會向伺服器型別的獨立例項返回代理。

在 .NET Remoting 中,可以通過以下方式在應用程式之間傳遞物件:

  • 作為方法呼叫中的引數,例如:public int myRemoteMethod (MyRemoteObject myObj)
  • 方法呼叫的返回值,例如:public MyRemoteObject myRemoteMethod(String myString)
  • 訪問 .NET 元件的屬性或欄位得到的值,例如:myObj.myNestedObject

對於 Marshal By Value (MBV,按值封送)的物件,當它在應用程式之間傳遞時,將建立一個完整的副本。

對於 Marshal By Reference (MBR,按引用封送)的物件,當它在應用程式之間傳遞時,將建立該物件的引用。當物件引用 (ObjRef) 到達遠端應用程式後,將轉變成“代理”返回給原始物件。
  
下面是一個簡單 .NET Remoting 伺服器物件的程式碼示例:

using System;
using System.Runtime.Remoting;
namespace myRemoteService
{
    // Well Known Web Service object
    public class myRemoteObject : MarshalByRefObject
    {
        // Method myRemoteMethod
        
            
           

相關推薦

遠端過程呼叫(RPC)

本文介紹了什麼是遠端過程呼叫(RPC),RPC 有哪些常用的方法,RPC 經歷了哪些發展階段,以及比較了各種 RPC 技術的優劣。 什麼是 RPC RPC 是遠端過程呼叫(Remote Procedure Call)的縮寫形式,Birrell 和 N

遠端過程呼叫 RPC 及其協議

遠端過程呼叫 簡介 RPC是遠端過程呼叫(Remote Procedure Call)的縮寫形式。SAP系統RPC呼叫的原理其實很簡單,有一些類似於三層構架的C/S系統,第三方的客戶程式通過介面呼叫SAP內部的標準或自定義函式,獲得函式返回的資料進行處理後顯示或列印。

PHP實現遠端過程呼叫RPC

一、初識RPC RPC(Remote Procedure Call)—遠端過程呼叫,它是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議。 二、工作原理 執行時,一次客戶機對伺服器的RPC呼叫,其內部操作大致有如下十步: 1.呼叫客戶端控制代碼;執行傳送引數

com.microsoft.sqlserver.jdbc.SQLServerException: 傳入的表格格式資料流(TDS)遠端過程呼叫(RPC)協議流不正確。此 RPC 請求中提供了過多的引數。

sqlserver在做批量插入的時候出現這個錯誤: com.microsoft.sqlserver.jdbc.SQLServerException: 傳入的表格格式資料流(TDS)遠端過程呼叫(RPC)協議流不正確。此 RPC 請求中提供了過多的引數。最多應為 2100。

[譯]RabbitMQ教程C#版 - 遠端過程呼叫(RPC)

原文: [譯]RabbitMQ教程C#版 - 遠端過程呼叫(RPC) 先決條件 本教程假定 RabbitMQ 已經安裝,並執行在localhost標準埠(5672)。如果你使用不同的主機、埠或證書,則需要調整連線設定。 從哪裡獲得幫助 如果您在閱讀本教程時遇到困難,可以通過郵件列表 聯絡我們。

輕鬆搞定RabbitMQ(七)——遠端過程呼叫RPC

翻譯:http://www.rabbitmq.com/tutorials/tutorial-six-java.html在第二篇博文中,我們已經瞭解到瞭如何使用工作佇列來向多個消費者分散耗時任務。但是付過我們需要在遠端電腦上執行一個方法然後等待結果,該怎麼辦?這是不同的需求。

.Net下RabbitMQ的使用(8) -- 遠端過程呼叫RPC

RPC是在計算中是一種常見的模式,是通常我要用訊息佇列來實現RPC有3個關鍵點: 1. 服務的定址 2. 訊息的接收 3. 訊息的關聯 在RabbitMQ的.net客戶端裡,提供了2個類:SimpleRpcClient 和 SimpleRpcServer

RabbitMQ入門:遠端過程呼叫(RPC)

假如我們想要呼叫遠端的一個方法或函式並等待執行結果,也就是我們通常說的遠端過程呼叫(Remote Procedure Call)。怎麼辦? 今天我們就用RabbitMQ來實現一個簡單的RPC系統:客戶端傳送一個請求訊息,服務端以一個響應訊息迴應。為了能夠接收到響應,客戶端在傳送訊息的同時傳送一個回撥佇列用來

奇怪的資料插入異常:傳入的表格格式資料流(TDS)遠端過程呼叫(RPC)協議流不正確。

前天完成了手頭的工作後,經理交給我一個bug讓我看下,我接過後看了下Bug資訊,是從未見過的異常,但根據異常資訊提示又很容易判斷出異常原因。 異常資訊:傳入的表格格式資料流(TDS)遠端過程呼叫(RPC)協議流不正確。引數 7 ("@ExchangeRate"): 提供的值不

第2部分 啟用遠端過程呼叫RPC

1 第2部分 啟用遠端過程呼叫——讓我們構建一個烤麵包機 烤麵包機樣例的第二部分將會加入一些烤麵包行為,為了完成這個任務,我們將會在toaster yang 資料模型中定義一個RPC(遠端過程呼叫)並且會寫一個實現。 1.1 定義yang RPC 編輯現有的toaster.

.Net下RabbitMQ的使用(7) -- 遠端過程呼叫RPC

RPC是在計算中是一種常見的模式,是通常我要用訊息佇列來實現RPC有3個關鍵點: 1. 服務的定址 2. 訊息的接收 3. 訊息的關聯 在RabbitMQ的.net客戶端裡,提供了2個類:SimpleRpcClient 和 SimpleRpcServer 來讓我們

RPC遠端過程呼叫

今天看了兩篇關於RPC遠端過程呼叫的,寫的很好,分享一下。 http://blog.csdn.net/mindfloating/article/details/39473807 http://blog.csdn.net/mindfloating/article/detail

RPC 協議 Remote process call 遠端過程呼叫

RPC資訊協議由兩個不同結構組成:呼叫資訊和答覆資訊。 簡單的說,RPC就是從一臺機器(客戶端)上通過引數傳遞的方式呼叫另  一臺機器(伺服器)上的一個函式或方法(可以統稱為服務)並得到返回的結果。 RPC 會隱藏底層的通訊細節(不需要直接處理Socket通訊或Http通訊

RPC遠端過程呼叫)簡介

RPC(Remote Procedure Call Protocol)——遠端過程呼叫協議,它是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議。 之前聽過這個名詞,但是也只是大概記住了“遠端呼叫”之類的關鍵詞,而其他並沒有太多瞭解。 來到TX實習,確實如別人所說的那樣

RabbitMQ的學習(四):RPC-遠端過程呼叫(純demo-可直接使用)

前言:在前面三篇文章中,分別對rabbitmq的搭建,並對rabbitmq常用的四種不同的交換機結合路由鍵編寫了各自的demo,可以參考: 1. RabbitMQ的學習(一):Windows下安裝及配置RabbitMQ,erlang環境變數; 2. RabbitMQ的學習(二):簡單的j

C++ RPC遠端過程呼叫

目的 最近由於摩爾定律已經不太適用,隨著大資料、計算量不斷增加,導致單機處理能力不能滿足需求,所以需要分散式計算,這就需要RPC(遠端過程呼叫),下面簡單介紹一下這個demo,來自於GitHub上的一個專案 client程式碼 #include <stri

Java分散式:RPC遠端過程呼叫

Java分散式:RPC(遠端過程呼叫) 引入RPC   比如我們有一個查詢的介面IDBQuery,以及其實現類DBQueryImp,如果我們執行IDBQuery查詢方法,只需要new一個DBQueryImp然後呼叫request方法即可,這就是本地函式呼叫,因為在同一個地址空間或者同一塊記憶體,通過方法棧

【圖文詳細 】Scala——RPC 遠端過程呼叫

1、RPC 遠端過程呼叫    1.1、RPC 概念  RPC(Remote Procedure Call)—遠端過程呼叫,它是一種通過網路從遠端計算機程式上請 求服務,而不需要了解底層網路技術的協議。RPC 協議假定某些傳輸協議的存在,如 TCP 或

用C程式碼簡要模擬實現一下RPC(遠端過程呼叫)並談談它在程式碼調測中的重要應用

        說明: 本文僅僅是一種模擬的RPC實現, 真正的RPC實現還是稍微有點複雜的。         我們來看看下面這個常見的場景: 在某系統中,我們要對某一函式進行調測, 但是, 很難很難構造出這個函式被呼叫的實際場景, 怎麼辦?         雖然很難構造