目录
第一步:创建工程
1、引入依赖
2、引入插件
3、工程结构
第二步:编写helloword.proto
第三步:使用插件生成代码
第四步:将文件拷贝到相应的包中
第五步:使用生成的代码,编写客户端和服务端
1、 服务端代码
2、 客户端代码
3、运行
本小节主要介绍Java中的gRPC快速开始示例。要求jdk版本1.7+.
# git地址 git clone -b v1.40.0 https://github.com/grpc/grpc-java # 本示例位置grpc-java/examples 模块 # helloword包以及proto文件夹中hellowrod.proto
我的gitee代码地址:
# 我的示例 https://gitee.com/work_ldj/gRPC-examples.git # Hello-gRPC模块(本文使用的示例) # 该模块基本上参考的官网示例,只不过加了些注释
第一步:创建工程
1、引入依赖
(版本详见源码)
<properties>
<!--gRPC版本-->
<gRPC.version>1.40.0</gRPC.version>
<protobuf.version>3.17.2</protobuf.version>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<scope>provided</scope>
</dependency>
<!--日志组件-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!--测试组件-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
2、引入插件
<!--gRPC-examples公用构建组件-->
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.0</version>
</extension>
</extensions>
<plugins>
<!--
protobuf 和 grpc 插件
推荐使用maven插件生成代码
-->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</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>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<!--基础组件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<inherited>true</inherited>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<inherited>true</inherited>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
3、工程结构
第二步:编写helloword.proto
//申明版本
syntax = "proto3";
option java_multiple_files = true;
//指定生成文件放在哪个包下
option java_package = "top.joylee.example.grpc.hello";
//声明 rpc 服务接口
//关键字: service 声明需要生成的服务接口"类"
service Greeter {
// 关键字: rpc 声明服务方法,包括方法名、请求消息(请求体)、相应消息(响应体)
// [注意]: proto使用Pascal命名方式,与驼峰命名的区别就是首字母大写。
// 不用担心方法调用时的方法名,因为插件会为我们转换过来。
// 另外推荐使用maven插件的方式生成代码,以免生成与JDK版本冲突的语法
rpc SayHello(HelloRequest) returns (HelloResponse);
}
//声明请求、响应消息
//关键字: message 声明请求体和响应体
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
【注意】:已经在工程结构中标出,但是还是提一句,此文件要放在src/main/proto文件夹下,proto命名一定不能错。 否则如下图所示:
会因为找不到proto文件而无法生成代码.
第三步:使用插件生成代码
1、重要的事说三遍,.proto文件的位置,要在main/proto文件夹下
2、检查maven插件是否下载成功
3、编译生成代码
3-1 首先执行protobuf:complie,生成消息相关代码
3-2 然后执行protobuf:compile-custome,生成grpc服务相关代码
这两步可以调换执行顺序,但是一定要都执行。
第四步:将文件拷贝到相应的包中
第五步:使用生成的代码,编写客户端和服务端
1、 服务端代码
服务端代码最终要的就是实现.proto文件中service定义的rpc服务。
public class HelloServer {
private final static Logger log = LoggerFactory.getLogger(HelloServer.class);
private Server server;
public static void main(String[] args) throws Exception {
HelloServer helloServer = new HelloServer();
helloServer.start();
helloServer.blockUntilShutdown();
}
private void start() throws IOException {
int port = 50001;
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
log.info("Server started.listening on {}", port);
// 监听jvm shutdown 事件,并处理
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.error("**** shutdown g=RPC server since JVM is shutting down");
try {
stop();
} catch (InterruptedException e) {
log.error("await stop error,interrupted", e);
}
log.info("**** server shut down ,good bye ***");
}));
}
private void blockUntilShutdown() throws InterruptedException {
if (Objects.isNull(server)) {
return;
}
server.awaitTermination();
}
private void stop() throws InterruptedException {
if (Objects.isNull(server)) {
return;
}
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
}
private static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
log.info("...receive {} request", request.getName());
HelloResponse response = HelloResponse.newBuilder().setMessage("Hello \t" + request.getName()).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
log.info("reply {} complete...", request.getName());
}
}
}
2、 客户端代码
客户端,主要展示的就是通过ManagedChannelBuilder创建channel,然后通过channel拿到stub,进行方法调用。
/**
* Hello gRPC 客户端
*/
public class HelloClient {
private static final Logger log = LoggerFactory.getLogger(HelloClient.class);
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloClient(Channel channel) {
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
public void greet(String name) {
log.info("*** {} will try to greet ...", name);
//第一步:设置请求体
HelloRequest request = HelloRequest
.newBuilder()
.setName(name)
.build();
//定义response
HelloResponse response;
try {
response = blockingStub.sayHello(request);
} catch (StatusRuntimeException e) {
log.error("gRPC failed,{}", e.getMessage(), e);
return;
}
log.info("Great:{}", response.getMessage());
}
public static void main(String[] args) throws InterruptedException {
String user = "Joy";
String target = "localhost:50001";
ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
.usePlaintext()
.build();
try {
for (int i = 1; i <= 5; i++) {
log.info("...第{}次请求", i);
HelloClient client = new HelloClient(channel);
client.greet(user);
log.info("第{}次请求完成...", i);
TimeUnit.SECONDS.sleep(2);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
}
}
}
3、运行
启动服务端,然后启动客户端,运行结果如下: