Git 源码 :https://github.com/tangsong1995/TS.Microservices
CSDN 资源 :https://download.csdn.net/download/qq_33649351/34675095
系列文章目录 :https://blog.csdn.net/qq_33649351/article/details/120998558
gRPC 是一个远程过程调用框架,由 Google 公司发起并开源。它可以让我们像在调用本地的类一样调用远程的服务。
.NET 对 gRPC 进行了很好的支持,具体如下:
gRPC 服务端核心包:
gRPC 客户端核心包:
定义 order.proto 文件,内容如下:
syntax = "proto3";
option csharp_namespace = "GrpcServices";
package GrpcServices;
service OrderGrpc {
rpc CreateOrder(CreateOrderCommand) returns (CreateOrderResult);
}
message CreateOrderCommand {
string buyerId = 1;
int32 productId = 2;
double unitPrice = 3;
double discount = 4;
int32 units = 5;
}
message CreateOrderResult {
int32 orderId = 1;
}
syntax 指定版本为 proto3 。
option csharp_namespace 指定命名空间为 GrpcServices 。
package 指定包为 GrpcServices 。
service 定义服务,定义方法。
message 定义消息,如上使用 message 定义了 CreateOrder 方法的入参及出参。需要注意定义参数的顺序,因为 gRPC 使用 Protocol Buffers 序列化,参数定义的顺序就决定了序列化时的顺序。
引用包:Grpc.AspNetCore。
编辑 .csproj 项目文件:
<ItemGroup>
<Protobuf Include="Proto\order.proto" GrpcServices="Server" />
ItemGroup>
在生成项目时,会生成相应的类,并且会将相关代码编译到 dll 内:
添加 OrderService 继承 OrderGrpc.OrderGrpcBase 实现业务逻辑:
public class OrderService : OrderGrpc.OrderGrpcBase
{
public override Task<CreateOrderResult> CreateOrder(CreateOrderCommand request, ServerCallContext context)
{
// do sth. save order
return Task.FromResult(new CreateOrderResult { OrderId = 1 });
}
}
在 Startup 中进行注册:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc(options =>
{
options.EnableDetailedErrors = true; // 开启错误详细信息,生成环境不应该启用
});
}
定义 OrderService 的 Endpoints :
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<OrderService>();
endpoints.MapControllers();
});
}
引用包:Grpc.AspNetCore 。
将服务端的 .proto 文件文件引入到客户端:
<ItemGroup>
<Protobuf Include="..\GrpcServer\Proto\order.proto" Link="Protos\order.proto" />
ItemGroup>
在 Startup 中进行注册,并指定服务端的请求地址:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpcClient<OrderGrpc.OrderGrpcClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
});
}
调用服务端:
public class TestController : ControllerBase
{
private readonly OrderGrpcClient _orderGrpcClient;
public TestController(OrderGrpcClient orderGrpcClient)
{
_orderGrpcClient = orderGrpcClient;
}
[HttpGet]
public async Task<CreateOrderResult> Test()
{
var result = await _orderGrpcClient.CreateOrderAsync(new GrpcServices.CreateOrderCommand() { BuyerId = "test" });
return result;
}
}
服务端增加对 HTTP2 的监听端口:
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://+:5000"
},
"Https": {
"Url": "https://+:5001"
},
"Http2": {
"Url": "http://+:5002",
"Protocols": "Http2"
}
}
}
客户端允许使用不加密的HTTP/2协议:
public void ConfigureServices(IServiceCollection services)
{
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //允许使用不加密的HTTP/2协议
}
使用 AddGrpcClient 注册时,注册对应监听了 Http2 的请求地址:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpcClient<OrderGrpc.OrderGrpcClient>(options =>
{
options.Address = new Uri("http://localhost:5002");
});
}
创建异常拦截器类继承 Interceptor :
public class ExceptionInterceptor : Interceptor
{
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
{
try
{
return await base.UnaryServerHandler(request, context, continuation);
}
catch (Exception ex)
{
var data = new Metadata();
data.Add("message", ex.Message);
throw new RpcException(new Status(StatusCode.Unknown, "Unknon"), data);
}
}
}
注册 gRPC 时添加此异常拦截器 :
services.AddGrpc(options =>
{
options.EnableDetailedErrors = true; // 开启错误详细信息,生成环境不应该启用
options.Interceptors.Add<ExceptionInterceptor>();
});
打开 cmd 输入以下命令安装 dotnet-grpc :
dotnet tool install dotnet-grpc -g
安装后需要重启VS。
将目录定位到工作目录:
dotnet-grpc 的命令主要有以下四个:
使用 dotnet grpc add-file 添加:
dotnet grpc add-file ..\GrpcServer\Proto\order.proto
使用 dotnet grpc add-url 添加服务器文件:
dotnet grpc add-url https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto -o Protos\helloworld.proto
使用 dotnet grpc remove 移除文件:
dotnet grpc remove https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto