Java端
gRPC默认通过Protobuf进行数据传输。Protobuf提供一种灵活、高效、自动化的机制,用于序列化结构数据。Protobuf仅需自定义一次所需要的数据格式,然后我们就可以使用Protobuf编译器自动生成各种语言的源码,方便我们读写自定义的格式化数据。
在idea安装插件
配置maven文件
主要是添加protobuf和grpc包的引用以及插件。
protobuf和grpc的引用为:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.12.0</version>
</dependency>
生成protobuf和grpc接口插件配置
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.0.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
完整配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>grpcdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>grpcdemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.12.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.5.5</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.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:3.0.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
</plugins>
</build>
</project>
定义一个接口服务文件(*.proto),这个文件需要放到与main/java同级位置,可以创建文件夹。
下面是一个示例文件calc.proto的内容
syntax = "proto3";
option java_multiple_files = false;
option java_package = "com.example.grpcdemo.grpc.calc";
option java_outer_classname = "PhmCalcProto";
// option objc_class_prefix = "Hello";
package com.example.grpcdemo.grpc.calc;
//定义服务
service PhmCalcService {
//注意:这里是returns 不是return
rpc calc (PhmCalcRequest) returns (PhmCalcResponse) {
}
}
//定义请求数据结构
message PhmCalcRequest {
string calcName = 1;
string calcCode = 2;
string calcParams = 3;
}
//定义返回数据结构
message PhmCalcResponse {
string status = 1;
string code = 2;
string message = 3;
string data = 4;
}
这里定义了一个服务接口“PhmCalcService”和两个传输对象“PhmCalcRequest”与“PhmCalcResponse”。
通过maven的install生成protobuf的接口模板文件
点击运行完成后,会在工程里面生成一个target文件夹(需要打开)
在target文件夹中,包含示例程序,接口模板java文件。
拷贝模板代码到工程中
为避免类冲突,可以将模板“target”文件夹删除或移走备份。
编写客户端请求测试类
package com.example.grpcdemo;
import com.example.grpcdemo.grpc.calc.PhmCalcProto;
import com.example.grpcdemo.grpc.calc.PhmCalcServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import java.util.concurrent.TimeUnit;
/**
* @author Administrator
*/
public class PhmCalcTestClient {
private final ManagedChannel channel;
private final PhmCalcServiceGrpc.PhmCalcServiceBlockingStub blockingStub;
private static final String GRPC_SERVER_HOST = "127.0.0.1";
private static final int GRPC_SERVER_PORT = 50051;
public PhmCalcTestClient(String host, int port) {
// usePlaintext表示明文传输,否则需要配置ssl, channel 表示通信通道
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();
// 存根,用于调用服务端的接口方法。
blockingStub = PhmCalcServiceGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public void testResult() {
PhmCalcProto.PhmCalcRequest request = PhmCalcProto.PhmCalcRequest.newBuilder()
.setCalcCode("code123")
.setCalcName("name123")
.setCalcParams("{\"p1\":\"p1Value\"}").build();
System.out.println("request: ");
System.out.println(request.toString());
PhmCalcProto.PhmCalcResponse response = blockingStub.calc(request);
System.out.println("response: ");
System.out.println(response.toString());
}
public static void main(String[] args) {
PhmCalcTestClient client = new PhmCalcTestClient(GRPC_SERVER_HOST, GRPC_SERVER_PORT);
client.testResult();
}
}
Python端
新建Python代码工程,如果没有安装,则先安装Python。
Python端的gRPC服务模板代码我们不在IDE工具中生成,使用Python的一个工具插件来完成。
安装python的grpc运行时,命令行执行
pip install grpcio
- 使用 protoc 编译 proto 文件, 生成 python 语言的实现
安装grpc工具,命令行执行
pip install grpcio-tools
编辑protobuf文件,生成服务模板代码。将上一步JAVA中定义的同一个protobuf文件“calc.proto”拷贝到Python工程目录,命令行定位到proto目录,执行命令
python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. calc.proto
编译后将生成代码calc_pb2.py和calc_pb2_grpc.py文件。
编写服务端测试类calcServer.py
from concurrent import futures
import time
import grpc
import calc_pb2
import calc_pb2_grpc
# 实现 proto 文件中定义的 PhmCalcServiceService
class CalcServer(calc_pb2_grpc.PhmCalcServiceServicer):
# 实现 proto 文件中定义的 rpc 调用
def calc(self, request, context):
print("request: ")
print(request)
# 通过实际计算得出结果。
# ...
response = calc_pb2.PhmCalcResponse(status="0", message="success", data="{\"p2\": \"p2Value\"}")
print("response: ")
print(response)
return response
def serve():
# 启动 rpc 服务
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
calc_pb2_grpc.add_PhmCalcServiceServicer_to_server(CalcServer(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(60*60*24) # one day in seconds
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()