RPC 呼叫完成之後,不會關閉連線;它標示為免費。 因此,伺服器可能會當機或失去網路連接,可能發生在通話期間或之間,當連線停留在集區中時。 就原則而言,只有在符合下列兩個條件時,RPC 運行時間才會重新嘗試這些呼叫:
- 伺服器無法執行呼叫,或呼叫是具冪等性。
- 用戶端可以以高效效能的方式實作重試。
下列段落會展開並釐清這兩個條件。
等冪呼叫是在伺服器上可以多次執行的呼叫,而不會產生不想要的副作用。 例如,在銀行中查詢指定帳戶餘額的 RPC 呼叫具有等冪性。 如果因為連線中斷而執行此呼叫兩次,則不會造成任何傷害。 另一個等冪呼叫範例是變更資料庫中客戶的位址。 執行兩次沒問題,因為第二次執行只會以相同的位址取代已經目前的位址。 「從帳戶 xyz 減去五十美元」這類操作不是冪等的。 網路連線中斷不應造成這類呼叫的多次執行。
出於安全考量,RPC 執行時期會將所有呼叫視為非等冪操作。 ncacn_ip_tcp不支援 [等冪] 屬性,而且會被忽略。 因此,前述清單中的第一個條件簡化為無法執行呼叫的伺服器 。
在許多情況下,RPC 執行環境無法明確判定呼叫是否已在伺服器上執行過。 在這種情況下,用戶端將不會重試執行呼叫。
下列範例說明 RPC 執行階段時期何時會重試呼叫以及何時不會:
伺服器重新啟動。
重新啟動後,在之前未進行呼叫的介面上,進行了一次無安全性 RPC 呼叫。 由於此介面上沒有呼叫,RPC 執行階段會首先嘗試協商使用此介面。 它會使用集區中的連線來傳送封包。 由於伺服器重新啟動,且連線不再有效,因此會傳回錯誤。 由於用戶端 RPC 執行時間尚未開始傳送實際呼叫的數據,因此用戶端會判斷伺服器可能無法在這些數據上執行。 因此,它會關閉連線,並在集區中尋找另一個連線。 如果找不到連線,則會開啟新的連線,並嘗試再次交涉使用 介面。 如果成功,就會進行呼叫(也就是說,因為在呼叫啟動之前就偵測到了失敗,所以進行重試)。
具隱私層級安全性(加密)的 RPC 呼叫是在已協商的安全性上下文的連線上進行。
為了確保高效能,RPC 執行時會將封送處理包內嵌加密(透過明文數據)。 如果嘗試傳送數據失敗,RPC 運行時間就無法重試呼叫,因為純文本數據已被加密的數據覆寫,而且無法以新的安全性內容重新加密數據。 因此,不會重試。
傳送非第一個資料片段會失敗。
不會重試,因為 RPC 運行時間可能會選擇在完成之後捨棄第一個片段的內容,而且無法重試傳送第一個片段。
RPC 要求已傳送。
伺服器中止連接。 未嘗試重試,因為 RPC 無法辨別伺服器是否收到呼叫並開始執行它。
如果伺服器使用動態端點,RPC 將不會在重試期間重新解析端點。 這表示如果伺服器被關閉後重新啟動,它可能會在不同的端點上,而在重試呼叫時,RPC 不會自動重新解析端點。 若要強制重新解析端點,RPC 用戶端應該先呼叫 RpcBindingReset,再重試呼叫。
在這些案例中,如果 RPC 用戶端可以判斷呼叫是否具有等冪性,或者如果它保留 RPC 捨棄的數據,它可能會選擇在 RPC 之上建立重試機制。
注意
如果伺服器是叢集,且叢集的不同節點會執行不同版本的伺服器軟體,則 RPC 重試可能會在故障轉移時將呼叫登陸叢集的不同節點上,而且可能位於不同版本的伺服器上。 在這類部署案例中,請確定用戶端不會依賴特定版本的伺服器軟體來執行指定的呼叫。 如果這樣做,客戶端應該在 RPC 之上建置機制,以偵測並處理這類條件。