dabaoge 2020-01-25
ä¸.ç®ä»
gRPC æ¯ä¸ä¸ªç±Google弿ºçï¼è·¨è¯è¨çï¼é«æ§è½çè¿ç¨è¿ç¨è°ç¨ï¼RPCï¼æ¡æ¶ã gRPC使客æ·ç«¯åæå¡ç«¯åºç¨ç¨åºå¯ä»¥éæå°è¿è¡éä¿¡ï¼å¹¶ç®åäºè¿æ¥ç³»ç»çæå»ºãå®ä½¿ç¨HTTP/2ä½ä¸ºéä¿¡åè®®ï¼ä½¿ç¨ Protocol Buffers ä½ä¸ºåºåååè®®ã
å®ç主è¦ä¼ç¹ï¼
è¿äºä¼ç¹ä½¿gRPCé常éåï¼
ä¸å»ºè®®ä½¿ç¨gRPCçåºæ¯ï¼
æ¯æçè¯è¨å¦ä¸ï¼

äº.gRPC on .NET Core
gRPC ç°å¨å¯ä»¥é常ç®åçå¨ .NET Core å ASP.NET Core ä¸ä½¿ç¨ï¼å¨ .NET Core ä¸çå®ç°ç弿ºå°åï¼https://github.com/grpc/grpc-dotnet ï¼å®ç®åç±å¾®è½¯å®æ¹ ASP.NET 项ç®ç人åè¿è¡ç»´æ¤ï¼è¯å¥½çæ¥å¥ .NET Core çæã
.NET Core ç gRPC åè½å¦ä¸ï¼
HttpClientFactoryï¼å许对gRPC客æ·ç«¯è¿è¡éä¸éç½®ï¼å¹¶ä½¿ç¨DI注å¥å°åºç¨ç¨åºä¸ä¸.ä½¿ç¨ ASP.NET Core å建 gRPC æå¡
éè¿ Visual Studio 2019 ï¼16.3.0ï¼æä¾ç模æ¿ï¼å¯ä»¥å¿«éå建 gRPC æå¡ã

æ¥ææä¸ä¸é»è®¤æºç åå«äºä»ä¹ä¸ä¸ã
â éç½®æä»¶ appsettings.json ï¼å¤äºKestrel å¯ç¨ HTTP/2 çéç½®ï¼å 为 gRPC æ¯åºäº HTTP/2 æ¥éä¿¡ç

â¡ PBåè®®æä»¶ greet.proto ç¨äºèªå¨çææå¡ã客æ·ç«¯åæ¶æ¯ï¼è¡¨ç¤ºä¼ éçæ°æ®ï¼çC# Class

⢠æå¡ç±» GreeterService ï¼æå¡ç±»éæç Greeter.GreeterBase æ¥èªäºæ ¹æ®protoæä»¶èªå¨çæçï¼çæçç±»å¨ obj\Debug\netcoreapp3.0ç®å½ä¸

èªå¨çæçç±»ï¼

⣠Startup.csç±»ï¼å° gRPCæå¡æ·»å å°äºç»ç»ç¹è·¯ç±ä¸

⤠csproj é¡¹ç®æä»¶ï¼åå«äº proto æä»¶å¼ç¨

2.è¿è¡
ç¬¬ä¸æ¬¡è¿è¡ä¼æç¤ºæ¯å¦ä¿¡ä»»è¯ä¹¦ï¼ç¹å»âæ¯â


è¿æ¯å 为HTTP/2éè¦HTTPSï¼å°½ç®¡HTTP/2å议没ææç¡®è§å®éè¦HTTPSï¼ä½æ¯ä¸ºäºå®å¨å¨æµè§å¨å®ç°ä¸é½è¦æ±äºHTTPSï¼æä»¥ç°å¨çHTTP/2åHTTPSåºæ¬é½æ¯ä¸å¯¹ã

å. å建 gRPC 客æ·ç«¯
1.æ·»å ä¸ä¸ª.NET Core æ§å¶å°åºç¨ç¨åº
2.éè¿nugetæ·»å åï¼Grpc.Net.ClientãGoogle.ProtobufãGrpc.Tools

3.å°æå¡ç proto æä»¶å¤å¶å°å®¢æ·ç«¯

4.ç¼è¾å®¢æ·ç«¯é¡¹ç®æä»¶ï¼æ·»å å³äºprotoæä»¶çæè¿°
<ItemGroup> <Protobuf Include="Protos\greet.proto" GrpcServices="Client" /> </ItemGroup>
注æ GrpcServices="Client" è¿éæ¯Clientåæå¡æ¯ä¸ä¸æ ·ç
5.çæå®¢æ·ç«¯é¡¹ç®å¯ä»¥éè¿protoæä»¶çæç±»
6.æ·»å 客æ·ç«¯è°ç¨ä»£ç
static async Task Main(string[] args)
{
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "ææ¨" });
Console.WriteLine("Greeter æå¡è¿åæ°æ®: " + reply.Message);
Console.ReadKey();
}7.åå¯å¨æå¡ï¼ç¶åè¿è¡å®¢æ·ç«¯

è¿éå¯ä»¥çå°ï¼å®¢æ·ç«¯æåè°ç¨äºæå¡ï¼æ¶å°äºè¿åçæ¶æ¯ã
äº.èªå·±å¨æåä¸ä¸ªæå¡
åé¢æä»¬ä½¿ç¨ç Greeter æå¡æ¯ç±æ¨¡æ¿èªå¨ç»æä»¬å建çï¼ç°å¨æä»¬æ¥èªå·±å¨æåä¸ä¸ªæå¡ã
1.å®ä¹ proto æä»¶ LuCat.protoï¼å¹¶å¨csprojé¡¹ç®æä»¶ä¸æ·»å æè¿°
syntax = "proto3";
option csharp_namespace = "AspNetCoregRpcService";
import "google/protobuf/empty.proto";
package LuCat; //å®ä¹åå
//å®ä¹æå¡
service LuCat{
//å®ä¹å¸ç«æ¹æ³
rpc SuckingCat(google.protobuf.Empty) returns(SuckingCatResult);
}
message SuckingCatResult{
string message=1;
}2.å®ç°æå¡ LuCatService.cs
public class LuCatService:LuCat.LuCatBase
{
private static readonly List<string> Cats=new List<string>(){"è±çé¶æ¸å±","è±ç鿏å±","ç¾ç","èç«","ç¸è±ç«","æ©ç«"};
private static readonly Random Rand=new Random(DateTime.Now.Millisecond);
public override Task<SuckingCatResult> SuckingCat(Empty request, ServerCallContext context)
{
return Task.FromResult(new SuckingCatResult()
{
Message = $"æ¨å¸äºä¸åª{Cats[Rand.Next(0, Cats.Count)]}"
});
}
}3.å¨ Startupç»ç»ç¹è·¯ç±ä¸æ³¨å
endpoints.MapGrpcService<LuCatService>();
4.æ·»å 客æ·ç«¯è°ç¨
var catClient = new LuCat.LuCatClient(channel);
var catReply = await catClient.SuckingCatAsync(new Empty());
Console.WriteLine("è°ç¨æ¸ç«æå¡ï¼"+ catReply.Message);5.è¿è¡æµè¯

å.å®é使ç¨ä¸çæå·§
æå·§1
ä¸é¢ç« èçæä½æ¥éª¤ä¸ï¼æä»¬éè¦å¨æå¡å客æ·ç«¯ä¹é´å¤å¶protoï¼è¿æ¯ä¸ä¸ªå¯ä»¥çç¥æçæ¥éª¤ã
1.å¤å¶ Protos æä»¶å¤¹å°è§£å³æ¹æ¡æ ¹ç®å½ï¼slnæä»¶æå¨ç®å½ï¼

2.å é¤å®¢æ·ç«¯åæå¡é¡¹ç®ä¸ç Protos æä»¶å¤¹
3.å¨å®¢æ·ç«¯é¡¹ç®æä»¶csproj䏿·»å å³äºprotoæä»¶çæè¿°
<ItemGroup> <Protobuf Include="..\..\Protos\greet.proto" GrpcServices="Client" Link="Protos\greet.proto" /> </ItemGroup>
4.卿å¡é¡¹ç®æä»¶csproj䏿·»å å³äºprotoæä»¶çæè¿°
<ItemGroup> <Protobuf Include="..\..\Protos\greet.proto" GrpcServices="Server" Link="Protos\greet.proto" /> </ItemGroup>
å¨å®é项ç®ä¸ï¼è¯·èªå·±è®¡ç®ç¸å¯¹è·¯å¾
5.è¿æ ·ä¸¤ä¸ªé¡¹ç®é½æ¯ä½¿ç¨çä¸ä¸ªprotoæä»¶ï¼åªç¨ç»´æ¤è¿ä¸ä¸ªæä»¶å³å¯

æå·§2
æä»¬å¨å®é项ç®ä¸ä½¿ç¨ï¼è¯å®æå¤ä¸ª proto æä»¶ï¼é¾éæä»¬æ¯æ·»å ä¸ä¸ª proto æä»¶é½è¦å»æ´æ° csprojæä»¶ï¼
æä»¬å¯ä»¥ä½¿ç¨MSBuildå鿥叮æä»¬å®æï¼æä»¬å° csproj é¡¹ç®æä»¶ä¸å¼å¥protoæä»¶ä¿¡æ¯è¿è¡ä¿®æ¹ã
æå¡ç«¯ï¼
<ItemGroup> <Protobuf Include="..\..\Protos\*.proto" GrpcServices="Server" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup>
客æ·ç«¯ï¼
<ItemGroup> <Protobuf Include="..\..\Protos\*.proto" GrpcServices="Client" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup>
示ä¾ï¼

ä¸.æ»ç»
gRPC ç°ç®åæ¯ä¸æ¬¾é常æçç髿§è½RPCæ¡æ¶ï¼å½åççææ¯é常好çï¼å¾å¤å¬å¸ç产åæè弿ºé¡¹ç®é½æå¨ä½¿ç¨gRPCï¼æäºå®ï¼ç¸ä¿¡å¯ä»¥è®©æä»¬æ´å®¹æçæå»º.NET Core å¾®æå¡ï¼å¯ä»¥è®© .NET Core æ´å¥½çæ¥å¥ gRPC çæãä¸å¾ä¸è¯´è¿æ¯ .NET Core 3.0 带æ¥çæä»¤äººæ¯å¥çç¹æ§ä¹ä¸ã
åèèµæï¼
å¨ASP.NET Coreä¸å建gRPC客æ·ç«¯åæå¡
以ä¸å°±æ¯æ¬æçå¨é¨å容ï¼å¸æå¯¹å¤§å®¶çå¦ä¹ ææå¸®å©ï¼ä¹å¸æå¤§å®¶å¤å¤æ¯æèæ¬ä¹å®¶ã