grpc 流使用
引入依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>grpc-sample</artifactId>
<version>1.0-SNAPSHOT</version>
<name>grpc-sample</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<grpc.version>1.44.0</grpc.version>
<protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
<os-maven-plugin.version>1.6.2</os-maven-plugin.version>
<com.google.protobuf.protoc.version>3.17.3</com.google.protobuf.protoc.version>
<protoc-gen-grpc-java.plugin.version>1.44.0</protoc-gen-grpc-java.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>detect</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf-maven-plugin.version}</version>
<configuration>
<!--
The version of protoc must match protobuf-java. If you don't depend on
protobuf-java directly, you will be transitively depending on the
protobuf-java version that grpc depends on.
-->
<protocArtifact>
com.google.protobuf:protoc:${com.google.protobuf.protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${protoc-gen-grpc-java.plugin.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<id>grpc-build</id>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
编写 proto 文件
syntax = "proto3";
package org.example.grpc.v1;
option java_multiple_files = true;
option java_package = "org.example.grpc.hello.v1";
message Stock{
string companyName = 1;
string companyCode = 2;
}
message StockPrice{
double price = 1;
string companyCode = 2;
}
service StockService{
// 服务器端返回 stream
rpc s2cStream(Stock) returns (stream StockPrice);
//client 请求为流
rpc c2sStream(stream Stock) returns(StockPrice);
//双向流
rpc scStreams(stream Stock) returns(stream StockPrice);
}
在 idea 右侧的 maven 中执行 compile, 则可以自动生成 grpc代码
grpc 客户端
public class StockClient {
private final ManagedChannel channel;
private final StockServiceGrpc.StockServiceBlockingStub stub;
private final StockServiceGrpc.StockServiceStub noStub;
public StockClient(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
//客户端请求参数类型非 stream类型
stub = StockServiceGrpc.newBlockingStub(channel);
noStub = StockServiceGrpc.newStub(channel);
}
public static void main(String[] args) {
StockClient client = new StockClient("localhost", 6666);
//服务器返回流
// client.invokes2cStream();
//客户端请求流【proto中流响应参数作为请求参数】
// client.invokec2sStream();
//双向流
client.invokescStreams();
}
public void invokes2cStream() {
Iterator<StockPrice> it = stub.s2cStream(Stock.newBuilder().setCompanyCode("0001").setCompanyName("天线宝宝").build());
while (it.hasNext()) {
StockPrice next = it.next();
System.out.println("client recv: " + next);
}
}
public void invokec2sStream() {
StreamObserver<StockPrice> responseObserver = new StreamObserver<StockPrice>() {
@Override
public void onNext(StockPrice value) {
System.out.println("client recv: " + value);
}
@Override
public void onError(Throwable t) {
System.out.println("client error: " + t.getMessage());
}
@Override
public void onCompleted() {
System.out.println("client completed");
}
};
StreamObserver<Stock> requestObserver = noStub.c2sStream(responseObserver);
for (int i = 0; i < 3; i++) {
Stock stock = Stock.newBuilder().setCompanyCode("00" + i).setCompanyName("天线宝宝" + i).build();
requestObserver.onNext(stock);
}
requestObserver.onCompleted();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void invokescStreams() {
StreamObserver<StockPrice> responseObserver = new StreamObserver<StockPrice>() {
@Override
public void onNext(StockPrice value) {
System.out.println("client recv: " + value);
}
@Override
public void onError(Throwable t) {
System.out.println("client error: " + t.getMessage());
}
@Override
public void onCompleted() {
System.out.println("client completed");
}
};
StreamObserver<Stock> requestObserver = noStub.scStreams(responseObserver);
for (int i = 0; i < 3; i++) {
Stock stock = Stock.newBuilder().setCompanyCode("00" + i).setCompanyName("天线宝宝" + i).build();
requestObserver.onNext(stock);
}
requestObserver.onCompleted();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
注意:如果是流,则需要使用非阻塞的 stub,在这里区别:
- StockServiceGrpc.StockServiceBlockingStub: 自动生成
- StockServiceGrpc.StockServiceStub: 自动生成
服务器端
服务器提供服务
public class StockServiceProvider extends StockServiceGrpc.StockServiceImplBase {
/**
* 服务器端返回 流
*
* @param request
* @param responseObserver
*/
@Override
public void s2cStream(Stock request, StreamObserver<StockPrice> responseObserver) {
System.out.println("server recv: " + request);
for (int i = 0; i < 3; i++) {
StockPrice stockPrice = StockPrice.newBuilder().setPrice((i + 1) * 0.3).setCompanyCode("00" + i).build();
responseObserver.onNext(stockPrice);
}
responseObserver.onCompleted();
}
/**
* 客户端请求 流数据
*
* @param responseObserver
* @return
*/
@Override
public StreamObserver<Stock> c2sStream(StreamObserver<StockPrice> responseObserver) {
return new StreamObserver<Stock>() {
private double price = 0d;
private Random random = new Random();
private String code;
@Override
public void onNext(Stock value) {
System.out.println("server recv:" + value);
price += random.nextDouble();
code = value.getCompanyCode();
}
@Override
public void onError(Throwable t) {
System.out.println("server handler error: " + t.getMessage());
}
@Override
public void onCompleted() {
StockPrice stockPrice = StockPrice.newBuilder().setPrice(price).setCompanyCode(code).build();
responseObserver.onNext(stockPrice);
responseObserver.onCompleted();
}
};
}
/**
* 客户端和服务器端双向流
*
* @param responseObserver
* @return
*/
@Override
public StreamObserver<Stock> scStreams(StreamObserver<StockPrice> responseObserver) {
return new StreamObserver<Stock>() {
private Random random = new Random();
@Override
public void onNext(Stock value) {
System.out.println("server recv:" + value);
StockPrice stockPrice = StockPrice.newBuilder().setPrice(random.nextDouble()).setCompanyCode(value.getCompanyCode()).build();
responseObserver.onNext(stockPrice);
}
@Override
public void onError(Throwable t) {
System.out.println("server handler error: " + t.getMessage());
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
}
grpc server
public class GrpcServer {
private Server server;
public static void main(String[] args) throws Exception {
GrpcServer grpcServer = new GrpcServer();
grpcServer.start();
grpcServer.terminated();
}
private void start() throws IOException {
int port = 6666;
server = ServerBuilder.forPort(port)
.addService(new StockServiceProvider())
.build().start();
System.out.println("server start port 6666...");
}
public void terminated() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
}
good luck!