ProtoBuf的介绍以及在Java中使用protobuf将对象进行序列化与反序列化:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108667427
Thrift介绍以及Java中使用Thrift实现RPC示例:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108689413
之前讲过Protobuf以及Thrift,下面介绍GPRC。
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
gPRC
gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持。
gRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。
在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制。
gRPC的Github:
https://github.com/grpc
gPRC-JAVA:
https://github.com/grpc/grpc-java
Java中实现GRPC通信
IDEA中新建Maven项目,然后来到gRPC-java的官方的github中将示例中的依赖复制到项目中
<dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty-shaded</artifactId> <version>1.32.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.32.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.32.1</version> </dependency> </dependencies>
因为gRPC是基于protobuf的,同样要将.proto文件编译成代码。
所以按照其github的指示,引入Maven插件
<build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.2</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.32.1:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
至此完整的pom文件代码
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.badao.grpc</groupId> <artifactId>hellogrpc</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty-shaded</artifactId> <version>1.32.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.32.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.32.1</version> </dependency> </dependencies> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.2</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.32.1:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
待导入完成后。
会在右边Maven面板中的Plugins下多出protobuf插件
然后就是在项目下新建src/main/proto目录,此插件会去此目录下找proto文件,在此目录下新建Person.proto
syntax = "proto3"; package com.badao.proto; option optimize_for =SPEED;option java_package = "com.badao.grpcjava";option java_outer_classname = "BadaoDataInfo";option java_multiple_files = true; service PersonService { rpc GetRealNameByUsername(MyRequest) returns (MyResponse) {}} message MyRequest { string username = 1;} message MyResponse { string realname = 2;}
这里的proto文件使用的是proto3的语法,这里的写法可以将github的代码克隆下来,然后参考其grpc-java\examples\src\main\proto
目录下的写法。
这里描述文件的意思就是定义一个接口PersonService,借口内的方法是GetRealNameByUsername,方法参数是自定义请求参数,方法响应是自定义响应。
下面的message就是java中的类,分别是自定义的请求实体和响应实体,以及对应的属性。
然后就是生成代码。
依次双击上面Maven面板插件中的protobuf:complie和protobuf:compile-custom
就会在target下生成对应的实体和相关的请求响应通信相关的类。
gRPC服务端搭建
在src/main/java下新建包com,badao.grpcjava,包下新建PersonServiceImpl类使其继承 PersonServiceGrpc.PersonServiceImplBase
然后重写其方法getRealNameByUsername对具体的根据昵称获取真实名字的具体实现。
package com.badao.grpcjava; import io.grpc.stub.StreamObserver; public class PersonServiceImpl extends PersonServiceGrpc.PersonServiceImplBase { @Override public void getRealNameByUsername(MyRequest request, StreamObserver<MyResponse> responseObserver) { System.out.println("接收到的客户端消息为:"+request.getUsername()); responseObserver.onNext(MyResponse.newBuilder().setRealname("公众号:霸道的程序猿").build()); responseObserver.onCompleted(); }}
然后新建服务端GrpcServer类
package com.badao.grpcjava; import io.grpc.Server;import io.grpc.ServerBuilder; import java.io.IOException; public class GrpcServer { private Server server; private void start() throws IOException { this.server = ServerBuilder.forPort(8899).addService(new PersonServiceImpl()).build().start(); System.out.println("GRPC Java服务端启动"); Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { public void run() { System.out.println("关闭JVM"); GrpcServer.this.stop(); } })); System.out.println("执行到这里"); } private void stop(){ if(null!=this.server){ this.server.shutdown(); } } private void awaitTermination() throws InterruptedException { if(null!=this.server){ this.server.awaitTermination(); } } public static void main(String[] args) throws IOException, InterruptedException { GrpcServer server = new GrpcServer(); server.start(); server.awaitTermination(); }}
这块的服务端的搭建可以参考gihub上示例代码的grpc-java\examples\src\main\java\io\grpc\examples\helloworld
目录下的服务和客户端的示例代码
gRPC客户端的搭建
在上面新建的包下新建GrpcClient客户端类
package com.badao.grpcjava; import io.grpc.ManagedChannel;import io.grpc.ManagedChannelBuilder; public class GrpcClient { public static void main(String[] args) { ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",8899) .usePlaintext().build(); PersonServiceGrpc.PersonServiceBlockingStub blockingStub = PersonServiceGrpc.newBlockingStub(managedChannel); MyResponse myResponse = blockingStub.getRealNameByUsername(MyRequest.newBuilder().setUsername("公众号:霸道的程序猿").build()); System.out.println(myResponse.getRealname()); }}
然后运行服务端的主方法后
然后再运行客户端的main方法
此时再查看服务端