Java实现grpc
1、实践
(1) IDEA安装插件
Protobuf Support
(2) 新建.proto文件
我这里命名为test.proto。 指定生成代码的包路径、接口服务等。 定义了一个UserService服务,包含一个方法getUser()。以及请求类UserRequest、响应类UserReply。
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples";
option java_outer_classname = "UserProto";
option objc_class_prefix = "HLW";
package test;
// The user service definition.
service User {
// getUser method
rpc getUser (UserRequest) returns (UserReply) {}
}
// The request message containing the user's name.
message UserRequest {
string name = 1;
}
// The response message containing the user
message UserReply {
string message = 1;
}
(3) pom引入依赖
包括grpc、protobuf和protobuf插件。
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<protobuf.version>3.6.1</protobuf.version>
<grpc.version>1.19.0</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
</plugin>
</plugins>
</build>
(4) 生成代码
操作protobuf插件的compile、compile-custom命令。
生成的代码如下,包含: ● protoc-dependencies: 相关依赖,proto文件格式。 ● protoc-plugins: pom中指定的插件。 ● generated-sources: 生成的源码包文件。
(5) 创建服务端
Server端要提供一个查询服务,需要继承UserGrpc.UserImplBase。示例中,监听端口10001。 public class TestService extends UserGrpc.UserImplBase{
public void getUser(UserRequest request,
StreamObserver<UserReply> responseObserver) {
UserReply reply = UserReply.newBuilder().setMessage("this is "+request.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
public class UserServer {
private Server server;
public static void main(String[] args) throws InterruptedException, IOException {
UserServer server=new UserServer();
server.start();
server.blockUntilShutdown();
}
private void start() throws IOException {
int port=10001;
server= ServerBuilder.forPort(port)
.addService(new TestService())
.build().start();
System.out.println("server start..... listen on "+port);
Runtime.getRuntime().addShutdownHook(new Thread(()->{
System.out.println("shut down grpc server");
try {
UserServer.this.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
}
private void stop() throws InterruptedException {
if(server!=null){
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
}
}
private void blockUntilShutdown() throws InterruptedException {
if(server!=null){
server.awaitTermination();
}
}
}
(6) 创建客户端
客户端这里要远程调用服务端的接口,因为是本地模拟,所以ip:127.0.0.1 port:10001。 通过Stub,像调用本地方法一样调用远程方法。
public class UserClient {
private ManagedChannel channel;
private UserGrpc.UserBlockingStub stub;
public UserClient(String host,int port){
channel= ManagedChannelBuilder.forAddress(host,port).usePlaintext().build();
stub=UserGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public String getUser(String name){
UserRequest request = UserRequest.newBuilder().setName(name).build();
UserReply helloReply = stub.getUser(request);
return helloReply.getMessage();
}
public static void main(String[] args) throws InterruptedException {
UserClient client=new UserClient("127.0.0.1",10001);
String hello = client.getUser("hello");
System.out.println("client:"+hello);
client.shutdown();
}
}
(7) 测试
因为我们是服务端监听客户端,所以要先启动服务端,再启动客户端。
2、源码
(1) protobuf
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,可用于数据通信协议和数据存储等,它是 Google 提供的一个具有高效协议数据交换格式工具库,是一种灵活、高效和自动化机制的结构数据序列化方法。
特点:二进制方式来表示数据。
相比XML,有编码后体积更小,编解码速度更快的优势;相比于 Json,Protobuf 有更高的转化效率,时间效率和空间效率都是 JSON 的 3-5 倍。
(2) 重要类和接口
针对上面生成的几个类和接口,做详细的说明:
我们先介绍通过compile命令生成的java包下的类:
UserRequestOrBuilder: 用户服务的响应接口,getName()对应proto文件中的UserRequest的name字符串的get操作。
//proto
message UserRequest {
string name = 1;
}
public interface UserRequestOrBuilder extends
com.google.protobuf.MessageOrBuilder {
java.lang.String getName();
com.google.protobuf.ByteString
getNameBytes();
}
UserRequest: 封装的UserService的请求实体。 继承GeneratedMessageV3类,并实现UserRequestOrBuilder接口。 内部类Builder可以做参数处理,并对getName()的具体实现逻辑。
public final class UserRequest extends
com.google.protobuf.GeneratedMessageV3 implements
UserRequestOrBuilder {
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
io.grpc.examples.UserRequestOrBuilder {
public Builder setName(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
name_ = value;
onChanged();
return this;
}
public java.lang.String getName() {
java.lang.Object ref = name_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
name_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
}
}
UserReplyOrBuilder: 用户服务的响应接口,getMessage()对应proto文件中的UserReply的message字符串的get操作。
//proto
message UserReply {
string message = 1;
}
public interface UserReplyOrBuilder extends
com.google.protobuf.MessageOrBuilder {
java.lang.String getMessage();
com.google.protobuf.ByteString
getMessageBytes();
}
UserResponse: 封装请求的响应实体。对getMessage()的具体实现。 与UserRequest类似,也有一个内部类Builder。
UserGrpc: 通过命令compile-custom生成。是grpc的核心类。 提供了三种场景的stub实现:UserStub(async)、UserBlockingStub(block)、UserFutureStub(ListenableFuture)
下一篇介绍Nacos中的grpc应用。
|