重新整理 .net core 实践篇—————grpc[三十三]
前言
简单整理一下grpc。
正文
什么是grpc?
- 一个远程过程调用框架,可以像类一样调用远程方法。
这种模式一般来说就是代理模式,然后都是框架自我生成的。
- 由google 公司发起并开源,故而前面有个g。
grpc的特点:
提供几乎所有主流语言的实现,打破语言隔阂。
基于http/2,开放协议,收到广泛的支持,易于实现和集成
http/2 有个特点哈,就是更快,可以了解下,后续会专门整理关于http相关的,要等网络原理整理完后。
默认使用protocol buffers 序列化,性能相较于restful json好很多
工具链成熟,代码生成便捷,开箱即用
支持双向流式的请求和相应,对批量处理、低延迟场景友好
.net 生态对gRPC的支持情况:
提供基于httpClient 的原生框架的实现
提供了原生的ASP .net Core 集成库
提供完整的代码工具
visual studio 和 visual Stuido Code 提供proto 文件的智能提示
实践:
service 服务端:
.net core 在服务端使用的包:
- Grpc.AspNetCore
客户端使用的包:
google.protobuf
Grpc.Net.Client
Grpc.Net.ClientFactory
Grpc.Tools
通过工具会生成proto 文件。
proto 文件:
定义包、库名
定义服务"service"
定义输入输出模型"message"
gRPC 异常处理:
使用Grpc.Core.RpcException
使用Grpc.Core.Interceptors.Interceptor
grpc 的加密方式:
grpc 因为是http2,默认使用https证书。
也可以不使用证书,里面可以设置,如果设置了,那么就是不加密的。
- 注入服务
services.AddGrpcClient<Greeter.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
});
- 测试代码
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
Greeter.GreeterClient service = context.RequestServices.GetService<Greeter.GreeterClient>();
HelloRequest helloRequest = new HelloRequest();
var reply = await service.SayHelloAsync(helloRequest);
Console.Read();
});
endpoints.MapControllers();
});
- 结果
这样就可以调用了。
这里如果我们使用http://localhost:5000,那么访问会失败,显示协议不可用,不支持http1.1。
那么如果需要http的话,就需要配置一些http2了。
在服务端的配置文件中,这样写:
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://*:5000"
},
"Https": {
"Url": "https://*:5001"
},
"Http2": {
"Url": "http://*:5002",
"Protocols": "Http2"
}
}
}
将http2的url设置为http://*:5002。
然后你就发现报错了:
这个问题也是比较简单的,因为http2默认使用加密,也就是应用解密的方式去解,自然就出错了。
那么需要这样:
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport",true);
支持不使用加密方式的http2。如果是在内网内,可以不使用加密方式,这样更加流畅。
那么还有一种情况就是如果在有证书的情况下,那么我们的开发环境可能就跑不过了,因为本地使用自签名证书,通过不了验证。
下面是生成证书的powershell脚本,百度的。
# setup certificate properties including the commonName (DNSName) property for Chrome 58+
$certificate = New-SelfSignedCertificate `
-Subject 改成自己想要的标题不要带乱七八糟的符号(安装证书的时候会显示这个) `
-DnsName 友好域名 `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-NotBefore (Get-Date) `
-NotAfter (Get-Date).AddYears(2) `
-CertStoreLocation "cert:CurrentUser\My" `
-FriendlyName "证书的友好名称,在IIS指定的时候显示Certificate for .NET Core" `
-HashAlgorithm SHA256 `
-KeyUsage DigitalSignature, KeyEncipherment, DataEncipherment `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")
$certificatePath = 'Cert:\CurrentUser\My\' + ($certificate.ThumbPrint)
# create temporary certificate path
$tmpPath = "C:\tmp"
If(!(test-path $tmpPath))
{
New-Item -ItemType Directory -Force -Path $tmpPath
}
# set certificate password here
$pfxPassword = ConvertTo-SecureString -String "证书的密码" -Force -AsPlainText
$pfxFilePath = "c:\tmp\证书的名称.pfx"
$cerFilePath = "c:\tmp\证书的名称.cer"
# create pfx certificate
Export-PfxCertificate -Cert $certificatePath -FilePath $pfxFilePath -Password $pfxPassword
Export-Certificate -Cert $certificatePath -FilePath $cerFilePath
# import the pfx certificate
Import-PfxCertificate -FilePath $pfxFilePath Cert:\LocalMachine\My -Password $pfxPassword -Exportable
# trust the certificate by importing the pfx certificate into your trusted root
Import-Certificate -FilePath $cerFilePath -CertStoreLocation Cert:\CurrentUser\Root
# optionally delete the physical certificates (don’t delete the pfx file as you need to copy this to your app directory)
# Remove-Item $pfxFilePath
Remove-Item $cerFilePath
然后在服务端配置一下证书:
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://*:5000"
},
"Https": {
"Url": "https://*:5001"
},
"Http2": {
"Url": "http://*:5002",
"Protocols": "Http2"
}
},
"Certificates": {
"Default": {
"Path": "self.cer",
"Password": "123456"
}
}
}
Certificates 配置了默认证书。
那么客户端请求一下https://localhost:5001.
返回:
那么这个时候无论证书验证是否成功,都返回true:
services.AddGrpcClient<Greeter.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
}).ConfigurePrimaryHttpMessageHandler(provider =>
{
var handle = new SocketsHttpHandler();
handle.SslOptions.RemoteCertificateValidationCallback = (a, b, c, d) => true;
return handle;
});
然后就可以访问了。
下面整理一下异常拦截器,如果我们服务端发生异常,我们希望有某种规律的错误发出。
测试异常:
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
throw new Exception("异常信息");
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
通过异常拦截器过滤一下:
services.AddGrpc(options =>
{
options.EnableDetailedErrors = false;
options.Interceptors.Add<ExceptionInterceptor>();
});
具体异常拦截类:
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)
{
//log 处理
Metadata entries = new Metadata();
entries.Add("message",ex.Message);
throw new RpcException(new Status(StatusCode.Unknown, "Unknown"), entries);
}
}
调试:
结
下一节实践一下用工具生成grpc 代码。
重新整理 .net core 实践篇—————grpc[三十三]的更多相关文章
- 重新整理 .net core 实践篇—————HttpClientFactory[三十二]
前言 简单整理一下HttpClientFactory . 正文 这个HttpFactory 主要有下面的功能: 管理内部HttpMessageHandler 的生命周期,灵活应对资源问题和DNS刷新问 ...
- 重新整理 .net core 实践篇————网关[三十六]
前言 简单整理一下网关. 正文 在介绍网关之前,介绍一下BFF,BFF全称是Backend For Frontend,它负责认证授权,服务聚合,目标是为前端提供服务. 说的通透一点,就是有没有见过这种 ...
- 重新整理 .net core 实践篇————配置应用[一]
前言 本来想整理到<<重新整理.net core 计1400篇>>里面去,但是后来一想,整理 .net core 实践篇 是偏于实践,故而分开. 因为是重新整理,那么就从配置开 ...
- 重新整理 .net core 实践篇————依赖注入应用[二]
前言 这里介绍一下.net core的依赖注入框架,其中其代码原理在我的另一个整理<<重新整理 1400篇>>中已经写了,故而专门整理应用这一块. 以下只是个人整理,如有问题, ...
- 重新整理 .net core 实践篇————polly失败重试[三十四]
前言 简单整理一下polly 重试. 正文 在开发程序中一般都有一个重试帮助类,那么polly同样有这个功能. polly 组件包: polly 功能包 polly.Extensions.Http 专 ...
- 重新整理 .net core 实践篇————网关中的身份签名认证[三十七]
前言 简单整理一下网关中的jwt,jwt用于授权认证的,其实关于认证授权这块https://www.cnblogs.com/aoximin/p/12268520.html 这个链接的时候就已经写了,当 ...
- 重新整理 .net core 实践篇————依赖注入应用之生命法则[三]
前言 该章演示依赖注入中,对象的释放行为. 紧接上文表示,演示: services.AddSingleton<IMySingletonService, MySingletonService> ...
- 重新整理 .net core 实践篇—————路由和终结点[二十三]
前言 简单整理一下路由和终节点. 正文 路由方式主要有两种: 1.路由模板方式 2.RouteAttribute 方式 路由约束: 1.类型约束 2.范围约束 3.正则表达式 4.是否必选 5.自定义 ...
- 重新整理 .net core 实践篇—————服务的配置更新[十三]
前言 前文讲述了,服务和配置直接的配合,这一节写一下,当配置文件修改了,每个服务如何感知自己的配置. 正文 服务感知到自己的配置发生变化,这就牵扯出两个东西: IoptionsMonitor<o ...
随机推荐
- JAVA8 lambda表达式权威教程!
Java 8新特性----Stream流 jdk8是Java 语言开发的一个主要版本,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等等.今天就重点介 ...
- 03.28,周六,12:00-17:00,ICPC训练联盟周赛,选用试题:UCF Local Programming Contest 2016正式赛。
A. Majestic 10 题意:三个数均大于10则输出"triple-double",如果两个数大于10则输出"double-double",如果一个大于1 ...
- 2020BUAA-个人博客-案例分析
个人博客作业-软件案例分析 项目 内容 北航2020软工 班级博客 作业要求 具体要求 我的课程目标 通过案例分析提升自己对于软件工程的认识 课程收获 分析软件,了解软件的定位 第一部分 调研,评测( ...
- 【建议收藏】缺少 Vue3 和 Spring Boot 的实战项目经验?我这儿有啊!
缺少 Vue3 和 Spring Boot 的实战项目经验?缺少学习项目和练手项目?我这儿有啊! 从 2019 年到 2021 年,空闲时间里陆陆续续做了一些开源项目,推荐给大家啊!记得点赞和收藏噢! ...
- Linux_配置主DNS服务(基础)
[RHEL8]-DNSserver:[Centos7.4]-DNSclient !!!测试环境我们首关闭防火墙和selinux(DNSserver和DNSclient都需要) [root@localh ...
- k8s运行容器之Job应用(6)
容器按照持续运行的时间可分为两类:服务类容器和工作类容器. 服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等.工作类容器则是一次性任务,比如批处理程序,完成后容 ...
- 高通 QC协议 谷歌 PD协议
高通 QC协议 谷歌 PD协议 上述协议是两款充电协议 现在已经应用于智能设备的充电中了 https://jingyan.baidu.com/article/7908e85cb04b1baf48 ...
- 10.16-17 mailq&mail:显示邮件传输队列&发送邮件
mailq命令 是mail queue(邮件队列)的缩写,它会显示待发送的邮件队列,显示的条目包括邮件队列ID.邮件大小.加入队列时间.邮件发送者和接受者.如果邮件进行最后一次尝试后还没有将邮件投递出 ...
- 关于RabbitMQ的一些问题总结
消息中间件在工作中一般都不会采用单机模式的,该篇其实是对mq的高可用等等常见问题做一些归纳. 消息队列的高可用 普通集群与镜像集群模式,此处不做深究,另开一篇专门讲述此处 如何保证消息不被重复消费 保 ...
- 快成物流科技 x mPaaS | 小程序容器加持下的技术架构“提质增效”
导言 从 2017 年开始,GMTC"移动技术大会"就更名为"大前端技术大会".发展至今,混合开发.原生开发.前端开发等概念正在深度融合,组成"大 ...