目录
介绍
软件描述
服务器基础结构(GrpcServerHelper)
客户基础设施(GrpcClientHelper)
GrpcServer和GrpcClient
运行示例
结论
.NET Core 3.0最重要的新功能之一(现已预发布,预计将于今年晚些时候发布)是对gRPC消息传递的支持。维基百科描述gRPC如下:
gRPC(gRPC远程过程调用)是最初在Google开发的开源远程过程调用(RPC)系统。它使用HTTP / 2进行传输,使用Protocol Buffers作为接口描述语言,并提供身份验证,双向流和流控制,阻塞或非阻塞绑定以及取消和超时等功能。它为许多语言生成跨平台的客户端和服务器绑定。最常见的使用场景包括连接微服务式架构中的服务以及将移动设备,浏览器客户端连接到后端服务。
据说gRPC的“杀手级功能”是对同步全双工流的支持。HTTP / 2协议用作传输协议。协议缓冲区用于有效的序列化。
如上所述,.NET Core 3.0框架支持基于gRPC的通信。Visual Studio 2019提供了gRPC服务的样板代码。但是,此代码仅提供没有消息流的单向通信。该项目是当前工作的出发点。在我的代码中,我尝试为服务器和客户端选择通用代码,并将其与支持使用gRPC的.NET Core 3.0双向消息流的便捷基础结构相结合。
基础结构项目(DLL)GrpcServerHelper和GrpcClientHelper放在Helpers文件夹中。它们可以分别由具体服务器和客户端引用和使用。假设客户端和服务器之间进行全双工gRPC消息交换,开发了辅助DLL。但是对消息结构和处理没有限制。这些功能都取决于具体的服务器和客户端。
gRPC数据和处理在具体服务器和客户端共享的proto文件communication.proto中定义。该文件为客户端到服务器和服务器到客户端消息提供了不同的类型,适当的enum和启动消息交换的CreateStreaming()函数。Visual Studio 2019从proto文件生成C#类。
类GeneralGrpcService
public async Task CreateDuplexStreaming(
IAsyncStreamReader requestStream,
IServerStreamWriter responseStream,
ServerCallContext context)
{
var httpContext = context.GetHttpContext();
Logger.LogInformation($"Connection id: {httpContext.Connection.Id}");
if (!await requestStream.MoveNext())
return;
var clientId = _messageProcessor.GetClientId(requestStream.Current);
Logger.LogInformation($"{clientId} connected");
var subscriber = new SubscribersModel
{
Subscriber = responseStream,
Id = $"{clientId}"
};
_serverGrpcSubscribers.AddSubscriber(subscriber);
do
{
if (requestStream.Current == null)
continue;
var resultMessage = _messageProcessor.Process(requestStream.Current);
if (resultMessage == null)
continue;
await _serverGrpcSubscribers.BroadcastMessageAsync(resultMessage);
} while (await requestStream.MoveNext());
_serverGrpcSubscribers.RemoveSubscriber(subscriber);
Logger.LogInformation($"{clientId} disconnected");
}
类ServerGrpcSubscribersBase
唯有abstract class GrpcClientBase
public async Task Do(
Channel channel,
Action onConnection = null,
Action onShuttingDown = null)
{
using (var duplex = CreateDuplexClient(channel))
{
onConnection?.Invoke();
var responseTask = Task.Run(async () =>
{
while (await duplex.ResponseStream.MoveNext(CancellationToken.None))
Console.WriteLine($"{duplex.ResponseStream.Current}");
});
string payload;
while (!string.IsNullOrEmpty(payload = MessagePayload))
await duplex.RequestStream.WriteAsync(CreateMessage(payload));
await duplex.RequestStream.CompleteAsync();
}
onShuttingDown?.Invoke();
await channel.ShutdownAsync();
}
具体服务器GrpcServer由Visual Studio 2019创建,ASP.MVC Core模板作为gRPC项目。它实现class MessageProcessor : MessageProcessorBase
services.AddSingleton();
services.AddSingleton();
扩展生成Messaging.MessagingBase类型的服务类DuplexService应该映射到方法Startup.Configure()中的端点,如下所示:
app.UseEndpoints(endpoints =>
{
// ...
endpoints.MapGrpcService();
});
服务器和客户端支持加密消息(HTTPS)的交换。就此而言,服务器在其Kestrel配置中使用grpcServer.pfx文件。和客户端使用证书文件certificate.crt。这两个文件都是根据此处提供的指南安装的OpenSSL应用程序创建的。
为了使用Proto Buffer序列化,服务器和客户端共享相同的proto文件communication.proto。该文件定义了流消息服务:
service Messaging
{
rpc CreateStreaming (stream RequestMessage) returns (stream ResponseMessage);
}
请求和响应消息格式以及适当的枚举器。
我没能在Visual Studio中找到一种方法将proto文件包含到服务器和客户端项目中,以确保生成适当的C#代码。所以我在GrpcServer.csproj和GrpcClient.csproj项目文件中手动执行此操作。在这些文件中,我添加了标记为的注释部分。
要运行该示例,请构建整个解决方案(这也将导致从proto文件生成类)。然后用...运行GrpcServer
dotnet GrpcServer.dll
......命令及其完全启动后,继续执行一个或多个......
dotnet GrpcClient.dll
...命令。
在客户端控制台中,键入一些以Enter结尾的消息。服务器将接收和处理该消息(处理代码的位置在方法MessageProcessor.Process()中保留,可以看到适当的注释)。如果您的消息包含问号?,则服务器会向其所有当前订户广播响应消息。客户端在其控制台中输出响应。
这项工作为使用gRPC程序的.NET 3.0同步双向消息流提供了基础设施。使用此基础结构可将具体服务器和客户端的代码减少到几行代码。
原文地址:https://www.codeproject.com/Articles/5163307/Bidirectional-Messages-Streaming-with-NET-Core-3-0