出于各種原因,多年來,我作業的公司在使用 Windows Communication Foundation (WCF) 方面投入了大量資金。我們目前正在將我們的主要開發平臺從 Visual Studio 2015 升級到 Visual Studio 2022。遺憾的是,我們發現我們的 WCF 客戶端和服務器應用程式需要比我們預期的更多作業才能將它們升級到 Visual Studio 2022 和更新的 .NET構架; 他們肯定不像以前那樣圓滑。我們計劃保留使用 WCF 的現有應用程式,但正在考慮新應用程式的其他選項。似乎被推動的主要選項是 gRpc,但是,從我到目前為止所了解的情況來看,對于我們想要做的某些事情,它似乎是一個非常糟糕的替代品。
- 函式呼叫的一種方式(即只要我們知道已交付的呼叫,我們就不需要等到它完成)。我知道這可以通過 gRpc 實作。
- 完全雙向通信(即客戶端可以呼叫服務器,也可以反過來;服務器可以呼叫客戶端)。我知道使用“流”這可以近似于 gRPC,但并不容易。
為了進行說明,請考慮一個涉及三種應用程式型別的簡化場景:
- 聲音請求者。請求在不同位置播放不同聲音并更改聲音引數的應用程式。
- 聲音播放器。可以播放請求的聲音并更改其引數的應用程式。它可以發出聲音結束的通知。
- 聲音處理器代理。位于聲音請求者和聲音播放器之間的應用程式。
我們的 WCF 實作將聲音處理程式代理作為 WCF 服務器,聲音請求器和聲音播放器應用程式是連接到服務器的客戶端。這很適合我們;代理不需要知道連接到哪些玩家和請求者,他們連接到它(并且可以隨時這樣做)。代理僅提供“編組”服務。下面是一個簡化的序列圖,用于說明可以進行的呼叫型別:
我的問題是“如果使用 gRpc 實作這個,我們將如何實作對 SoundPlayer 的呼叫(例如 CreateSound、PlaySound 等)?” 如果我的理解是正確的,因為 SoundPlayer 是一個客戶端(而不是服務器),我們需要將這些實作為從播放器到服務器的呼叫“回傳”的流。有沒有更簡單的方法?(我很高興我們可以讓 SoundPlayer 成為 SoundHandlerProxy 可以作為客戶端連接的服務器——但這意味著代理需要知道它要連接的所有播放器,這是我們寧愿避免的。)或者,除了 gRpc 之外,還有其他我們可以遷移到的東西嗎(最好是至少在未來十年內會保持穩定的東西)?
uj5u.com熱心網友回復:
我不是 .Net 專家,所以我可能會弄錯一些細節。但我認為主旨是正確的。
單向服務在線上并不是那么有趣,因為它們仍然使用 HTTP 請求/回應。來自單向樣本
呼叫操作時,服務會在服務操作執行之前回傳 HTTP 狀態代碼 202... 呼叫操作的客戶端會阻塞,直到收到來自服務的 202 回應。
因此,它們更像是一個存根功能,可以在 gRPC 中輕松模擬。在 gRPC 中,您將定義 return 的方法google.protobuf.Empty
,并在服務器端在另一個執行緒中開始長時間運行的作業并立即回傳。
service Foo {
rpc Bar(BarRequest) returns (google.protobuf.Empty);
}
public class FooService : Foo.FooBase
{
public override Task<Empty> Bar(BarRequest request,
ServerCallContext context)
{
startProcessingInAnotherThread(request);
return Task.FromResult(new Empty {});
}
}
全雙向通信似乎與Duplex Services相同。這些通過配置客戶端以了解服務器如何到達它(它的主機:埠)來作業。然后客戶端將該資訊發送到服務器,以便服務器將來將 RPC 發回給它。這種設計肯定會對安全產生影響,您應該查看您正在使用的安全模型。
這將通過客戶端在 gRPC 中模擬,只需向服務器發送一個通道地址字串,然后服務器創建一個到該地址的通道。
service SoundHandler {
rpc Connect(ConnectRequest) returns (google.protobuf.Empty);
}
message ConnectRequest {
enum Type {
TYPE_UNKNOWN = 0;
TYPE_SOUND_REQUESTER = 1;
TYPE_SOUND_PLAYER = 2;
};
string channelAddress = 1;
Type type = 2;
}
service SoundPlayer {
rpc CreateSound(CreateSoundRequest) returns (CreateSoundResponse);
// ...
}
service SoundEventReceiver {
rpc SoundFinished(SoundFinishedRequest) returns (SoundFinishedResponse);
}
然后,在服務中,您將創建一個到所提供地址的通道以進行回呼。
public class SoundHandlerService : SoundHandler.SoundHandlerBase
{
public override Task<Empty> Bar(ConnectRequest request,
ServerCallContext context)
{
var channel = GrpcChannel.ForAddress(request.channelAddress);
if (request.type == TYPE_SOUND_PLAYER) {
var channel = GrpcChannel.ForAddress(request.channelAddress);
var client = new SoundPlayer.SoundPlayerClient(channel);
registerSoundPlayer(channel, client);
} // ...
return Task.FromResult(new Empty {});
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/534772.html
標籤:C#wcfgrpc