.net core 用grpc实现微服务
GRPC 是Google发布的一个开源、高性能、通用RPC(Remote Procedure Call)框架。提供跨语言、跨平台支持。以下以.NET Core 使用控制台、docker中演示如何使用GRPC框架。
软件版本
.net core :1.0.1
GRPC:1.0.1-pre1
1.定义服务
使用proto3语法定义一个服务,主要测试package、import、常用类型的测试,
proto3语法: https://developers.google.com/protocol-buffers/docs/proto3
定义一个result.proto
syntax = "proto3";
package App.RPC.Model;
message Response{
bool sucess=1;
string message=2;
}
定义RPCDemoService.proto文件如下:
syntax = "proto3";
package App.RPC.Service;
import "result.proto";
service RPCDemoService{
rpc Add(DemoRequest) returns (App.RPC.Model.Response){}
rpc GetById(DemoId) returns (DemoRequest){}
rpc Get(Search) returns (DemoList){}
}
message DemoId{
int32 Id=1;
}
message Search{
int32 page=1;
int32 size=2;
string query=3;
}
message DemoRequest{
string Id=1;
int32 CommentId=2;
bool IsDeleted=3;
}
message DemoList{
repeated DemoRequest details = 1;
}
2.将服务生成类文件:
项目引用nuget包Grpc.Tools 1.0.0 或通过命令安装这个程序包,然后找到文件路径
先配置packages\Grpc.Tools\1.0.0\tools\windows_x64\protoc.exe环境变量
protoc.exe --csharp_out=d:\grpcdemo\code\ --grpc_out=d:\grpcdemo\code\ --plugin=protoc-gen-grpc=yourpath\.nuget\packages\Grpc.Tools\1.0.0\tools\windows_x64\grpc_csharp_plugin.exe result.proto
protoc.exe --csharp_out=d:\grpcdemo\code\ --grpc_out=d:\grpcdemo\code\ --plugin=protoc-gen-grpc=yourpath\.nuget\packages\Grpc.Tools\1.0.0\tools\windows_x64\grpc_csharp_plugin.exe RPCDemoService.proto
3.创建.net core 类型项目App.RPCDemo
Project.json文件内容如下:
{
"version": "1.0.0-*",
"dependencies": {
"Grpc.Tools": "1.0.0"
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50",
"dependencies": {
"NETStandard.Library": "1.6.0",
"Grpc": "1.0.1-pre1",
"Grpc.Core": "1.0.1-pre1",
"Google.Protobuf": "3.1.0",
"System.Interactive.Async": "3.0.0"
}
}
}
}
4.创建服务端App.RPCDemoServer
因为要在docker 中进行测试,官方网站并没有docker 下的例子,也没有说这个rpc在生产环境中如何hosting; 通过查看.net core的host源码在Microsoft.AspNetCore.Hosting.Internal.ApplicationLifetime这个类文件有实现,把这个文件的内容直接copy过来
类的部分内容如下:
private readonly CancellationTokenSource _startedSource = new CancellationTokenSource();
private readonly CancellationTokenSource _stoppingSource = new CancellationTokenSource();
private readonly CancellationTokenSource _stoppedSource = new CancellationTokenSource();
/// <summary>
/// Triggered when the application host has fully started and is about to wait
/// for a graceful shutdown.
/// </summary>
public CancellationToken ApplicationStarted => _startedSource.Token;
/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// Request may still be in flight. Shutdown will block until this event completes.
/// </summary>
public CancellationToken ApplicationStopping => _stoppingSource.Token;
/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// All requests should be complete at this point. Shutdown will block
/// until this event completes.
/// </summary>
public CancellationToken ApplicationStopped => _stoppedSource.Token;
google Grpc中的server类型没有接口,定义一个接口Iserver
namespace App.RPC.Core
{
public interface IServer
{
void Start();
void Stop();
Status State { get; set; }
}
public enum Status
{
None,
Stop,
Running
}
}
在创建一个hosting 文件内容如下:
public static class RpcHostExtensions
{
public static void Run(this IServer server)
{
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
Action shutdown = () =>
{
if (!cts.IsCancellationRequested)
{
server.Stop();
Console.WriteLine("Rpc Service is shutting down...");
cts.Cancel();
}
done.Wait();
};
#if NETSTANDARD1_5
var assemblyLoadContext = AssemblyLoadContext.GetLoadContext(typeof(WebHostExtensions).GetTypeInfo().Assembly);
assemblyLoadContext.Unloading += context => shutdown();
#endif
Console.CancelKeyPress += (sender, eventArgs) =>
{
shutdown();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
server.Run(cts.Token, "Rpc Service started. Press Ctrl+C to shut down.");
done.Set();
}
}
/// <summary>
/// Runs a web application and block the calling thread until token is triggered or shutdown is triggered.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
/// <param name="token">The token to trigger shutdown.</param>
public static void Run(this IServer server, CancellationToken token)
{
server.Run(token, shutdownMessage: null);
}
private static void Run(this IServer server, CancellationToken token, string shutdownMessage)
{
if (server.State != Status.Running)
{
server.Start();
}
var applicationLifetime = new ApplicationLifetime();
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
token.Register(state =>
{
((ApplicationLifetime)state).StopApplication();
},
applicationLifetime);
applicationLifetime.ApplicationStopping.WaitHandle.WaitOne();
}
}
实现服务RPCDemoImpl
public class RPCDemoImpl : RPCDemoService.RPCDemoServiceBase
{
public override Task<Response> Add(DemoRequest request, ServerCallContext context)
{
return Task.FromResult(new Response { Message = "成功" + context.Host + DateTime.Now.Ticks.ToString(), Sucess = true });
}
public override Task<DemoList> Get(Search request, ServerCallContext context)
{
var result = new DemoList();
result.Details.Add(new DemoRequest()
{
CommentId = 1,
Id = DateTime.Now.Ticks.ToString(),
IsDeleted = false
});
return Task.FromResult(result);
}
public override Task<DemoRequest> GetById(DemoId request, ServerCallContext context)
{
return Task.FromResult(new DemoRequest()
{
CommentId = request.Id,
Id = DateTime.Now.Ticks.ToString(),
IsDeleted = false
});
}
}
program文件如下:
public class Program
{
public static void Main(string[] args)
{
string host = "0.0.0.0";
int port = 9007;
var dic = Common.GetArgs(args);
if (dic != null && dic.Count > 0)
{
string tempHost;
string tempPort;
if (dic.TryGetValue("host", out tempHost))
{
host = tempHost;
}
if (dic.TryGetValue("port", out tempPort))
{
port = Convert.ToInt32(tempPort);
}
}
GrpcServer server = new GrpcServer
{
Services = { RPCDemoService.BindService(new RPCDemoImpl()) },
Ports = { new ServerPort(host, port, ServerCredentials.Insecure) }
};
Console.WriteLine("Google Grpc Starting");
foreach (var item in server.Ports)
{
Console.WriteLine(string.Format("RPC server {0} listening on port {1}", item.Host, item.Port));
}
server.Run();
}
}
编译发布后运行如下:

客户端程序
public static void Main(string[] args)
{
string host = "127.0.0.1";
string port = "9007";
long length = 10;
var dic = Common.GetArgs(args);
if (dic != null && dic.Count > 0)
{
string tempHost;
string tempPort, tempLength;
if (dic.TryGetValue("host", out tempHost))
{
host = tempHost;
}
if (dic.TryGetValue("port", out tempPort))
{
port = tempPort;
}
if (dic.TryGetValue("repeat", out tempLength))
{
length = Convert.ToInt64(tempLength);
}
}
Channel channel = new Channel(string.Format("{0}:{1}", host, port), ChannelCredentials.Insecure);
var client = new RPCDemoService.RPCDemoServiceClient(channel);
var stopwatch = Stopwatch.StartNew();
for (var i = 0; i < length; i++)
{
var reply = client.GetById(new DemoId() { Id = i });
Console.WriteLine("receive" + JsonConvert.SerializeObject(reply));
}
stopwatch.Stop();
Console.WriteLine(string.Format("repeat={0}, time={1} Milliseconds, time/repeat={2}", length, stopwatch.ElapsedMilliseconds, stopwatch.ElapsedMilliseconds / (float)length));
Console.ReadKey();
channel.ShutdownAsync().Wait();
}
编译发布运行如下:

Centos 7测试如下:
服务端
[demo@node139 App.RPCDemoServer]$ docker run --name rcpdemo -d -p 9007:9007 grpcemoserver
966b44acb2e0757c45b7dcf2d865e424dc764e50844e312ef2ea374999992a55
客户端
[demo@node139 App.RPCDemoClient]$ dotnet App.RPCDemoClient.dll host=192.168.190.139 port=9007 repeat=1
receive{"Id":"636138810040717530","CommentId":0,"IsDeleted":false}
docker中演示和源码地址:https://github.com/yjpgfwxf/App.GRPCDemo.NetCore
.net core 用grpc实现微服务的更多相关文章
- ASP.NET Core基于K8S的微服务电商案例实践--学习笔记
摘要 一个完整的电商项目微服务的实践过程,从选型.业务设计.架构设计到开发过程管理.以及上线运维的完整过程总结与剖析. 讲师介绍 产品需求介绍 纯线上商城 线上线下一体化 跨行业 跨商业模式 从0开始 ...
- 微服务优化之使用gRPC做微服务的内部通信
使用gRPC做微服务的内部通信 gRPC是一个由Google开源的远程服务调用框架,具有多路复用和双向流式通信的特性. 大家好,在本文中将为大家介绍为什么我们应该使用gRPC代替RESTful或JSO ...
- 使用 ASP.NET Core 3.1 的微服务开发指南
使用 ASP.NET Core 3.1 的微服务 – 终极详细指南 https://procodeguide.com/programming/microservices-asp-net-core/ A ...
- 如何基于gRPC沟通微服务框架
本文我们来讲解一下如何使用 gRPC构建微服务,gRPC是一个开源框架,可用于构建可扩展且高性能的微服务并创建服务之间的通信. 背景 随着企业越来越多地转向微服务,对构建这些微服务的低延迟和可扩展框架 ...
- AspNet Core Api Restful 实现微服务之旅 (一)
(一)了解微服务(二)搭建VS项目框架 (三)创建AspNet Core Api VS2017 安装包 链接:https://pan.baidu.com/s/1hsjGuJq 密码:ug59 创 ...
- python3和grpc的微服务探索实践
对于微服务的实践,一般都是基于Java和Golang的,博主最近研究了下基于Python的微服务实践,现在通过一个简单的服务来分析Python技术栈的微服务实践 技术栈:Python3 + grpc ...
- grpc 实现微服务生态笔记
微服务的发展可谓是一波三折,一代一代经历和N多技术成果,grpc只是其中一个,因为其东家是google,明显比较稳定.加上其强大的文档和技术支持和跨平台的支持,在企业级应用上有很大的可信任感,所以也有 ...
- 微服务架构攀登之路(四)之使用gRPC构建微服务
做一个处理用户信息的微服务 客户端通过用户名,可以从服务端查询用户的基本信息 gRPC proto user.proto 定义客户端请求.服务端响应的数据格式 user.pb.go 自动生成的,为数据 ...
- .NET Core 实践一:微服务架构的优点(转)
微服务现在已经是各种互联网应用首选的云架构组件,无论是 BAT 还是 滴滴.美团 ,微服务都是重要的一环. 相对于微服务,传统应用架构有以下缺点: 1. 业务代码混杂,团队成员职责边界不清,团队协作体 ...
随机推荐
- Sql Server之数据类型详解
数据类型是一种属性,用于指定对象可保存的数据的类型,SQL Server中支持多种数据类型,包括字符类型.数值类型以及日期类型等.数据类型相当于一个容器,容器的大小决定了装的东西的多少,将数据分为 ...
- uploadify上传错误:uncaught exception: call to startUpload failed原因
这个不是什么tab的问题,而是可能有多个上传的div或者input(含有相同的name或者ID)导致的 如果有两个不同的上传按钮,那么他们的name,id要设置得不一样. <div id='to ...
- jquer 事件,选择器,dom操作
一.jQuery简介 jQuery 是一个 JavaScript 库.(其实就是js,就是封装了,语法上有些不一样) jQuery 极大地简化了 JavaScript 编程. jQuery 库位于一个 ...
- 学C++的经验总结
下面的是学C++时要注意的. 1.把C++当成一门新的语言学习(和C没啥关系!真的.): 2.看<Thinking In C++>,不要看<C++变成死相>: 3.看<T ...
- 关于如何显示Jianshu图片的方案
问题的提出 简书是一个很好的博客网站,很多朋友都在jianshu上进行创作.当然出于各种目的,我们可能想将简书的文章同步到其他网站. 这个时候你会发现所有的文章里面的图片都无法正常显示了. 原因 如果 ...
- 【发布】工业串口和网络软件通讯平台(SuperIO v2.2.4)
SuperIO 下载:本站下载 百度网盘 更新说明: 1.修复无法把数据输出给IAppService的问题,以及无法触发删除操作事件. 2.侦听端口,可以设置. 3.设备接口,增加Object属性,方 ...
- Javascript:JSON总结
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于ECMAScript的一个子集,采用完全独立于语言的文本格式.这些特性使JSON成为理想的数据交换 ...
- linux下tomcat安全配置
转:http://www.tuicool.com/articles/R7fQNfQ 0x00 删除默认目录 安装完tomcat后,删除 $CATALINA_HOME/webapps 下默认的所有目录文 ...
- The habits of highly successful people
1.Morning Routine (早上列行公事) Probably the most common habit ultra-successful people have is they can t ...
- 【转载】实用的Javascript获取网页屏幕可见区域高度
本文转载原地址:这里 document.body.clientWidth ==> BODY对象宽度 document.body.clientHeight ==> BODY对象高度 docu ...