现在系统都服务化,.net core 实现服务化的方式有很多,我们通过grpc实现客户端、服务端通信。

grpc(https://grpc.io/)是google发布的一个开源、高性能、通用RPC(Remote Procedure Call)框架,使用HTTP/2协议,支持多路复用,并用ProtoBuf作为序列化工具,提供跨语言、跨平台支持。下面以.net core演示如何使用grpc框架实现通信。

软件版本

.net core:2.0

grpc:1.11.0

项目结构

InstallGrpc .net framework类库 只为得到生成协议代码工具protoc.exe、grpc_csharp_plugin.exe,没有其他作用,如果已有工具,可以不用

Snai.GrpcClient 客户端 .net core 2.0控制台程序

Snai.GrpcService.Hosting 服务端宿主 .net core 2.0控制台程序

Snai.GrpcService.Impl 协议方法实现  .net standard 2.0类库

Snai.GrpcService.Protocol 生成协议方法 .net standard 2.0类库

运行结果

服务端

客户端

客户端调用服务端求和方法成功。

项目实现

一、服务端

新建Snai.GrpcService解决方案

1、编写协议

新建 Snai.GrpcService.Protocol协议类库项目,在 依赖项 右击 管理NuGet程序包 浏览 找到 Grpc.Core 版本1.11.0,Google.Protobuf 版本3.5.1 包下载安装

在项目根目录下新建一个 msg.proto 文件,打开 msg.proto 文件,在其中编写基于proto3语言的协议代码,用于自动生成到各语言协议,如果需要更深入的学习proto3语言可以打开该网站Proto3语言指南。msg.proto 代码如下

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

syntax = "proto3";

package Snai.GrpcService.Protocol;

定义了1个服务,且有1个方法:

service MsgService{
  rpc GetSum(GetMsgNumRequest) returns (GetMsgSumReply){}
}

方法的接收参数和返回参数

message GetMsgNumRequest {
  int32 Num1 = 1;
  int32 Num2 = 2;
} message GetMsgSumReply {
  int32 Sum = 1;
}

2、将协议生成C#代码

生成协议代码需 protoc.exe、grpc_csharp_plugin.exe工具,在.net framework 项目下引用安装 Grpc.Tools 组件程序包,会得到protoc.exe、grpc_csharp_plugin.exe,但.net core 项目引用安装是不会下载工具到项目目录的,所以我们需要建一个.net framework项目,我建了个 InstallGrpc .net framework类库 用于引用安装得到工具。

这里得到工具有个小插曲,引用Grpc.Tools版本1.11.0得到protoc.exe、grpc_csharp_plugin.exe 拷到 Snai.GrpcService.Protocol 目录下生成不了,我再引用Google.Protobuf.Tools版本3.5.1里面有 protoc.exe,用 Grpc.Tools下的 grpc_csharp_plugin.exe, Google.Protobuf.Tools下protoc.exe 根据当前系统选择,拷贝到 Snai.GrpcService.Protocol 目录下。

先用Grpc.Tools 下的,如果生成不了,再用 Grpc.Tools下的 grpc_csharp_plugin.exe, Google.Protobuf.Tools下protoc.exe

然后在项目中新建一个名为ProtocGenerate.cmd的文件,在其中输入以下指令:

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

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

3、编写协议实现代码

新建Snai.GrpcService.Impl实现类库项目,在 依赖项 下载安装Grpc.Core 包,项目引用Snai.GrpcService.Protocol

在项目根目录下新建 MsgServiceImpl.cs 类文件,继承 MsgService.MsgServiceBase 协议类,实现服务方法,代码如下:

using Grpc.Core;
using Snai.GrpcService.Protocol;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks; namespace Snai.GrpcService.Impl
{
    public class MsgServiceImpl: MsgService.MsgServiceBase
    {
        public MsgServiceImpl()
        {
        }         public override async Task<GetMsgSumReply> GetSum(GetMsgNumRequest request, ServerCallContext context)
        {
            var result = new GetMsgSumReply();             result.Sum = request.Num1 + request.Num2;             return result;
        }
    }
}

在项目根目录下新建 RpcConfig.cs 类文件,编写绑定服务到服务端,服务端 地址 端口 等信息,实现启动方法,代码如下:

using Grpc.Core;
using Snai.GrpcService.Protocol;
using System;
using System.Collections.Generic;
using System.Text; namespace Snai.GrpcService.Impl
{
    public static class RpcConfig
    {
        private static Server _server;         public static void Start()
        {
            _server = new Server
            {
                Services = { MsgService.BindService(new MsgServiceImpl()) },
                Ports = { new ServerPort("localhost", 40001, ServerCredentials.Insecure) }
            };
            _server.Start();             Console.WriteLine("grpc ServerListening On Port 40001");
            Console.WriteLine("任意键退出...");
            Console.ReadKey();             _server?.ShutdownAsync().Wait();
        }
    }
}

最终项目结构如下:

aaarticlea/png;base64,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" alt="" />

4、编写服务端启动程序

新建Snai.GrpcService.Hosting 控制台程序,项目引用Snai.GrpcService.Impl

打开 Program.cs 文件,修改 Main 方法,加入服务启动,代码如下:

using Snai.GrpcService.Impl;
using System; namespace Snai.GrpcService.Hosting
{
    class Program
    {
        static void Main(string[] args)
        {
            RpcConfig.Start();
        }
    }
}

最终项目结构如下:

到此服务端所有代码已编写完成,下面开始编写客户端。

二、客户端

新建Snai.GrpcClient 控制台程序,在 依赖项 下载安装Grpc.Core 包,项目引用Snai.GrpcService.Protocol

在项目根目录下新建 MsgServiceClient.cs 类文件,编写与服务端通信的 地址 端口 等信息,并调用服务端方法,代码如下:

using Grpc.Core;
using Snai.GrpcService.Protocol;
using System;
using System.Collections.Generic;
using System.Text; namespace Snai.GrpcClient
{
    public static class MsgServiceClient
    {
        private static Channel _channel;
        private static MsgService.MsgServiceClient _client;         static MsgServiceClient()
        {
            _channel = new Channel("127.0.0.1:40001", ChannelCredentials.Insecure);
            _client = new MsgService.MsgServiceClient(_channel);
        }         public static GetMsgSumReply GetSum(int num1, int num2)
        {
            return _client.GetSum(new GetMsgNumRequest
            {
                Num1 = num1,
                Num2 = num2
            });
        }
    }
}

打开 Program.cs 文件,修改 Main 方法,得到服务端返回结果,显示结果,代码如下:

using Snai.GrpcService.Protocol;
using System; namespace Snai.GrpcClient
{
    class Program
    {
        static void Main(string[] args)
        {
            GetMsgSumReply msgSum = MsgServiceClient.GetSum(10, 2);             Console.WriteLine("grpc Client Call GetSum():" + msgSum.Sum);             Console.WriteLine("任意键退出...");
            Console.ReadKey();
        }
    }
}

最终项目结构如下:

到此所有代码都已编写完成

三、启动

右击生成解决方案,生成完成后,先启动服务端,再启动客户端

命令行到服务端目录 Snai.GrpcService.Hosting\bin\Debug\netcoreapp2.0\,用命令 dotnet Snai.GrpcService.Hosting.dll 启动服务端

命令行到客户端目录 Snai.GrpcClient\bin\Debug\netcoreapp2.0\,用命令 dotnet Snai.GrpcClient.dll 启动客户端

客户端调用服务端方法成功,实现grpc

它们之间是通过Grpc.Core中的 Server 和 Channel 来通信

Github源码地址:https://github.com/Liu-Alan/Snai.GrpcService

博客地址:http://www.snaill.net/post/1

.net core grpc 实现通信(一)的更多相关文章

  1. .Net Core Grpc 实现通信

    .Net Core 3.0已经把Grpc作为一个默认的模板引入,所以我认为每一个.Net程序员都有学习Grpc的必要,当然这不是必须的. 我在我的前一篇文章中介绍并创建了一个.Net Core 3.0 ...

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

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

  3. .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡

    本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...

  4. Asp.Net Core Grpc 入门实践

    Grpc简介 gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. 在 gRPC 中,客户端应用程序可以直接调用不同计算机上的服务器应用程序上的方法,就像它是本地对象一样,从而更轻松地创 ...

  5. NetCore服务虚拟化01(集群组件Sodao.Core.Grpc)

    一. 起始 去年.NetCore2.0的发布,公司决定新项目采用.NetCore开发,当作试验.但是问题在于当前公司内部使用的RPC服务为Thrift v0.9 + zookeeper版本,经过个性化 ...

  6. .NET Core ❤ gRPC

    这篇内容主要来自Microsoft .NET团队程序经理Sourabh Shirhatti的博客文章:https://grpc.io/blog/grpc-on-dotnetcore/, .NET Co ...

  7. ASP.NET Core gRPC 入门全家桶

    一. 说明 本全家桶现在只包含了入门级别的资料,实战资料更新中. 二.官方文档 gRPC in Asp.Net Core :官方文档 gRPC 官网:点我跳转 三.入门全家桶 正片: ASP.NET ...

  8. ASP.NET Core gRPC 健康检查的实现方式

    一. 前言 gRPC 服务实现健康检查有两种方式,前面在此文 ASP.NET Core gRPC 使用 Consul 服务注册发现 中有提到过,这里归纳整理一下.gRPC 的健康检查,官方是定义了标准 ...

  9. 旧 WCF 项目迁移到 asp.net core + gRPC 的尝试

    一个月前,公司的运行WCF的windows服务器down掉了,由于 AWS 没有通知,没有能第一时间发现问题. 所以,客户提出将WCF服务由C#改为JAVA,在Linux上面运行:一方面,AWS对Li ...

随机推荐

  1. CentOS Redhat Linux安装 Oracle Client 的注意点

    1) 安装文件要拷贝到本地文件系统执行 2) 虽然不知道 libXmu是什么,但是安装之后,关联包安装了许多,感觉很省心 yum install libXmu.i686 3)  还有找不到的包的话,用 ...

  2. [Java学习] 强调一下编程风格

    讲完了Java的基础语法,大家就可以编写简单的程序代码了,这里有必要强调一下编程风格. 代码风格虽然不影响程序的运行,但对程序的可读性却非常重要.自己编写的程序要让别人看懂,首先在排版方面要非常注意. ...

  3. Sasha and a Very Easy Test CodeForces - 1109E (数学,线段树)

    大意: 给定n元素序列, q个操作: (1)区间乘 (2)单点除(保证整除) (3)区间求和对m取模 要求回答所有操作(3)的结果 主要是除法难办, 假设单点除$x$, $x$中与$m$互素的素因子可 ...

  4. Pavel and barbecue CodeForces - 756A (排列,水题)

    大意: 给定排列p, 0/1序列b, 有n个烤串, 每秒钟第i串会移动到$p_i$, 若$p_i$为1则翻面, 可以修改b和p, 求最少修改次数使得每串在每个位置正反都被烤过. 显然只需要将置换群合并 ...

  5. Liebig's Barrels CodeForces - 985C (贪心)

    链接 大意:给定$nk$块木板, 要制作$n$个$k$块板的桶, 要求任意两桶容积差不超过$l$, 每个桶的容积为最短木板长, 输出$n$个桶的最大容积和 假设最短板长$m$, 显然最后桶的体积都在$ ...

  6. java使用HttpClient

    HttpClient常用的包有两个 org.apache.http.client以及org.apache.commons.httpclient 我常用的是org.apache.http.client. ...

  7. @RunWith和 SpringJUnit4ClassRunner ---->junit4和Spring一起使用

    今天在看Spring的Demo的时候,看到了如此单元测试的写法 如下: @RunWIth(SpringJunit4ClassRunner.class) @ContextConfiguration(lo ...

  8. Adaboost入门教程——最通俗易懂的原理介绍(图文实例)

    https://blog.csdn.net/px_528/article/details/72963977 写在前面 说到Adaboost,公式与代码网上到处都有,<统计学习方法>里面有详 ...

  9. ArrayList Vector LinkedList(一)

    ArrayList Vector LinkedList 区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素, ...

  10. 重启oracle数据库的操作方法

    在实际的应用中,有时候工作数据库需要重新启动.本文介绍了一个特别实用的操作步骤,希望对大家有所帮助. 1. 停应用层的各种程序 2. 停Oralce的监听进程 $ lsnrctl stop 3. 在独 ...