NET Core下使用gRpc公开服务(SSL/TLS)

一、前言

前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇教程以gRpc为主,但是使用了其SSL/TLS,这样更加符合实际的生产使用,期间也会配套的讲解Docker、openssl等。

二、服务端

a.准备工作

笔者的项目分为三个部分分别如下所示:

Sino.GrpcService.Host(控制台):宿主程序

Sino.GrpcService.Impl(类库):实现协议

Sino.GrpcService.Protocol(类库):生成协议

最终的项目如下图所示:

每个项目的project.json如下所示:

 

其中“buildOptions”和“publishOptions”中我们将后面我们需要的证书包含到输出和发布中,其中我们还利用了“Configuration”相关组件去读取配置信息。

Sino.GrpcService.Impl:

其中我们安装了“MongoDb.Driver”,为了能够贴近真实的情况,笔者这里采用MongoDb作为数据源来提供数据,当然读者为了能够快速上手可以硬编码一些数据。

Sino.GrpcService.Protocol:

至此项目的初始化结束。

b.编写协议

首先我们打开Sino.GrpcService.Protocol项目,在其中新建一个msg.proto文件,打开msg.proto文件,我们将在其中编写基于proto3语言的协议,以便后面自动生成到各语言,如果读者需要更深入的学习可以打开该网站Proto3语言指南

这里我们定义我们当前使用的是proto3语言并且包名(生成为C#则为命名空间)为:

syntax = "proto3";
package Sino.GrpcService;

笔者为该服务定义了1个服务,且有4种方法:

service MsgService{
rpc GetList(GetMsgListRequest) returns (GetMsgListReply){}
rpc GetOne(GetMsgOneRequest) returns (GetMsgOneReply){}
rpc Edit(EditMsgRequest) returns (EditMsgReply){}
rpc Remove(RemoveMsgRequest) returns (RemoveMsgReply){}
}

对应到其中每个方法的接收参数和返回参数的定义如下:

到这为止我们就完成了协议的编写。

c.将协议生成为C#代码

相对于网站的很多关于C#使用gRpc的教程都是基于.NET项目框架下的,所以可以安装gRpc.Tools,但是.NET Core安装后是找不到工具的,所以读者可以新建一个.NET项目安装该类库,然后将其中的工具复制到Sino.GrpcService.Protocol中,这里读者需要根据你当前的系统去选择,复制完成之后在该项目中新建一个名为“ProtocGenerate.cmd”的文件,在其中输入以下指令:

protoc -I . --csharp_out . --grpc_out . --plugin=protoc-gen-grpc=grpc_csharp_plugin.exe msg.proto

然后读者直接双击运行,就会看到项目下生成了“Msg.cs”和“MsgGrpc.cs”两个文件,这样就完成了所有协议部分的工作了,最终的项目结构如下所示:

d.编写实现代码

有了协议层之后我们就可以开始编写实现了,因为笔者这里使用了MongoDb提供数据所以下文篇幅会较长。

首先打开Sino.GrpcService.Impl项目在其中新建Model文件,然后在该文件夹下新建MsgDM.cs文件,该文件主要是定义MongoDb存储的数据结构,具体内容如下所示:

紧接着我们新建Repositories文件夹,在其中新建四个文件分别为“IDataContext.cs”、“DataContext.cs”、“IMsgRepository.cs”和“MsgRepository.cs”。打开IDataContext.cs文件在其中编写如下内容:

    /// <summary>
/// 数据库上下文
/// </summary>
public interface IDataContext
{
IMongoDatabase Database { get; set; }
}

打开DataContext.cs文件进行数据库初始化相关工作:

    public class DataContext : IDataContext
{
public IMongoDatabase Database { get; set; } public DataContext(IConfigurationRoot config)
{
var client = new MongoClient(config.GetConnectionString("mongodb"));
Database = client.GetDatabase("aSQ0cWkEshl8NiVn");
}
}

打开IMsgRepository.cs,我们需要在其中定义仓储提供的操作:

/// <summary>
/// 消息仓储
/// </summary>
public interface IMsgRepository
{
/// <summary>
/// 获取列表
/// </summary>
Task<List<MsgDM>> GetList(long userId, string title, long startTime, long endTime); /// <summary>
/// 获取实体
/// </summary>
Task<MsgDM> Get(string id); /// <summary>
/// 更新实体
/// </summary>
Task<bool> Update(MsgDM data); /// <summary>
/// 添加实体
/// </summary>
Task<string> Insert(MsgDM data); /// <summary>
/// 删除实体
/// </summary>
Task<bool> Delete(string id);
}

对应的我们还需要打开MsgRepository.cs文件实现该接口:

完成了上面关于数据库的工作,下面我们就进入正题,开始实现gRpc服务了,首先我们在项目根目录下新建MsgServiceImpl.cs文件,在其中实现我们协议中的服务:

三、证书生成

a.安装openssl

首先读者需要从该网站下载openssl安装程序:

Openssl下载

笔者的系统是Win10 64所以下载的是“Win64 OpenSSL v1.1.0b”。

b.制作证书

网上有很多的教程,但是对于新手来说直接给绕晕了,有的有ca、client和service有的没有,这里笔者提供一个全面的cmd脚本(默认CA是自己):

 1 @echo off
2 set OPENSSL_CONF=c:\OpenSSL-Win64\bin\openssl.cfg
3
4 echo Generate CA key:
5 openssl genrsa -passout pass:1111 -des3 -out ca.key 4096
6
7 echo Generate CA certificate:
8 openssl req -passin pass:1111 -new -x509 -days 365 -key ca.key -out ca.crt -subj "/C=CN/ST=JS/L=ZJ/O=sino/OU=test/CN=root"
9
10 echo Generate server key:
11 openssl genrsa -passout pass:1111 -des3 -out server.key 4096
12
13 echo Generate server signing request:
14 openssl req -passin pass:1111 -new -key server.key -out server.csr -subj "/C=CN/ST=JS/L=ZJ/O=sino/OU=test/CN=root"
15
16 echo Self-sign server certificate:
17 openssl x509 -req -passin pass:1111 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
18
19 echo Remove passphrase from server key:
20 openssl rsa -passin pass:1111 -in server.key -out server.key
21
22 echo Generate client key
23 openssl genrsa -passout pass:1111 -des3 -out client.key 4096
24
25 echo Generate client signing request:
26 openssl req -passin pass:1111 -new -key client.key -out client.csr -subj "/C=CN/ST=JS/L=ZJ/O=sino/OU=test/CN=root"
27
28 echo Self-sign client certificate:
29 openssl x509 -passin pass:1111 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
30
31 echo Remove passphrase from client key:
32 openssl rsa -passin pass:1111 -in client.key -out client.key

以上的脚本也会生成我们下面Demo中使用的证书。

四、完善服务端

用了上面的证书之后我们需要继续把服务端启动gRpc服务部分的代码书写完毕,这里笔者是采用命令行形式运行的,所以gRpc的启动是独立放在一个文件文件中,如下RpcConfiguration所示:

其中我们使用了server.crtserver.key这两个证书,所以在Host项目中需要将这个两个证书文件copy到项目根目录下,如果需要发布的时候包含则需要在project.json中配置如下节:

  "publishOptions": {
"include": [ "server.crt", "server.key", "appSettings.json", "appSettings.*.json" ]
}

最后我们需要在Program中启动对应的gRpc即可。

五、客户端编写

完成了服务端的编写剩下的就是客户端的编写,当然客户端的编写相对容易很多,笔者这里直接把Sino.GrpcService.Protocol项目包含到客户端解决方案中了(在正式开发中建议采用nuget包进行管理),为了简单起见,所以只调用了其中一个服务接口:

public static class MsgServiceClient
{
private static Channel _channel;
private static MsgService.MsgServiceClient _client; static MsgServiceClient()
{
var cacert = File.ReadAllText("server.crt");
var ssl = new SslCredentials(cacert);
var channOptions = new List<ChannelOption>
{
new ChannelOption(ChannelOptions.SslTargetNameOverride,"root")
};
_channel = new Channel("grpcservice.t0.daoapp.io:61130", ssl, channOptions);
_client = new MsgService.MsgServiceClient(_channel);
} public static GetMsgListReply GetList(int userId, string title, long startTime, long endTime)
{
return _client.GetList(new GetMsgListRequest
{
UserId = userId,
Title = title,
StartTime = startTime,
EndTime = endTime
});
}
}

需要注意下其中“ChannelOptions.SslTargetNameOverride”这部分是必须的,因为我们是自己生成的证书,所以域名是root,如果是生产环境可以不需要。

六、利用Docker运行

a.安装Docker For Windows

这里需要win10的系统,这样可以直接在ps中直接利用docker指令了。

b.编写Dockerfile

因为1.1版本出来了,但是经过本人的验证,如果你的应用不升级是无法使用该镜像的,默认使用1.1,所以这里我们的Dockerfile需要指定下特定的版本,否则是无法构建的,我们首先在解决方案的根目录下新建Dockerfile文件,然后在其中放入以下命令:

 1 FROM microsoft/dotnet:1.0-sdk-projectjson
2
3 ADD ./ /usr/local/src
4 WORKDIR /usr/local/src/Sino.GrpcService.Host/
5
6 RUN cd /usr/local/src/
7 RUN dotnet restore -v http://api.nuget.org/v3/index.json
8 RUN dotnet build
9
10 EXPOSE 9007
11
12 CMD ["dotnet","run"]

c.生成镜像并运行

我们打开ps,然后cd到解决方案的文件夹下利用:

docker build -t gRpcService:1.0 .

开始构建,基于国内的情况建议大家将docker默认拉取镜像的地址调整下。生成好之后,利用以下指令去启动即可:

docker run -d –name -p 9007:9007 gRpcService gRpcService:1.0

当然客户端连接的地址和端口也要根据-p指定的情况去调整。

七、其他

对应的源码可以访问以下地址:

https://github.com/Vip56/Sino.GrpcService

https://github.com/Vip56/Sino.GrpcClient

如果需要询问相关问题的可以短消息给我。

Xamarin.Android -> Xamarin.IOS -> 混合 -> Xamarin.Forms

gRpc NET Core的更多相关文章

  1. gRPC .NET Core跨平台学习

    前些天发布gRPC C# 学习,在.NET Framework 中使用gRPC ,今天来学习 .NET Core gRPC. gRPC 的.NET Core 包在NuGet 上发布了,结合.NET C ...

  2. 谷歌发布的首款基于HTTP/2和protobuf的RPC框架:GRPC

    Google 刚刚开源了grpc,  一个基于HTTP2 和 Protobuf 的高性能.开源.通用的RPC框架.Protobuf 本身虽然提供了RPC  的定义语法,但是一直以来,Google 只开 ...

  3. .net core 用grpc实现微服务

    GRPC 是Google发布的一个开源.高性能.通用RPC(Remote Procedure Call)框架.提供跨语言.跨平台支持.以下以.NET Core 使用控制台.docker中演示如何使用G ...

  4. .NET Core下使用gRpc公开服务(SSL/TLS)

    一.前言 前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇 ...

  5. asp.net core 3.0 gRPC框架小试

    什么是gRPC gRPC是google开源的一个高性能.跨语言的RPC框架,基于HTTP2协议,采用ProtoBuf 定义的IDL. gRPC 的主要优点是: 现代高性能轻量级 RPC 框架. 协定优 ...

  6. ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...

  7. .net core 3.0中可以使用gRPC了

    今天发现.net core下有gRPC模板了,这个可是补全了.net core下高性能RPC框架缺失这一大短板了. 使用模板创建了工程后,发现连客户端的示例也创建了. 更加给力的是,IDE是能直接识别 ...

  8. .net core grpc 实现通信(一)

    现在系统都服务化,.net core 实现服务化的方式有很多,我们通过grpc实现客户端.服务端通信. grpc(https://grpc.io/)是google发布的一个开源.高性能.通用RPC(R ...

  9. .net core grpc consul 实现服务注册 服务发现 负载均衡(二)

    在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...

随机推荐

  1. C语言的结构体和C++结构体的区别

    关于C++中声明结构体中需要使用构造器创建实例对象的语法: <C++的结构体构造方法的基本概念:结构体的构造方法需要和结构体的名字相同,并且无返回值,也不要void关键字,这样的方法就是构造器的 ...

  2. 集合1--毕向东java基础教程视频学习笔记

    Day14 集合框架01 体系概述02 共性方法03 迭代器04 List集合共性方法05 ListIterator06 List集合具体对象特点07 Vector中的枚举 01 体系概述 集合类为什 ...

  3. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  4. C#调用SQL Server分页存储过程

    以SQL Server2012提供的offset ..rows fetch next ..rows only为例 e.g. 表名:Tab1 ------------------------------ ...

  5. Android中在sdcard上创建文件夹

    //在SD卡上创建一个文件夹    public void createSDCardDir(){     if(Environment.MEDIA_MOUNTED.equals(Environment ...

  6. Android gdb 调试

    [1].终端目录设置到: proj.android[2].make文件的编译选项加上: -g -gstabs+[3].执行编译脚本: sh ./build_native.sh NDK_DEBUG=1[ ...

  7. 理解 OpenStack + Ceph (7): Ceph 的基本操作和常见故障排除方法

    本系列文章会深入研究 Ceph 以及 Ceph 和 OpenStack 的集成: (1)安装和部署 (2)Ceph RBD 接口和工具 (3)Ceph 物理和逻辑结构 (4)Ceph 的基础数据结构 ...

  8. 理解 QEMU/KVM 和 Ceph(2):QEMU 的 RBD 块驱动(block driver)

    本系列文章会总结 QEMU/KVM 和 Ceph 之间的整合: (1)QEMU-KVM 和 Ceph RBD 的 缓存机制总结 (2)QEMU 的 RBD 块驱动(block driver) (3)存 ...

  9. css多栏自适应布局

    css多栏自适应布局还是需要总结一下的,都是基本功. 一般使用position属性布局,或者用float属性布局,也可以使用display属性. 看资料说position适合首页布局,因为首页内容往往 ...

  10. C++ 之 重载赋值操作符

    Widget 类中,定义了一个 Bitmap 类型的私有数据成员 -- pb 指针 class Bitmap { ... }; class Widget { private: Bitmap *pb; ...