有了前面的基础 我们已经构建了服务端和客户端连接的工具类 也已经熟悉了通过maven去处理对应的proto文件
如果有不是很清楚的可以看看前面的基础内容 或者有不足之处欢迎指正!
--------------------------------------------------------------------------------------------------------------------------------------------
今天我们来熟悉一下4种GRPC的通信方式 我们还是先配置下maven的pom.xml
<?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>modle</groupId>
<artifactId>modle</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>ServerGrpc</module>
<module>ClientGrpc</module>
<module>Demo</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.20.0</grpc.version>
<os.plugin.version>1.5.0.Final</os.plugin.version>
<protobuf.plugin.version>0.5.1</protobuf.plugin.version>
<protoc.version>3.5.1</protoc.version>
</properties>
<dependencies>
<dependency>
<groupId>model.grpc.util</groupId>
<artifactId>GrpcUtil</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.20.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.20.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.20.0</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.29.Final</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.24</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.7.1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-bom</artifactId>
<version>${grpc.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os.plugin.version}</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf.plugin.version}</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
<attachProtoSources>false</attachProtoSources>
<clearOutputDirectory>false</clearOutputDirectory>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
其次我们开始编写对应的proto文件
syntax = "proto3";
package Demo05GRPC.proto;
option java_package = "Demo05GRPC.proto";
option java_outer_classname = "StudentProto";
option java_multiple_files = true;
service StudentRpcService {
//单向阻塞数据传递
rpc getRealName (StudentRequest) returns (StudentResponse) {
};
//单向服务器端流式响应
rpc getRealByAge (ByAgeRequest) returns (stream StudentByAgeResponse) {
};
//单向客户端端流式请求
rpc getStudentByAge (stream ByAgeRequest) returns (StudentListResponse) {
};
//双向流式请求和响应
rpc getStudentByBItalk (stream StreamRequest) returns (stream StreamResponse) {
};
}
message StudentRequest {
string name = 1;
}
message StudentResponse {
string realName = 1;
}
message ByAgeRequest {
string age = 1;
}
message StudentByAgeResponse {
string name = 1;
string age = 2;
}
message StudentListResponse {
repeated StudentByAgeResponse response = 1;
}
message StreamRequest {
string request_info = 1;
}
message StreamResponse {
string response_info = 1;
}
通过maven编译和生成对应的java类 如下所示
然后我们编写对应的GRPC生成的远程服务的实现类
ServerStudentImp(注意这个类启动服务器时候需要加载)
package Demo05GRPC;
import Demo05GRPC.proto.*;
import io.grpc.stub.StreamObserver;
import java.util.UUID;
public class ServerStudentImp extends StudentRpcServiceGrpc.StudentRpcServiceImplBase {
//单向阻塞数据传递
@Override
public void getRealName(StudentRequest request, StreamObserver<StudentResponse> responseObserver) {
responseObserver.onNext(StudentResponse.newBuilder().setRealName("张三").build());
responseObserver.onNext(StudentResponse.newBuilder().setRealName("李四").build());
responseObserver.onCompleted();
}
//单向服务器端流式响应
@Override
public void getRealByAge(ByAgeRequest request, StreamObserver<StudentByAgeResponse> responseObserver) {
responseObserver.onNext(StudentByAgeResponse.newBuilder().setName("李四").build());
responseObserver.onNext(StudentByAgeResponse.newBuilder().setAge("22").build());
responseObserver.onNext(StudentByAgeResponse.newBuilder().setName("战三").build());
responseObserver.onNext(StudentByAgeResponse.newBuilder().setAge("25").build());
responseObserver.onCompleted();
}
//单向客户端端流式请求
@Override
public StreamObserver<ByAgeRequest> getStudentByAge(StreamObserver<StudentListResponse> responseObserver) {
return new StreamObserver<ByAgeRequest>() {
//请求是流式 请求一次 返回一次
@Override
public void onNext(ByAgeRequest byAgeRequest) {
byAgeRequest.getAge();
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onCompleted() {
StudentByAgeResponse response=StudentByAgeResponse.newBuilder().setAge("22").setName("张三").build();
StudentByAgeResponse response1=StudentByAgeResponse.newBuilder().setAge("23").setName("王五").build();
StudentByAgeResponse respons2=StudentByAgeResponse.newBuilder().setAge("24").setName("赵6").build();
StudentListResponse listResponse=StudentListResponse.newBuilder().addResponse(response).addResponse(response1).addResponse(respons2).build();
responseObserver.onNext(listResponse);
responseObserver.onCompleted();
}
};
}
//双向流式请求和响应
@Override
public StreamObserver<StreamRequest> getStudentByBItalk(StreamObserver<StreamResponse> responseObserver) {
return new StreamObserver<StreamRequest>() {
@Override
public void onNext(StreamRequest streamRequest) {
responseObserver.onNext(StreamResponse.newBuilder().setResponseInfo(UUID.randomUUID()+"").build());
}
@Override
public void onError(Throwable throwable) {
System.out.println(throwable.getMessage());
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
}
最后就是我们的客户端和服务端的测试代码了
服务端如下:
package Demo05GRPC;
import io.grpc.Server;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import java.io.IOException;
public class ServerGrpc {
private Server server;
public void start() throws IOException {
NettyServerBuilder serverBuilder=NettyServerBuilder.forPort(8002);
serverBuilder.addService(new ServerStudentImp());//将所有的远程服务类加进去管理
//我这里只有一个实现类
this.server = serverBuilder.build();
this.server.start();
}
public void stop(){
if(null !=this.server){
this.server.shutdown();
}
}
/**
* 阻塞等待RPC服务器停止
*/
public void blockUntilShutdown() {
if (server != null) {
try {
server.awaitTermination();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
ServerGrpc serverGrpc=new ServerGrpc();
serverGrpc.start();
serverGrpc.blockUntilShutdown();
}
}
客户端代码:
package Demo05GRPC;
import Demo05GRPC.proto.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
public class GrpcClient {
public static void main(String[] args) {
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost"
, 8002).usePlaintext(true).build();
/*StudentRpcServiceGrpc.StudentRpcServiceBlockingStub stub = StudentRpcServiceGrpc.newBlockingStub(managedChannel);
java.util.Iterator<Demo05GRPC.proto.StudentByAgeResponse> response = stub.getRealByAge(ByAgeRequest.newBuilder().setAge("222").build());
while (response.hasNext()){
StudentByAgeResponse response1= response.next();
System.out.println(response1.getAge());
System.out.println(response1.getName());
}*/
/*StreamObserver<StudentListResponse> streamObserver= new StreamObserver<StudentListResponse>() {
@Override
public void onNext(StudentListResponse value) {
value.getResponseList().forEach(e->{
System.out.println(e.getName());
System.out.println(e.getAge());
});
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onCompleted() {
}
};
StudentRpcServiceGrpc.StudentRpcServiceStub stub1=StudentRpcServiceGrpc.newStub(managedChannel);
StreamObserver<Demo05GRPC.proto.ByAgeRequest> response1= stub1.getStudentByAge(streamObserver);
response1.onNext(ByAgeRequest.newBuilder().setAge("22").build());
response1.onNext(ByAgeRequest.newBuilder().setAge("23").build());
response1.onNext(ByAgeRequest.newBuilder().setAge("24").build());
response1.onNext(ByAgeRequest.newBuilder().setAge("25").build());
response1.onNext(ByAgeRequest.newBuilder().setAge("26").build());
response1.onCompleted();
try {
Thread.sleep(5000);
}catch (Exception e){
e.getMessage();
}
}*/
StudentRpcServiceGrpc.StudentRpcServiceStub stub1 = StudentRpcServiceGrpc.newStub(managedChannel);
StreamObserver<Demo05GRPC.proto.StreamRequest> requestStreamObserver = stub1.getStudentByBItalk(new StreamObserver<StreamResponse>() {
@Override
public void onNext(StreamResponse streamResponse) {
System.out.println(streamResponse.getResponseInfo());
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onCompleted() {
}
});
for (int i = 0; i < 10; i++) {
requestStreamObserver.onNext(StreamRequest.newBuilder().setRequestInfo(System.currentTimeMillis() + "").build());
try {
Thread.sleep(1000);
} catch (Exception e) {
e.getMessage();
}
}
try {
Thread.sleep(5000);
} catch (Exception e) {
e.getMessage();
}
}
}
看到这里 我们可以对照之前写的工具类 已经封装好了 结合项目只需要将我们远程服务的所有实现在初始化的时候调用NettyServerBuilder.addService()就可以使用我们的grpc 服务与服务之间的轻松访问。