.NET Core 使用 grpc 实现微服务

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

一、定义服务

通过proto定义一个数学计算服务,其中包括两个服务方法(Add, Multipy)以及4个请求响应对象(AddRequest, AddReply, MultiplyRequest, MultiplyReply)。

// 文件名:mathservice.protosyntax = "proto3";
option java_multiple_files = false;
option java_package = "MathServices";
option java_outer_classname = "MathServicesProto";
option objc_class_prefix = "MathServices";
package MathServices;// 数学运算服务service MathService {  
    rpc Add (AddRequest) returns (AddReply) {}  rpc Multiply (MultiplyRequest)
   returns (MultiplyReply)
{} } message AddRequest {  double First = 1;  double Second = 2; } message AddReply {  double Sum = 1; } message MultiplyRequest {  double First = 1;  double Second = 2; } message MultiplyReply {  double Result = 1; }

二、将服务编译成存根(stub)

通过以下批处理命令generate_protos.bat将服务定义生成多种语言和平台版本的客户端和服务端存根。

@rem 生成客户端和服务器端存根setlocal@rem 进入当前目录
cd /d %~dp0set TOOLS_PATH=C:\Users\Freeman\.nuget\packages\Grpc.Tools\1.0.0\tools\windows_x86 %TOOLS_PATH%\protoc.exe ^--proto_path protos ^--cpp_out=Interfaces/cpp ^--csharp_out=Interfaces/csharp ^--java_out=Interfaces/java ^--js_out=Interfaces/javascript ^--grpc_out=Interfaces/csharp ^--plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe ^protos/mathservice.proto endlocaltimeout 5

针对CSHARP语言,protoc.exe编译器生成了如下图几个类,其中左边4个类用于构造请求和响应对象,MathService类用于下一步构造服务和消费服务。


CSHARP STUBS

三、实现并运行服务

通过上一步的编译,自动生成了MathService类,下面通过该类构造并启动grpc服务。

通过继承基类实现服务接口

    /// <summary>/// 实现RPC服务端接口。/// </summary>public class MathServiceImpl : MathService.MathServiceBase{public override Task<AddReply> Add(AddRequest request, ServerCallContext context){        
            return Task.FromResult(new AddReply { Sum = request.First + request.Second });}public override Task<MultiplyReply> Multiply(MultiplyRequest request, ServerCallContext context){        
             return Task.FromResult(new MultiplyReply { Result = request.First * request.Second });}}

启动服务

const string ip = "0.0.0.0";const int port = 50051;
Server server = new Server();
server.Ports.Add(new ServerPort(ip, port, ServerCredentials.Insecure));
server.Services.Add(MathService.BindService(new MathServiceImpl()));
server.Start();
server.Ports.ToList().ForEach(a => Console.WriteLine($"Server listening on port {a.Port}..."));
Console.ReadLine();

四、客户端调用服务

客户端通过创建一个Channel和一个服务客户端来使用服务。

var channel = new Channel($"{"127.0.0.1"}:{port}", SslCredentials.Insecure);
var client = new MathService.MathServiceClient(channel);
var random = new Random();while (true) {    var first = random.NextDouble();    
      var second = random.NextDouble();  
     var reply = client.Add(new AddRequest { First = first, Second = second });  
     Console.WriteLine($"RPC call Add service: {first:F4} + {second:F4} = {reply.Sum:F4}");    Thread.Sleep(500); }


RPC调用

五、使用SSL实现加密通讯

grpc默认实现了基于证书的SSL加密通讯,使用中需要注意以下事项。

  • 在Windows上开发请安装 OpenSSL对应版本并将openssl.exe所在路径添加到环境变量中。

  • 通过以下样例脚本生成通讯中所需要的服务端和客户端证书,其中需要特别注意的是,Generate server signing request:中的CN=KEKYK字段如果是本机测试,请一定使用本机名称,如果是真实环境请使用域名,因为客户端必须通过机器名(本地测试)或域名访问该服务。如果此处CN字段不使用机器名或域名,将导致以下错误:


    CN字段不使用主机名或域名时产生的错误

  • 生成服务端和客户端证书脚本generate_ssl.bat

@echo offset OPENSSL_CONF=c:\OpenSSL-Win64\bin\openssl.cfg   echo Generate CA key: openssl genrsa -passout pass:1111 -des3 -out ca.key 4096echo Generate CA certificate: openssl req -passin pass:1111 -new -x509 -days 365 -key ca.key -out ca.crt -subj  "/C=US/ST=CA/L=Cupertino/O=YourCompany/OU=YourApp/CN=MyRootCA"echo Generate server key: openssl genrsa -passout pass:1111 -des3 -out server.key 4096echo Generate server signing request: openssl req -passin pass:1111 -new -key server.key -out server.csr -subj  "/C=US/ST=CA/L=Cupertino/O=YourCompany/OU=YourApp/CN=kekyk"echo Self-sign server certificate: openssl x509 -req -passin pass:1111 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt echo Remove passphrase from server key: openssl rsa -passin pass:1111 -in server.key -out server.keyecho Generate client keyopenssl genrsa -passout pass:1111 -des3 -out client.key 4096echo Generate client signing request: openssl req -passin pass:1111 -new -key client.key -out client.csr -subj  "/C=US/ST=CA/L=Cupertino/O=YourCompany/OU=YourApp/CN=client"echo Self-sign client certificate: openssl x509 -passin pass:1111 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt echo Remove passphrase from client key: openssl rsa -passin pass:1111 -in client.key -out client.keypause
  • 基于SSL的服务端启动如下,创建服务的时候请使用主机名(开发环境)或域名(生产环境),不要使用IP地址。

    public static void RpcServerSsl()
    {  
        var cacert = File.ReadAllText(CombinePath("ca.crt")); 
       var servercert = File.ReadAllText(CombinePath("server.crt"));  
      
        var serverkey = File.ReadAllText(CombinePath("server.key")); 
      var keypair = new KeyCertificatePair(servercert, serverkey); 
     
      var sslCredentials = new SslServerCredentials(new List<KeyCertificatePair>() 
     
         { keypair }, cacert, false);  
       
       var server = new Server{Services = { MathService.BindService(new MathServiceImpl()) },Ports = { new ServerPort("KEKYK", sslPort, sslCredentials) }};server.Start();server.Ports.ToList().ForEach(a => Console.WriteLine($"Server (SSL) listening on port {a.Port}..."));Console.ReadLine();
    }
  • 基于SSL的客户端使用如下,注意测试环境中使用主机名,生产环境中使用域名来,不要使用任何形式的IP地址。

    public static void RpcClientSsl(){  
       var cacert = File.ReadAllText(CombinePath("ca.crt")); 
      var clientcert = File.ReadAllText(CombinePath("client.crt")); 
     
      var clientkey = File.ReadAllText(CombinePath("client.key"));  
     
       var ssl = new SslCredentials(cacert, new KeyCertificatePair(clientcert, clientkey)); 
      var channel = new Channel("KEKYK", sslPort, ssl);  
     
       var client = new MathService.MathServiceClient(channel);  
       var random = new Random();  while (true){      
             var first = random.NextDouble();   
           var second = random.NextDouble();      
          
             var reply = client.AddAsync(new AddRequest { First = first, Second = second }, 
               new CallOptions()).ResponseAsync.Result;Console.WriteLine($"RPC call Add service: {first:F4} + {second:F4} = {reply.Sum:F4}");Thread.Sleep(1000);}
    }

原文地址:http://www.jianshu.com/p/f5e1c002047a


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

范式 第一 第二 第三范式

第一范式&#xff08;每个数据项不可分&#xff09; 如果一个关系模式R的所有属性都是不可分的基本数据项&#xff0c;则R∈1NF&#xff08;即R符合第一范式&#xff09;。 第二范式 &#xff08;没有部分依赖&#xff09; 若关系模式R∈1NF&#xff08;即R符合第一范式&a…

Vue.js2.0开发环境搭建(四)

转载自 vuejs2.0从入门到放弃--入门实例&#xff08;四&#xff09;最近&#xff0c;很多小伙伴有疑惑&#xff0c;想学vuejs必须先了解复杂的构建工具和命令行操作吗&#xff01;&#xff01;答案是否定的&#xff01; 对于很多做前端的同学&#xff0c;涉及到命令行和构建工…

微信小程序父级之间的传值_微信小程序自定义组件封装及父子间组件传值的方法...

首先在我们可以直接写到需要的 page 中&#xff0c;然后再进行抽取组件&#xff0c;自定义组件建议wxzx-xxx命名例如&#xff0c;我们封装的组件名为 **wxzx-loadmorewxzx-loadmore.wxml正在加载{{tip}}这里就是把index.wxml中的需要封装成组件的代码原样copy过来wxzx-loadmore…

[公测]微信小程序设计指南文档

微信小程序开放了。不要在意名额&#xff0c;一定要加大专注度。并保持良好的想法以及意识&#xff0c;扩大认知范围&#xff0c;这样才能占得先机。程序上的事我不懂&#xff0c;设计文档还是有必要看一看。文档并没有讲如何更漂亮。只是从人性化的角度去讲&#xff0c;如何让…

多线程----join插队

package com.kuang.demo05; public class TestJoin implements Runnable {Overridepublic void run() {for (int i 0; i <10 ; i) {System.out.println("VIP线程来插队了&#xff01;&#xff01;&#xff01;"i);}}public static void main(String[] args) thro…

联通 培训 c班还 20190814

看我的ppt是没有很多文字的 文字都在心里 电脑比较旧 可以装一个Linux 还能用 还是装xp把 电脑旧可以在咸鱼上买一个ssd&#xff0c;还能用很久。 Linux 目录每个用户都一样 不可以修改 ps -ef | sudo service sudo 授权 一般都是普通用户 docker 启动就类似模拟…

Vue开源项目库汇总

转载自 Vue开源项目库汇总最近做了一个Vue开源项目库汇总&#xff0c;里面集合了OpenDigg 上的优质的Vue开源项目库&#xff0c;方便移动开发人员便捷的找到自己需要的项目工具等&#xff0c;感兴趣的可以到GitHub上给个star。 UI组件 element ★9305 - 饿了么出品的Vue2的web…

PL/SQL经典练习

/* PL/SQL编程*/--先把scott里面的表弄到test表空间里面来 CREATE TABLE EMP ASSELECT * FROM SCOTT.EMP; CREATE TABLE DEPT ASSELECT * FROM SCOTT.DEPT; /* 上机1 */ --&#xff08;1&#xff09;计算King所交税金DECLARE V_SHUIJIN NUMBER; --应交税金V_SA…

alertmanager 告警恢复_Prometheus配置企业微信告警

kubernetes operator安装的&#xff0c;如果不会可看上一篇文章前提&#xff1a;创建企业微信&#xff0c;创建应用然后配置altermanager.yamlglobal:resolve_timeout: 5m receivers: - name: wechatwechat_configs:- agent_id: "100000x"api_secret: Nm7PRrxxxxG8Ep…

IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API

IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API。 使用IdentityServer4 来实现使用客户端凭据保护ASP.NET Core Web API 访问。 IdentityServer4 GitHub: https://github.com/IdentityServer/IdentityServer4 IdentityServer 框架支持以下功能&…

JAVA多线程总结(笔记)

线程的特点 线程就是独立的执行路径&#xff1b;在线程运行时&#xff0c;即使没有自己创建线程&#xff0c;后台也会有多个线程&#xff0c;如主线程&#xff0c;gc线程&#xff1b;main()称之为主线程&#xff0c;为系统的入口&#xff0c;用于执行整个程序&#xff1b;在一…

很有道理的内容

男生选女朋友最看重的是什么? 病毒营销陈轩 被赞同30万&#xff0c;被收藏24万&#xff0c;顶级病毒营销专家&#xff0c;加个人微信送书 12,540 人也赞同了该回答 有女孩给我发私信&#xff1a; “我是个很好的女孩&#xff0c;漂亮身材好&#xff0c;白领一枚&#xff0c…

学python后做什么工作好_学习完Python课程后可以做什么工作?

Python作为人工智能、大数据的首选编程语言&#xff0c;也是进入编程世界的理想选择&#xff0c;已经成为了大家都在追求学习的语言&#xff0c;那么学习Python之后到底可以做什么呢?为您详细的介绍一下。什么是Python?Python是一种面向对象解释型计算机程序设计语言。而且Py…

vue-beauty 的v-data-table数据单元不换行

原因由于css样式 .ant-table-tbody>tr>td, .ant-table-thead>tr>th {padding: 16px 8px;word-break: keep-all;white-space: nowrap; /*强制不换行*/ } 只需覆盖white-space的值就可以 如&#xff1a; .ant-table-tbody>tr>td {white-space:normal } 补…

用Middleware给ASP.NET Core Web API添加自己的授权验证

Web API&#xff0c;是一个能让前后端分离、解放前后端生产力的好东西。不过大部分公司应该都没能做到完全的前后端分离。API的实现方式有很 多&#xff0c;可以用ASP.NET Core、也可以用ASP.NET Web API、ASP.NET MVC、NancyFx等。说到Web API&#xff0c;不同的人有不同的做法…

公司电脑重装经验 ThinkPad E480 win7重装 电脑重装

***************************下面是20200813更新的****************************** 1.电脑的机械盘老是掉线 要重启才能找到 不用了 还是用自己的移动硬盘代替公司的D盘吧 拷贝也很慢 2.公司的c盘菜120G太小 就只安装必须使用的软件 外接移动硬盘代替电脑的D盘 可以用…

Java 内存泄露以及避免方法

转载自 Java 内存泄露以及避免方法 内存泄露: 是指在程序运行过程中会不断的分配内存空间&#xff0c;那些不再使用的内存空间应该即时回收它们&#xff0c;从而保证可以保证系统可以再次使用这些内存。如果存在无用的内存没有被收回来&#xff0c;那就是内存泄露。 说明…

Tomacat乱码解决

解决方法 解决后

体验Rabbitmq强大的【优先级队列】之轻松面对现实业务场景

说到队列的话&#xff0c;大家一定不会陌生&#xff0c;但是扯到优先级队列的话&#xff0c;还是有一部分同学是不清楚的&#xff0c;可能是不知道怎么去实现吧&#xff0c;其实呢&#xff0c;&#xff0c;&#xff0c;这东西已经烂大街了。。。很简单&#xff0c;用“堆”去实…

jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令

转载自 jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令 1&#xff0e;Jstack 1.1 jstack能得到运行java程序的java stack和native stack的信息。可以轻松得知当前线程的运行情况。如下图所示 注&#xff1a;这个和thread dump是同样的结果。但是thread dump是用ki…