gRPC由Google發起的系統,基於HTTP/2協定傳輸,使用ProtocolButters為介面描述語言,在Microsoft Docs有一篇針對gRPC與HttpApi的比較表,接著加上Server端以及Client的使用方式
Server
Nuget
dotnet add package Grpc.AspNetCore
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
建立資料夾 “Protos”,以及新增檔案 hello.proto
syntax = "proto3";
option csharp_namespace = "GrpcServiceSample.Core";
package hello;
service Hello {
rpc HelloWorld (HelloWorldRequest) returns (HelloWorldResponse);
}
message HelloWorldRequest {
string name = 1;
}
message HelloWorldResponse {
string message = 1;
}
編譯後會在 “obj” 底下產生對應的程式碼
實作 gRPC 服務的邏輯
public class GreeterService : Hello.HelloBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
public override Task<HelloWorldResponse> HelloWorld(HelloWorldRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloWorldResponse()
{
Message = "Hello World! " + request.Name
});
}
}
Client
Nuget
dotnet add package Google.Protobuf
dotnet add package Grpc.Net.Client
dotnet add package Grpc.Tools
把 Server 內定義的 hello.proto 直接copy過去
調整一下 .csproj,主要要把 GrpcServices 改成 Client
<ItemGroup>
<Protobuf Include="Protos\hello.proto" GrpcServices="Client" />
</ItemGroup>
編譯後也會在 obj 底下產生對應的程式碼
呼叫 gRPC 服務
[HttpGet]
public async Task<string> Get()
{
var channel = GrpcChannel.ForAddress("http://localhost:5000");
var client = new Hello.HelloClient(channel);
var response = await client.HelloWorldAsync(new HelloWorldRequest
{
Name = "Test"
});
return response.Message;
}
把Server跟Client都跑起來,理應可以正常呼叫服務
把 gRPC 服務透過DI注入
Nuget
dotnet add package Grpc.Net.ClientFactory
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddGrpcClient<Hello.HelloClient>(options =>
{
options.Address = new Uri("http://localhost:5000");
});
}
使用端
private readonly Hello.HelloClient _client;
public WeatherForecastController(Hello.HelloClient client)
{
_client = client;
}
[HttpGet]
public async Task<string> Get()
{
var response = await _client.HelloWorldAsync(new HelloWorldRequest
{
Name = "Test"
});
return response.Message;
}
不支援 HTTP/2 的 Server
若執行端不支援 HTTP/2,運行 Server 端時會出現Exception,在 Microsoft Docs 有提供解決方案
HTTP/2 over TLS is not supported on macOS due to missing ALPN support.) (HTTP/2 over TLS is not supported on macOS due to missing ALPN support.
Server端
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
options.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2);
});
webBuilder.UseStartup<Startup>();
});
}
Client端則是在呼叫服務前加上
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
比較 gRPC 服務與 HTTP API
搭配 ASP.NET Core 的 gRPC 服務
針對 .NET Core 上的 gRPC 進行疑難排解
Sample Code
Server
Nuget
dotnet add package Grpc.AspNetCore
Startup
public void ConfigureServices(IServiceCollection services) { services.AddGrpc(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGrpcService<GreeterService>(); }); }
建立資料夾 “Protos”,以及新增檔案 hello.proto
// hello.proto // 使用proto3 syntax = "proto3"; // namespace option csharp_namespace = "GrpcServiceSample.Core"; // package package hello; // 定義方法 request and response service Hello { rpc HelloWorld (HelloWorldRequest) returns (HelloWorldResponse); } // 下面定義 dto message HelloWorldRequest { string name = 1; } message HelloWorldResponse { string message = 1; }
編譯後會在 “obj” 底下產生對應的程式碼
實作 gRPC 服務的邏輯
public class GreeterService : Hello.HelloBase { private readonly ILogger<GreeterService> _logger; public GreeterService(ILogger<GreeterService> logger) { _logger = logger; } public override Task<HelloWorldResponse> HelloWorld(HelloWorldRequest request, ServerCallContext context) { return Task.FromResult(new HelloWorldResponse() { Message = "Hello World! " + request.Name }); } }
Client
Nuget
把 Server 內定義的 hello.proto 直接copy過去
調整一下 .csproj,主要要把 GrpcServices 改成 Client
<ItemGroup> <Protobuf Include="Protos\hello.proto" GrpcServices="Client" /> </ItemGroup>
編譯後也會在 obj 底下產生對應的程式碼
呼叫 gRPC 服務
[HttpGet] public async Task<string> Get() { var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Hello.HelloClient(channel); var response = await client.HelloWorldAsync(new HelloWorldRequest { Name = "Test" }); return response.Message; }
把Server跟Client都跑起來,理應可以正常呼叫服務
把 gRPC 服務透過DI注入
Nuget
dotnet add package Grpc.Net.ClientFactory
Startup
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddGrpcClient<Hello.HelloClient>(options => { options.Address = new Uri("http://localhost:5000"); }); }
使用端
private readonly Hello.HelloClient _client; public WeatherForecastController(Hello.HelloClient client) { _client = client; } [HttpGet] public async Task<string> Get() { var response = await _client.HelloWorldAsync(new HelloWorldRequest { Name = "Test" }); return response.Message; }
不支援 HTTP/2 的 Server
若執行端不支援 HTTP/2,運行 Server 端時會出現Exception,在 Microsoft Docs 有提供解決方案
Server端
public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureKestrel(options => { options.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2); }); webBuilder.UseStartup<Startup>(); }); }
Client端則是在呼叫服務前加上
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
比較 gRPC 服務與 HTTP API
搭配 ASP.NET Core 的 gRPC 服務
針對 .NET Core 上的 gRPC 進行疑難排解
Sample Code