grpc入门(代码片段)

2ysp 2ysp     2022-12-31     296

关键词:

一、gRPC简介

在介绍gRPC之前先说一下RPC(Remote Procedure Call),也叫远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。相比HTTP协议来说,它主要是基于TCP/IP协议的的,传输效率更高,能够跨语言,典型的RPC框架有RMI、Hessian、Dubbo等。想要深入了解它们之间区别的话可以看这篇博客


gRPC由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。具备以下特性:

  1. 基于HTTP/2,HTTP/2 提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。gRPC 的协议设计上使用了HTTP2 现有的语义,请求和响应的数据使用HTTP Body 发送,其他的控制信息则用Header 表示。
  2. IDL使用ProtoBuf ,gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。
  3. 多语言支持(C, C++, Python, PHP, Nodejs, C#, Objective-C、Golang、Java),gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。

二、认识protocol buffers

2.1简介

protocol buffers(简称protobuf),是由google开源的,在 RPC (远程方法调用)里非常流行的二进制编解码格式,类似xml,json等。主要有以下几个优点:

  1. 性能好/效率高
  2. 代码生成机制,比如可以将proto文件编译为Java文件
  3. 支持多种编程语言
  4. 支持“向后兼容”和“向前兼容”

2.2语法

2.2.1 定义一个消息类型

syntax = "proto3";

message SearchRequest 

  required string query = 1;

  optional int32 page_number = 2;

  optional int32 result_per_page = 3;


第一行指定了使用proto3语法,如果没有指定,编译器会使用proto2。这个指定语法行必须是文件的非空非注释的第一个行。

SearchRequest相当于我们Java中的一个实体类,里面有三个字段分别为String 类型query,int类型page_number和int类型result_per_page。

后面的数字1,2,3是标识号,必须从1开始。这些标识符是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改 变。注:[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号

字段的第一个是修饰符,必须是required,optional,repeated其中一个

  1. required:一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的;
  2. optional:表示可选的,可以有值也可以没有。
  3. repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于java中的List;

字段类型与Java类型对应关系如下图:
技术分享图片

2.2.2 定义一个服务(service)

如果想要将消息类型用在RPC(远程方法调用)系统中,可以在.proto文件中定义一个RPC服务接口,protocol buffer编译器将会根据所选择的不同语言生成服务接口代码及存根。如,想要定义一个RPC服务并具有一个方法,该方法能够接收 SearchRequest并返回一个SearchResponse,此时可以在.proto文件中进行如下定义:

service SearchService 

  rpc Search (SearchRequest) returns (SearchResponse);


更多相关语法可以查看这篇博客

三、完成Hello World

项目结构如图:
技术分享图片

3.1新建项目

新建一个maven项目grpc_demo,然后在pom文件引入grpc和代码生成插件,内容如下。

  1. <properties> 
  2. <grpc.version>1.0.3</grpc.version> 
  3. </properties> 
  4.  
  5. <dependencies> 
  6. <dependency> 
  7. <groupId>io.grpc</groupId> 
  8. <artifactId>grpc-netty</artifactId> 
  9. <version>$grpc.version</version> 
  10. </dependency> 
  11. <dependency> 
  12. <groupId>io.grpc</groupId> 
  13. <artifactId>grpc-protobuf</artifactId> 
  14. <version>$grpc.version</version> 
  15. </dependency> 
  16. <dependency> 
  17. <groupId>io.grpc</groupId> 
  18. <artifactId>grpc-stub</artifactId> 
  19. <version>$grpc.version</version> 
  20. </dependency> 
  21. </dependencies> 
  22.  
  23. <build> 
  24. <extensions> 
  25. <extension> 
  26. <groupId>kr.motd.maven</groupId> 
  27. <artifactId>os-maven-plugin</artifactId> 
  28. <version>1.4.1.Final</version> 
  29. </extension> 
  30. </extensions> 
  31. <plugins> 
  32. <plugin> 
  33. <groupId>org.xolstice.maven.plugins</groupId> 
  34. <artifactId>protobuf-maven-plugin</artifactId> 
  35. <version>0.5.0</version> 
  36. <configuration> 
  37. <protocArtifact>com.google.protobuf:protoc:3.1.0:exe:$os.detected.classifier</protocArtifact> 
  38. <pluginId>grpc-java</pluginId> 
  39. <pluginArtifact>io.grpc:protoc-gen-grpc-java:$grpc.version:exe:$os.detected.classifier</pluginArtifact> 
  40. </configuration> 
  41. <executions> 
  42. <execution> 
  43. <goals> 
  44. <goal>compile</goal> 
  45. <goal>compile-custom</goal> 
  46. </goals> 
  47. </execution> 
  48. </executions> 
  49. </plugin> 
  50. </plugins> 
  51. </build> 

3.2编写proto文件

syntax = "proto3";


option java_multiple_files = true;
//定义包名
option java_package = "cn.sp.helloworld";
//定义生成的类名称
option java_outer_classname = "HelloWorldProto";

option objc_class_prefix = "HLW";



package helloworld;

// The greeting service definition.

service Greeter 
  
    // Sends a greeting
  
    rpc SayHello (HelloRequest) returns (HelloReply) 




// The request message containing the user‘s name.

message HelloRequest 
 
     string name = 1;




// The response message containing the greetings

message HelloReply 
  
    string message = 1;


运行命令mvn clean compile,就可以看到编译后生成的Java文件。
控制台输出:
技术分享图片
目录结构
技术分享图片
将这些代码复制到src/main/java/cn/sp目录下

3.3完成HelloWorldClient和HelloWorldServer

客户端代码

  1. package cn.sp.client; 
  2.  
  3. import cn.sp.GreeterGrpc; 
  4. import cn.sp.HelloReply; 
  5. import cn.sp.HelloRequest; 
  6. import io.grpc.ManagedChannel; 
  7. import io.grpc.ManagedChannelBuilder; 
  8. import io.grpc.StatusRuntimeException; 
  9.  
  10. import java.util.concurrent.TimeUnit; 
  11.  
  12. public class HelloWorldClient  
  13.  
  14. //一个gRPC信道 
  15. private final ManagedChannel channel; 
  16.  
  17.  
  18. private final GreeterGrpc.GreeterBlockingStub blockingStub;//阻塞/同步 存根 
  19.  
  20. //初始化信道和存根 
  21. public HelloWorldClient(int port,String host) 
  22. this(ManagedChannelBuilder.forAddress(host,port).usePlaintext(true)); 
  23.  
  24.  
  25. private HelloWorldClient(ManagedChannelBuilder<?> channelBuilder) 
  26. channel = channelBuilder.build(); 
  27. blockingStub = GreeterGrpc.newBlockingStub(channel); 
  28.  
  29.  
  30. public void shutDown()throws InterruptedException 
  31. channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); 
  32.  
  33.  
  34. //客户端方法 
  35. public void greet(String name) 
  36. HelloRequest request = HelloRequest.newBuilder().setName(name).build(); 
  37. HelloReply response; 
  38. try 
  39. response = blockingStub.sayHello(request); 
  40. catch (StatusRuntimeException e) 
  41. System.out.println("RPC调用失败:"+e.getMessage()); 
  42. return
  43.  
  44.  
  45. System.out.println("服务器返回信息:"+response.getMessage()); 
  46.  
  47.  
  48. public static void main(String[] args)throws Exception  
  49. HelloWorldClient client = new HelloWorldClient(50051,"127.0.0.1"); 
  50. try  
  51. for (int i=0;i<5;i++) 
  52. client.greet("world:"+i); 
  53.  
  54. finally  
  55. client.shutDown(); 
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  

服务器端代码

  1. package cn.sp.server; 
  2.  
  3. import cn.sp.GreeterGrpc; 
  4. import cn.sp.HelloReply; 
  5. import cn.sp.HelloRequest; 
  6. import io.grpc.Server; 
  7. import io.grpc.ServerBuilder; 
  8. import io.grpc.stub.StreamObserver; 
  9.  
  10. public class HelloWorldServer  
  11.  
  12.  
  13. private int port = 50051
  14. private Server server; 
  15.  
  16. /** 
  17. * 启动服务 
  18. * @throws Exception 
  19. */ 
  20. private void start()throws Exception 
  21. server = ServerBuilder.forPort(port) 
  22. .addService(new GreeterImpl()) 
  23. .build().start(); 
  24. System.out.println("service start ...."); 
  25. Runtime.getRuntime().addShutdownHook(new Thread() 
  26. @Override 
  27. public void run()  
  28. System.err.println("*** shutting down gRPC server since JVM is shutting down"); 
  29. HelloWorldServer.this.stop(); 
  30. System.err.println("*** server shut down"); 
  31.  
  32. ); 
  33.  
  34.  
  35. private void stop() 
  36. if (server != null
  37. server.shutdown(); 
  38.  
  39.  
  40. // block 一直到程序退出 
  41. private void blockUntilShutDown()throws InterruptedException 
  42. if (server != null
  43. server.awaitTermination(); 
  44.  
  45.  
  46.  
  47. // 定义一个实现服务接口的类 
  48. private class GreeterImpl extends GreeterGrpc.GreeterImplBase 
  49.  
  50. public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) 
  51. System.out.println("收到的信息:"+req.getName()); 
  52.  
  53. //这里可以放置具体业务处理代码 start 
  54. //这里可以放置具体业务处理代码 end 
  55.  
  56. //构造返回 
  57. HelloReply reply = HelloReply.newBuilder().setMessage("Hello: " + req.getName()).build(); 
  58. responseObserver.onNext(reply); 
  59. responseObserver.onCompleted(); 
  60.  
  61.  
  62.  
  63. public static void main(String[] args)throws Exception  
  64. HelloWorldServer server = new HelloWorldServer(); 
  65. server.start(); 
  66. server.blockUntilShutDown(); 
  67.  
  68.  
  69.  

3.4运行测试

先运行服务端的main方法,再运行客户端,可以看到服务端控制台输出信息如下:

service start ....
收到的信息:world:0
收到的信息:world:1
收到的信息:world:2
收到的信息:world:3
收到的信息:world:4

客户端控制台输出信息:

服务器返回信息:Hello: world:0
服务器返回信息:Hello: world:1
服务器返回信息:Hello: world:2
服务器返回信息:Hello: world:3
服务器返回信息:Hello: world:4

说明客户端发出的五次问候请求服务端都接收到了,并且返回了响应。

四、总结

gRPC中proto文件的编写就显得十分重要了,要多加注释相当于接口文档,目前代码调用过程看着貌似有些复杂,后面整合SpringBoot之后就很简单了,不过我还是喜欢HTTP。。。。

grpc学习入门(代码片段)

grpc框架参考资料:官方文档教学grpc-go入门https://www.cnblogs.com/hongjijun/p/13724738.htmlGRPC是Google公司基于Protobuf开发的跨语言的、高性能的、通用的开源RPC框架。GRPC基于HTTP/2协议设计,可以基于一个HTTP/2链接提供多个服务,... 查看详情

grpc入门(代码片段)

一、gRPC简介在介绍gRPC之前先说一下RPC(RemoteProcedureCall),也叫远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。相比HTTP协议来说,它主要是基于TCP/IP协议的的,传输效率更... 查看详情

window下golang使用grpc入门案例(代码片段)

一、检查golang的安装环境https://golang.org/dl/需要墙,或者在这里下载https://pan.baidu.com/s/12tTmrVIel6sfeBInpt9lQA最新版本1.10下载msi安装即可goversion验证安装 查看详情

grpc入门与实操(.net篇)(代码片段)

为什么选择gRPC历史长久以来,我们在前后端交互时使用WebApi+JSON方式,后端服务之间调用同样如此(或者更久远之前的WCF+XML方式)。WebApi+JSON是优选的,很重要的一点是它们两者都是平台无关的三方标准,且足够语义化,便于程... 查看详情

grpc入门(代码片段)

1.gRPC简介gRPC是一种高性能、开源和通用的远程过程调用(RPC)框架,由Google开源并维护。它使用ProtocolBuffers(protobuf)作为接口定义语言(IDL),提供跨平台、跨语言的RPC调用支持。gRPC具有以下几个特点:高性能:使用HTTP/2协... 查看详情

grpc入门与实操(.net篇)(代码片段)

为什么选择gRPC历史长久以来,我们在前后端交互时使用WebApi+JSON方式,后端服务之间调用同样如此(或者更久远之前的WCF+XML方式)。WebApi+JSON是优选的,很重要的一点是它们两者都是平台无关的三方... 查看详情

高质量通信grpc入门,有了它,谁还用socket(代码片段)

1含义RPC(remoteprocedurecall远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样。gRPC是一个高性能、... 查看详情

一个简单的案例入门grpc(代码片段)

这篇文章本来要在年前和小伙伴们见面,但是因为我之前的Mac系统版本是10.13.6,这个版本比较老,时至今天在运行一些新鲜玩意的时候有时候会有一些BUG(例如运行最新版的Nacos等),运行gRPC的插件也有BU... 查看详情

一个简单的案例入门grpc(代码片段)

这篇文章本来要在年前和小伙伴们见面,但是因为我之前的Mac系统版本是10.13.6,这个版本比较老,时至今天在运行一些新鲜玩意的时候有时候会有一些BUG(例如运行最新版的Nacos等),运行gRPC的插件也有BU... 查看详情

3.微服务--grpc(代码片段)

1.gRPC入门1.1gRPC简介gRPC由google开发,是一款语言中立、平台中立、开源的远程过程调用系统gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用1.2gRPC与Protobuf介绍微服务架构中,... 查看详情

grpc与boto3理解与使用(代码片段)

文章目录gRPCBoto3gRPCPythongRPC入门按照上面那个例子运行,下面主要讲讲遇到的问题和发现的一些事情python中运行client有问题,可以加入下面的代码解决os.environ['http_proxy']=""os.environ['https_proxy']="... 查看详情

grpc快速入门——protobuf序列化原理解析(代码片段)

gRPC快速入门(二)——Protobuf序列化原理解析一、Protobuf序列化原理简介1、序列化序列化是将数据结构或对象转换成二进制字节流的过程。Protobuf对于不同的字段类型采用不同的编码方式和数据存储方式对消息字段进行序列化,... 查看详情

grpc(代码片段)

文章引自 gRPC快速入门gRPCRPC是什么在分布式计算,远程过程调用(英语:RemoteProcedureCall,缩写为RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的... 查看详情

grpc,protoc,protoc-gen-go,rust(代码片段)

...ps://segmentfault.com/a/1190000015042409  SpringBoot中使用grpc入门https://www.cnblogs.com/sevenyuan/p/8535382.html protobuffer、gRPC、restfulgRPC的相互转化Howtofixthisissuewithgrpcmethodhandler8Basicallyyourprotoc-gen-godoesn‘tmatcht 查看详情

漫谈grpc2:实战grpc,跨语言的rpc框架到底好不好用,试试就知道(代码片段)

...个HTTP/2链接提供多个服务,对于移动设备更加友好。入门首先来看一个最简单的gRPC服务,第一步是定义proto文件,因为gRPC也是C/S架构,这一步相当于明确接口规范。protosyntax = "proto3";package proto;// The gr... 查看详情

深入浅出掌握grpc通信框架(代码片段)

...架,为了弄清楚Alluxio服务端的线程模型,必然需要对Grpc代码有所掌握。本文先介绍Grpc底层HTTP2的知识,通过一个GRPC项目,深入GRPC源码,探索GRPC的线程模型。2.Grpc简介GRPC是Google推出的RPC框架。并且支持多种语言。GRPC的几种模... 查看详情

gogrpc入门(代码片段)

前言最近较忙,其实准备一篇搞定的中途有事,只能隔了一天再写正文pb.go需要注意的是,在本个demo中,客户端与服务端都是Golang,所以在客户端与服务端都公用一个pb.go模板文件(如果是不同的语言生成的pb是对应语言),可以将pb.go文件... 查看详情

grpc安装(代码片段)

安装请参考官方资料-快速开始,安装gRPC需要安装Go、protocolbuffer、protoc-gen-go、gRPC等。1.安装Go,grpc是用Golang开发的,所以需要安装Go;2.下载protocolbuffer,这是gRPC的协议编译工具,写好proto之后,需要用这个编译。windows下直接下... 查看详情