使用 gRPC 重試的暫時性錯誤處理
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
gRPC 重試這項功能,可讓 gRPC 用戶端自動重試失敗的呼叫。 本文討論如何設定重試原則,以在 .NET 中建立復原性、容錯的 gRPC 應用程式。
gRPC 重試需要 Grpc.Net.Client 2.36.0 版或更新版本。
暫時性錯誤處理
gRPC 呼叫可能會因暫時性錯誤而中斷。 暫時性錯誤包括:
- 暫時失去網路連線。
- 暫時無法使用服務。
- 因伺服器載入而逾時。
當 gRPC 呼叫中斷時,用戶端會擲回 RpcException
,以及錯誤的詳細資料。 用戶端應用程式必須攔截例外狀況,並選擇如何處理錯誤。
var client = new Greeter.GreeterClient(channel);
try
{
var response = await client.SayHelloAsync(
new HelloRequest { Name = ".NET" });
Console.WriteLine("From server: " + response.Message);
}
catch (RpcException ex)
{
// Write logic to inspect the error and retry
// if the error is from a transient fault.
}
在應用程式各處複製重試邏輯的過程,非常詳細繁瑣且容易出錯。 幸運的是,.NET gRPC 用戶端有內建支援自動重試功能。
設定 gRPC 重試原則
建立 gRPC 通道時,會設定一次重試原則:
var defaultMethodConfig = new MethodConfig
{
Names = { MethodName.Default },
RetryPolicy = new RetryPolicy
{
MaxAttempts = 5,
InitialBackoff = TimeSpan.FromSeconds(1),
MaxBackoff = TimeSpan.FromSeconds(5),
BackoffMultiplier = 1.5,
RetryableStatusCodes = { StatusCode.Unavailable }
}
};
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});
上述 程式碼:
- 建立
MethodConfig
。 您可以設定每個方法的重試原則,並使用Names
屬性來比對方法。 這個方法已設定MethodName.Default
,因此會套用至這個通道所呼叫的所有 gRPC 方法。 - 設定重試原則。 這個原則會指示用戶端自動重試已失敗且狀態碼為
Unavailable
的 gRPC 呼叫。 - 藉由設定
GrpcChannelOptions.ServiceConfig
,將建立的通道設定為使用重試原則。
使用通道建立的 gRPC 用戶端會自動重試失敗的呼叫:
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
new HelloRequest { Name = ".NET" });
Console.WriteLine("From server: " + response.Message);
重試有效時機
系統會在下列情況下重試呼叫:
- 失敗的狀態碼符合
RetryableStatusCodes
中的值。 - 先前的嘗試次數少於
MaxAttempts
。 - 尚未認可呼叫。
- 尚未超過期限。
gRPC 呼叫會在兩種情境中認可:
- 用戶端收到回應標頭。 呼叫
ServerCallContext.WriteResponseHeadersAsync
時,或當第一則訊息寫入伺服器回應資料流時,伺服器會傳送回應標頭。 - 用戶端的外寄訊息 (若為串流,則為多則訊息) 已超過用戶端的緩衝區大小上限。
MaxRetryBufferSize
和MaxRetryBufferPerCallSize
是在 通道上設定 。
不論狀態碼或先前的嘗試次數為何,都不會重試已認可的呼叫。
串流呼叫
串流呼叫可以搭配 gRPC 重試使用,但合併使用時有重要的考慮事項:
- 伺服器串流、雙向串流:從伺服器傳回多則訊息的串流 RPC 在收到第一則訊息之後,將不會進行重試。 應用程式必須新增額外的邏輯,才能手動重新建立伺服器串流呼叫和雙向串流呼叫。
- 用戶端串流、雙向串流:如果傳出的訊息已超過用戶端的緩衝區大小上限,則傳送多則訊息至伺服器的串流 RPC 將不會進行重試。 可以透過組態增加緩衝區大小上限。
如需詳細資訊,請參閱重試有效時機。
重試輪詢延遲
各次重試嘗試之間的輪詢延遲,是使用 InitialBackoff
、MaxBackoff
和 BackoffMultiplier
來設定。 如需每個選項的詳細資訊,請參閱 gRPC 重試選項一節。
各次重試嘗試之間的實際延遲會隨機化。 介於 0 到目前輪詢之間的隨機延遲,會決定下次進行重試嘗試的時間。 請考慮即使已設定指數輪詢,增加各次嘗試之間的目前輪詢,各次嘗試之間的實際延遲並不一定都會變長。 系統將延遲隨機化,以防止多個呼叫的重試會叢集在一起,且可能造成伺服器多載。
使用中繼資料偵測重試
可以透過 grpc-previous-rpc-attempts
中繼資料的存在來偵測 gRPC 重試。 grpc-previous-rpc-attempts
中繼資料:
- 會自動新增至重試的呼叫,並傳送至伺服器。
- 值代表先前重試嘗試的數目。
- 值一律為整數。
請考慮下列重試情節:
- 用戶端對伺服器進行 gRPC 呼叫。
- 伺服器失敗並傳回可重試的狀態碼回應。
- 用戶端重試 gRPC 呼叫。 因為先前曾嘗試過一次,所以
grpc-previous-rpc-attempts
中繼資料的值是1
。 中繼資料會隨著重試傳送至伺服器。 - 伺服器成功並傳回 OK。
- 用戶端回報成功。
grpc-previous-rpc-attempts
位於回應的中繼資料,且值為1
。
初始 gRPC 呼叫上沒有 grpc-previous-rpc-attempts
中繼資料,第一次重試時為 1
、第二次重試為 2
,依此類推。
gRPC 重試選項
下表描述設定 gRPC 重試原則的選項:
選項 | 描述 |
---|---|
MaxAttempts |
呼叫嘗試次數上限,包括原始嘗試。 此值會受到 GrpcChannelOptions.MaxRetryAttempts 限制,預設值為 5。 此為必要的值,而且必須大於 1。 |
InitialBackoff |
各次重試嘗試之間的初始輪詢延遲。 介於 0 到目前輪詢之間的隨機延遲,會決定下次進行重試嘗試的時間。 每次嘗試之後,目前的輪詢都會乘以 BackoffMultiplier 。 此為必要的值,而且必須大於零。 |
MaxBackoff |
最大輪詢會對指數輪詢成長設定上限。 此為必要的值,而且必須大於零。 |
BackoffMultiplier |
每次重試嘗試之後,輪詢都會乘上這個值,並且當乘數大於 1 時,會以指數方式成長。 此為必要的值,而且必須大於零。 |
RetryableStatusCodes |
狀態碼的集合。 系統會自動重試在失敗時狀態相符的 gRPC 呼叫。 如需狀態碼的詳細資訊,請參閱狀態碼及其在 gRPC 中的使用。 至少需要一個可重試的狀態碼。 |
對沖
對沖是替代的重試策略。 對沖可讓您主動傳送單一 gRPC 呼叫的多個複本,而不需要等待回應。 對沖的 gRPC 呼叫可能會在伺服器上多次執行,而系統會使用第一個成功的結果。 請務必只針對能安全多次執行而不會產生負面影響的方法啟用對沖。
與重試相比,對沖的優缺點如下:
- 對沖的優點是,可能會較快傳回成功的結果。 它允許系統同時呼叫多個 gRPC,並在得到第一個成功的結果時完成。
- 對沖的缺點是可能造成浪費。 可能進行多次呼叫,且全數成功。 只有第一個結果獲得採用,而 rest 遭到捨棄。
設定 gRPC 對沖原則
對沖原則的設定類似於重試原則。 請注意,對沖原則無法與重試原則結合。
var defaultMethodConfig = new MethodConfig
{
Names = { MethodName.Default },
HedgingPolicy = new HedgingPolicy
{
MaxAttempts = 5,
NonFatalStatusCodes = { StatusCode.Unavailable }
}
};
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});
gRPC 對沖選項
下表描述設定 gRPC 對沖原則的選項:
選項 | 描述 |
---|---|
MaxAttempts |
對沖原則所傳送的呼叫數目最大值。 MaxAttempts 代表所有嘗試的總數,包括原始嘗試在內。 此值會受到 GrpcChannelOptions.MaxRetryAttempts 限制,預設值為 5。 此為必要的值,而且必須大於或等於 2。 |
HedgingDelay |
系統會立即傳送第一個呼叫,後續的對沖呼叫則依據這個值加以延遲。 當延遲設定為零或 null 時,系統會立即傳送所有對沖呼叫。 HedgingDelay 是選擇項,預設值為零。 此值必須大於或等於零。 |
NonFatalStatusCodes |
狀態碼的集合,表示其他對沖呼叫仍然可能成功。 如果伺服器傳回不嚴重的狀態碼,系統會繼續執行對沖呼叫。 否則,系統會取消等待處理的要求,並將錯誤傳回給應用程式。 如需狀態碼的詳細資訊,請參閱狀態碼及其在 gRPC 中的使用。 |