一、前言

 

      前一陣子關(guān)于.NET的各大公眾號(hào)都發(fā)表了關(guān)于gRpc的消息,而隨之而來的就是一波關(guān)于.NET Core下如何使用的教程,但是在這眾多的教程中基本都是泛泛而談,難以實(shí)際在實(shí)際環(huán)境中使用,而該篇教程以gRpc為主,但是使用了其SSL/TLS,這樣更加符合實(shí)際的生產(chǎn)使用,期間也會(huì)配套的講解Docker、openssl等。

 

二、服務(wù)端

 

a.準(zhǔn)備工作

筆者的項(xiàng)目分為三個(gè)部分分別如下所示:

Sino.GrpcService.Host(控制臺(tái)):宿主程序

Sino.GrpcService.Impl(類庫):實(shí)現(xiàn)協(xié)議

Sino.GrpcService.Protocol(類庫):生成協(xié)議

 

最終的項(xiàng)目如下圖所示:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

每個(gè)項(xiàng)目的project.json如下所示:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

 

其中“buildOptions”和“publishOptions”中我們將后面我們需要的證書包含到輸出和發(fā)布中,其中我們還利用了“Configuration”相關(guān)組件去讀取配置信息。

 

Sino.GrpcService.Impl:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

 

其中我們安裝了“MongoDb.Driver”,為了能夠貼近真實(shí)的情況,筆者這里采用MongoDb作為數(shù)據(jù)源來提供數(shù)據(jù),當(dāng)然讀者為了能夠快速上手可以硬編碼一些數(shù)據(jù)。

 

Sino.GrpcService.Protocol:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

至此項(xiàng)目的初始化結(jié)束。

 

b.編寫協(xié)議

      首先我們打開Sino.GrpcService.Protocol項(xiàng)目,在其中新建一個(gè)msg.proto文件,打開msg.proto文件,我們將在其中編寫基于proto3語言的協(xié)議,以便后面自動(dòng)生成到各語言,如果讀者需要更深入的學(xué)習(xí)可以打開該網(wǎng)站Proto3語言指南。

這里我們定義我們當(dāng)前使用的是proto3語言并且包名(生成為C#則為命名空間)為:

syntax = "proto3"; package Sino.GrpcService;

 

 

筆者為該服務(wù)定義了1個(gè)服務(wù),且有4種方法:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

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

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

 

對(duì)應(yīng)到其中每個(gè)方法的接收參數(shù)和返回參數(shù)的定義如下:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

 

到這為止我們就完成了協(xié)議的編寫。

 

c.將協(xié)議生成為C#代碼

      相對(duì)于網(wǎng)站的很多關(guān)于C#使用gRpc的教程都是基于.NET項(xiàng)目框架下的,所以可以安裝gRpc.Tools,但是.NET Core安裝后是找不到工具的,所以讀者可以新建一個(gè).NET項(xiàng)目安裝該類庫,然后將其中的工具復(fù)制到Sino.GrpcService.Protocol中,這里讀者需要根據(jù)你當(dāng)前的系統(tǒng)去選擇,復(fù)制完成之后在該項(xiàng)目中新建一個(gè)名為“ProtocGenerate.cmd”的文件,在其中輸入以下指令:

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

 

然后讀者直接雙擊運(yùn)行,就會(huì)看到項(xiàng)目下生成了“Msg.cs”和“MsgGrpc.cs”兩個(gè)文件,這樣就完成了所有協(xié)議部分的工作了,最終的項(xiàng)目結(jié)構(gòu)如下所示:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

d.編寫實(shí)現(xiàn)代碼

      有了協(xié)議層之后我們就可以開始編寫實(shí)現(xiàn)了,因?yàn)楣P者這里使用了MongoDb提供數(shù)據(jù)所以下文篇幅會(huì)較長(zhǎng)。

 

首先打開Sino.GrpcService.Impl項(xiàng)目在其中新建Model文件,然后在該文件夾下新建MsgDM.cs文件,該文件主要是定義MongoDb存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu),具體內(nèi)容如下所示:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

 

 

緊接著我們新建Repositories文件夾,在其中新建四個(gè)文件分別為“IDataContext.cs”、“DataContext.cs”、“IMsgRepository.cs”和“MsgRepository.cs”。打開IDataContext.cs文件在其中編寫如下內(nèi)容:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

    /// <summary>     /// 數(shù)據(jù)庫上下文     /// </summary>     public interface IDataContext     {         IMongoDatabase Database { get; set; }     }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

 

打開DataContext.cs文件進(jìn)行數(shù)據(jù)庫初始化相關(guān)工作:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

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

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

 

打開IMsgRepository.cs,我們需要在其中定義倉(cāng)儲(chǔ)提供的操作:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

/// <summary>     /// 消息倉(cāng)儲(chǔ)     /// </summary>     public interface IMsgRepository     {         /// <summary>         /// 獲取列表         /// </summary>         Task<List<MsgDM>> GetList(long userId, string title, long startTime, long endTime);         /// <summary>         /// 獲取實(shí)體         /// </summary>         Task<MsgDM> Get(string id);         /// <summary>         /// 更新實(shí)體         /// </summary>         Task<bool> Update(MsgDM data);         /// <summary>         /// 添加實(shí)體         /// </summary>         Task<string> Insert(MsgDM data);         /// <summary>         /// 刪除實(shí)體         /// </summary>         Task<bool> Delete(string id);     }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

 

對(duì)應(yīng)的我們還需要打開MsgRepository.cs文件實(shí)現(xiàn)該接口:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

 

 

完成了上面關(guān)于數(shù)據(jù)庫的工作,下面我們就進(jìn)入正題,開始實(shí)現(xiàn)gRpc服務(wù)了,首先我們?cè)陧?xiàng)目根目錄下新建MsgServiceImpl.cs文件,在其中實(shí)現(xiàn)我們協(xié)議中的服務(wù):

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

 

 

三、證書生成

 

a.安裝openssl

首先讀者需要從該網(wǎng)站下載openssl安裝程序:

Openssl下載

筆者的系統(tǒng)是Win10 64所以下載的是“Win64 OpenSSL v1.1.0b”。

 

b.制作證書

網(wǎng)上有很多的教程,但是對(duì)于新手來說直接給繞暈了,有的有ca、client和service有的沒有,這里筆者提供一個(gè)全面的cmd腳本(默認(rèn)CA是自己)

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 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

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

以上的腳本也會(huì)生成我們下面Demo中使用的證書。

 

四、完善服務(wù)端

      用了上面的證書之后我們需要繼續(xù)把服務(wù)端啟動(dòng)gRpc服務(wù)部分的代碼書寫完畢,這里筆者是采用命令行形式運(yùn)行的,所以gRpc的啟動(dòng)是獨(dú)立放在一個(gè)文件文件中,如下RpcConfiguration所示:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn) View Code

其中我們使用了server.crtserver.key這兩個(gè)證書,所以在Host項(xiàng)目中需要將這個(gè)兩個(gè)證書文件copy到項(xiàng)目根目錄下,如果需要發(fā)布的時(shí)候包含則需要在project.json中配置如下節(jié):

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

最后我們需要在Program中啟動(dòng)對(duì)應(yīng)的gRpc即可。

 

五、客戶端編寫

      完成了服務(wù)端的編寫剩下的就是客戶端的編寫,當(dāng)然客戶端的編寫相對(duì)容易很多,筆者這里直接把Sino.GrpcService.Protocol項(xiàng)目包含到客戶端解決方案中了(在正式開發(fā)中建議采用nuget包進(jìn)行管理),為了簡(jiǎn)單起見,所以只調(diào)用了其中一個(gè)服務(wù)接口:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

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             });         }     }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

需要注意下其中“ChannelOptions.SslTargetNameOverride”這部分是必須的,因?yàn)槲覀兪亲约荷傻淖C書,所以域名是root,如果是生產(chǎn)環(huán)境可以不需要。

 

六、利用Docker運(yùn)行

 

a.安裝Docker For Windows

      這里需要win10的系統(tǒng),這樣可以直接在ps中直接利用docker指令了。

 

b.編寫Dockerfile

      因?yàn)?span style="line-height: 1.8">1.1版本出來了,但是經(jīng)過本人的驗(yàn)證,如果你的應(yīng)用不升級(jí)是無法使用該鏡像的,默認(rèn)使用1.1,所以這里我們的Dockerfile需要指定下特定的版本,否則是無法構(gòu)建的,我們首先在解決方案的根目錄下新建Dockerfile文件,然后在其中放入以下命令:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 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"]

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

 

 

c.生成鏡像并運(yùn)行

我們打開ps,然后cd到解決方案的文件夾下利用:

docker build -t gRpcService:1.0 .

 

開始構(gòu)建,基于國(guó)內(nèi)的情況建議大家將docker默認(rèn)拉取鏡像的地址調(diào)整下。生成好之后,利用以下指令去啟動(dòng)即可:

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

 

當(dāng)然客戶端連接的地址和端口也要根據(jù)-p指定的情況去調(diào)整。

 

七、其他

對(duì)應(yīng)的源碼可以訪問以下地址:

 

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

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