目标
从头一步步创建 java 版的 gRPC 示例项目,体验 gRPC 的开发流程。
步骤说明
使用 protobuf 定义 grpc service、request 和 response type。
使用 protobuf compiler 生成 server 和 client 相关代码。
创建 server 应用,实现 service 接口,创建 grpc server。
创建 client 应用,使用生成的 stub 进行 rpc 调用。
详细步骤
(1)创建项目
创建项目文件夹,准备好初始化的文件和目录:
$ mkdir grpc-project
$ cd grpc-project
$ touch pom.xml
$ mkdir -p src/main/java
$ mkdir -p src/main/proto
结构如下:
├── pom.xml
└── src
└── main
├── java
└── proto
pom.xml
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">
4.0.0
com.grpc.example
grpcjava
0.0.1-SNAPSHOT
jar
grpc-java-demo
http://maven.apache.org
UTF-8
1.8
UTF-8
1.15.0
3.5.1
3.5.1-1
2.0.7.Final
io.grpc
grpc-netty-shaded
${grpc.version}
io.grpc
grpc-protobuf
${grpc.version}
io.grpc
grpc-stub
${grpc.version}
io.grpc
grpc-alts
${grpc.version}
io.grpc
grpc-testing
${grpc.version}
test
io.grpc
grpc-netty
${grpc.version}
io.netty
netty-tcnative-boringssl-static
${netty.tcnative.version}
com.google.api.grpc
proto-google-common-protos
1.0.0
com.google.protobuf
protobuf-java-util
${protobuf.version}
junit
junit
4.12
test
org.mockito
mockito-core
1.9.5
test
kr.motd.maven
os-maven-plugin
1.5.0.Final
org.xolstice.maven.plugins
protobuf-maven-plugin
0.5.1
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
${project.build.sourceDirectory}
false
compile
compile-custom
org.apache.maven.plugins
maven-enforcer-plugin
1.4.1
enforce
enforce
org.apache.maven.plugins
maven-compiler-plugin
2.1
1.8
1.8
(2)定义 proto
$ vim src/main/proto/HelloService.proto
内容:
syntax = "proto3";
option java_multiple_files = true;
package com.example.grpc.gencode;
message HelloRequest {
string firstName = 1;
string lastName = 2;
}
message HelloResponse {
string greeting = 1;
}
service HelloService {
rpc hello(HelloRequest) returns (HelloResponse);
}
生成代码:
$ mvn clean compile
项目结构:
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── grpc
│ │ └── gencode
│ │ ├── HelloRequest.java
│ │ ├── HelloRequestOrBuilder.java
│ │ ├── HelloResponse.java
│ │ ├── HelloResponseOrBuilder.java
│ │ ├── HelloServiceGrpc.java
│ │ └── HelloServiceOuterClass.java
│ └── proto
│ └── HelloService.proto
(3)实现 service
$ vim src/main/java/com/example/grpc/HelloServiceImpl.java
代码:
package com.example.grpc;
import com.example.grpc.gencode.HelloRequest;
import com.example.grpc.gencode.HelloResponse;
import com.example.grpc.gencode.HelloServiceGrpc.HelloServiceImplBase;
import io.grpc.stub.StreamObserver;
public class HelloServiceImpl extends HelloServiceImplBase {
@Override
public void hello(
HelloRequest request, StreamObserver responseObserver) {
String greeting = new StringBuilder()
.append("Hello, ")
.append(request.getFirstName())
.append(" ")
.append(request.getLastName())
.toString();
HelloResponse response = HelloResponse.newBuilder()
.setGreeting(greeting)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
(4)创建 server
$ vim src/main/java/com/example/grpc/GrpcServer.java
代码:
package com.example.grpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
public class GrpcServer {
public static void main(String[] args) {
try {
int port = 50051;
final Server server = ServerBuilder.forPort(port)
.addService(new HelloServiceImpl())
.build()
.start();
System.out.println("Server started, listening on " + port);
server.awaitTermination();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(5)创建 client
$ vim src/main/java/com/example/grpc/GrpcClient.java
代码:
package com.example.grpc;
import java.util.concurrent.TimeUnit;
import com.example.grpc.gencode.HelloRequest;
import com.example.grpc.gencode.HelloResponse;
import com.example.grpc.gencode.HelloServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class GrpcClient {
public static void main(String[] args) {
ManagedChannel channel = null;
try {
channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext(true).build();
HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);
HelloResponse helloResponse = stub
.hello(HelloRequest.newBuilder().setFirstName("Baeldung").setLastName("gRPC").build());
System.out.println(helloResponse.getGreeting());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (channel != null) {
try {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
现在的项目结构:
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── grpc
│ │ ├── GrpcClient.java
│ │ ├── GrpcServer.java
│ │ ├── HelloServiceImpl.java
│ │ └── gencode
│ │ ├── HelloRequest.java
│ │ ├── HelloRequestOrBuilder.java
│ │ ├── HelloResponse.java
│ │ ├── HelloResponseOrBuilder.java
│ │ ├── HelloServiceGrpc.java
│ │ └── HelloServiceOuterClass.java
│ └── proto
│ └── HelloService.proto
编译运行
$ mvn clean compile
在一个命令终端中启动 server:
$ mvn exec:java -Dexec.mainClass="com.example.grpc.GrpcServer"
Server started, listening on 50051
server 会阻塞等待。
在另一个命令终端中启动 client:
$ mvn exec:java -Dexec.mainClass="com.example.grpc.GrpcClient"
Hello, Baeldung gRPC
输出后程序结束运行。