关于protobuf是什么?有什么用能干什么等相关的概述就不说明了
安装protobuf 编译器
github下载地址:Releases · protocolbuffers/protobuf (github.com)
官网:Protocol Buffers Documentation (protobuf.dev)
下载对应操作系统的安装包,配置protoc的环境变量。在终端输入如下命令查看protoc环境变量是否配置成功
// 如果输入此命令没有显示出对应的版本,说明环境变量配置错误
protoc --version
新建java maven工程
新建3个java maven工程,用来实现gRPC远程调用。
# 3个java maven 工程说明
rpc-grpc-api # 此工程用来做共通工程,给服务端、客户端提供对应的proto文件生成的java代码
rpc-grpc-server # grpc的服务端,也可以说是服务的提供者
rpc-grpc-client # grpc的客户端
rpc-grpc-api
在此工程目录的src目录下新建一个proto目录,把所有编写的.proto文件存放到此目录。
新建Hello.proto文件
// protobuf的版本
syntax = "proto3";
// 是否生成多个文件
option java_multiple_files = false;
// 生成文件默认存放的包名
option java_package = "com.grpc";
// 生成proto对应的文件名
option java_outer_classname = "HelloProto";
// 定义消息,请求传递的参数
message HelloRequest{
string name = 1;
}
// 返回的消息
message HelloResponse{
string result = 1;
}
// 定义grpc服务
service HelloGrpcService{
rpc helloGrpc(HelloRequest) returns(HelloResponse);
}
关于protobuf相关的语法查看官网。
// 使用protoc命令,把proto 文件中的IDL转换成对应的java编程语言
protoc --java_out=/xxx/xxx.proto
我们不使用这种方式,使用起来不太方便。在此使用的是grpc-java的maven插件来帮助我们快速的将proto文件内容生成对应的java代码
grpc-java github地址:grpc/grpc-java: The Java gRPC implementation. HTTP/2 based RPC (github.com)
在rpc-grpc-api的pom.xml文件中添加如下依赖:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.51.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.51.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.51.0</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
并在pom.xml的build标签中添加插件
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</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.24.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.60.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
注意:使用grpc-java插件,.proto文件必放置到proto目录中,否则使用此插件生成对应代码时会失败
打开idea中的maven菜单栏,进行如下图操作生成对应的java代码,此步骤只是将对应的.proto文件中定义的message转换成对应的java代码
生成的代码如下,还需将生成的代码拷贝到java目录下
然后等待上述文件生成成功后,再执行如下图操作,生成.proto文件中定义的service代码
同理,生成的代码还需要拷贝到java目录下
到此 rpc-grpc-api 工程的代码就生成完毕
rpc-grpc-server
在此rpc-grpc-server工程中的pom.xml文件中依赖rpc-grpc-api
<dependency>
<groupId>com.rpc</groupId>
<artifactId>rpc-grpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
新建一个HelloGrpcServiceImpl类继承rpc-grpc-api项目生成的HelloGrpcServiceGrpc.HelloGrpcServiceImplBase类,覆盖.proto文件中的helloGrpc方法,并书写对应的业务
public class HelloGrpcServiceImpl extends HelloGrpcServiceGrpc.HelloGrpcServiceImplBase {
@Override
public void helloGrpc(HelloProto.HelloRequest request, StreamObserver<HelloProto.HelloResponse> responseObserver) {
// 获取客户端传递的参数
String name = request.getName();
// 业务处理
System.out.println("获取到的参数为:" + name);
// 构建返回
HelloProto.HelloResponse.Builder responseBuilder = HelloProto.HelloResponse.newBuilder();
// 构建返回数据
responseBuilder.setResult("hello,I am grpc remote method result");
// 构建响应
HelloProto.HelloResponse response = responseBuilder.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
对应的rpc远程方法已经编写完毕,接下来编写一个main函数来模拟后端服务,代码如下:
public class Hello {
public static void main(String[] args) throws IOException, InterruptedException {
// 编写服务的构建者,并绑定端口
ServerBuilder serverBuilder = ServerBuilder.forPort(9000);
// 发布服务
serverBuilder.addService(new HelloGrpcServiceImpl());
// 创建服务
Server server = serverBuilder.build();
// 启动服务
server.start();
// 等待客户端的连接
server.awaitTermination();
}
}
启动服务,检测是否错误,如果服务端没问题,接下来编写客户端
rpc-grpc-client
工程依赖rpc-grpc-api
<dependency>
<groupId>com.rpc</groupId>
<artifactId>rpc-grpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
然后在客户端工程新建main函数,模拟客户端调用rpc远程服务端,编写代码如下:
public class HelloClient {
public static void main(String[] args) {
// 创建连接服务端的通道
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",9000).usePlaintext().build();
// 获取代理对象stub
HelloGrpcServiceGrpc.HelloGrpcServiceBlockingStub helloGrpcService = HelloGrpcServiceGrpc.newBlockingStub(managedChannel);
// 准备远程调用参数
HelloProto.HelloRequest.Builder builder = HelloProto.HelloRequest.newBuilder();
builder.setName("hello grpc server,i am grpc client");
HelloProto.HelloRequest request = builder.build();
// 进行rpc远程调用
HelloProto.HelloResponse response = helloGrpcService.helloGrpc(request);
String result = response.getResult();
System.out.println("获取到rpc远程调用的结果为:"+result);
}
}
启动客户端,观察调用结果,如果都正常,说明使用grpc进行远程调用ok
服务端调用输出内容:
客户端获取到的响应结果: