eShopOnContainers 知多少[11]:服务间通信之gRPC (2)

我们已经知道gRpc 是基于HTTP2.0 协议。然而,连接的建立,默认并不是一步到位直接基于HTTP2.0建立连接的。客户端是先基于HTTP1.1进行协议协商,协商成功后,确认服务端支持HTTP2.0后,才会建立HTT2.0连接,协议协商需要TLS的ALPN协议来实现。流程如下:

HTTP2.0 协议协商

这意味着,默认情况下,您需要启用TLS协议才能完成HTTP2.0协议协商,进而才能使用gRPC。

然而,在微服务架构中,并不是所有服务都需要启用安全传输层协议,尤其是微服务间的内部调用。那么在微服务内部如何使用gRPC进行通信呢?

客户端绕过协议协商,直连HTTP2.0(前提是:服务端必须支持HTTP2.0)

服务端配置如下:

WebHost.CreateDefaultBuilder(args)     .ConfigureKestrel(options =>     {         options.Listen(IPAddress.Any, ports.httpPort, listenOptions =>         {             listenOptions.Protocols = HttpProtocols.Http1AndHttp2; //同时监听协议HTTP1,HTTP2         });         options.Listen(IPAddress.Any, ports.gRPCPort, listenOptions =>         {             listenOptions.Protocols = HttpProtocols.Http2; // gRPC端口仅监听HTTP2.0         });     })

客户端需要添加以下设置,这些设置只能在客户端开始时设置一次:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true);

知道了这些,再回过来看GrpcCallerService的实现,就一目了然了。

public static class GrpcCallerService { public static async Task<TResponse> CallService<TResponse>(string urlGrpc, Func<GrpcChannel, Task<TResponse>> func) { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true); var channel = GrpcChannel.ForAddress(urlGrpc); /* using var httpClientHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; } }; */ Log.Information(@"Creating gRPC client base address urlGrpc ={@urlGrpc}, BaseAddress={@BaseAddress} ", urlGrpc, channel.Target); try { return await func(channel); } catch (RpcException e) { Log.Error("Error calling via gRPC: {Status} - {Message}", e.Status, e.Message); return default; } finally { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", false); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", false); } } public static async Task CallService(string urlGrpc, Func<GrpcChannel, Task> func) { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true); /* using var httpClientHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; } }; */ var channel = GrpcChannel.ForAddress(urlGrpc); Log.Debug("Creating gRPC client base address {@httpClient.BaseAddress} ", channel.Target); try { await func(channel); } catch (RpcException e) { Log.Error("Error calling via gRPC: {Status} - {Message}", e.Status, e.Message); } finally { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", false); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", false); } } } 最后

本文简要介绍了 eShopOnContainers 如何通过集成 gRPC 来完善服务间同步通信机制,希望对你在对微服务进行RPC相关技术选型时有一定的启示和帮助。

参考资料:

HTTP2.0笔记之连接建立

eShopOnContainers/wiki/gRPC

Google Protocol Buffer 的使用和原理

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpszzj.html