RPC(Remote Procedure Call)是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
之前本人介绍过Java简单实现RPC的例子,这里将继续介绍如何快速使用工业级别的RPC技术gRPC。
gRPC是谷歌搞的一个RPC协议,它配套protobuf使用。用户可以通过protobuffer自定义传输数据的格式。
使用过程可以概述为三点:
- 在.proto文件中定义服务。
- 使用协议缓冲区编译器生成服务器和客户端代码。
- 使用Java gRPC API为您的服务编写一个简单的客户端和服务器

新建maven项目,并导入pom文件
<dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty-shaded</artifactId> <version>1.23.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.23.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.23.0</version> </dependency><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.10.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.23.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>新建proto文件
syntax = "proto3"; package com.chenqh.proto; // 生成代码所在包 option java_package = "com.chenqh.proto"; // 生成代码类名 option java_outer_classname = "StudentProto"; option java_multiple_files = true; service StudentService{ rpc GetRealNameByUsername(MyRequest) returns (MyResponse){} } message MyRequest { string username = 1; } message MyResponse { string realname = 2; }执行命令
mvn generate-sources
生成接口如下所示

服务端实现接口
package grpc; import com.chenqh.proto.MyRequest; import com.chenqh.proto.MyResponse; import com.chenqh.proto.StudentServiceGrpc; import io.grpc.stub.StreamObserver; public class StudentServiceImpl extends StudentServiceGrpc.StudentServiceImplBase { @Override public void getRealNameByUsername(MyRequest request, StreamObserver<MyResponse> responseObserver) { System.out.println("has received information from client : "+ request.getUsername()); responseObserver.onNext(MyResponse.newBuilder().setRealname("proto response").build()); responseObserver.onCompleted(); } }
package grpc;
import io.grpc.ServerBuilder;
import io.grpc.Server;
import java.io.IOException;
public class GrpcServer {
private Server server;
private void start() throws IOException {
/* The port on which the server should run */
int port = 8899;
server = ServerBuilder.forPort(port)
.addService(new StudentServiceImpl())
.build()
.start();
// 回调钩子
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
GrpcServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
private void awaitTermination() throws InterruptedException {
if(null != this.server){
this.server.awaitTermination();
}
}
public static void main(String[] args) throws InterruptedException, IOException {
GrpcServer server = new GrpcServer();
server.start();
server.awaitTermination();
}
}
客户端调用接口
package grpc; import com.chenqh.proto.MyRequest; import com.chenqh.proto.MyResponse; import com.chenqh.proto.StudentServiceGrpc; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.concurrent.TimeUnit; public class Client { public static void main(String[] args) throws InterruptedException { ManagedChannel managedChannel = ManagedChannelBuilder .forAddress("localhost",8899).usePlaintext(true).build(); StudentServiceGrpc.StudentServiceBlockingStub blockingStub = StudentServiceGrpc.newBlockingStub(managedChannel); //服务端返回单条消息 MyResponse myResponse = blockingStub. getRealNameByUsername(MyRequest.newBuilder().setUsername("proto request").build()); System.out.println(myResponse.getRealname()); managedChannel.shutdown().awaitTermination(3, TimeUnit.SECONDS); } }启动服务端
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wAg1yklO-1571816882893)(C:\Users\cqh_d\AppData\Roaming\Typora\typora-user-images\1571811956049.png)]](https://img-blog.csdnimg.cn/20191023155213666.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4NDIwOTcz,size_16,color_FFFFFF,t_70)
启动客户端


版权声明:本文为qq_28420973原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。