问题背景
公司内部分布式微服务更常用GRPC框架进行通信,因为约定好了各个接口的协议,开发会更有效率,保存一份接口文档也容易查看
- http是应用层协议,tcp是传输层协议
- tcp是以二进制数据流进行传输,上层应用开发不友好,所以出现了http协议
- RPC (Remote Procedure Call)即远程过程调用,是分布式系统常见的一种通信方法。GRPC是Google的RPC框架,方便开发
- http用于接口较少、系统交互少的情况
- GRPC比HTTP更多的优势在于,动态扩展、统一化、安全性、服务法治理等,分布式微服务项目RPC通信是首选,而GRPC又是RPC中的首选框架之一
- GRPC使用http2协议建立通信通道,内容交换格式使用protobuf,微服务之间只需要商定好proto文件,通过使用protobuf插件即可通信
注意事项 - 默认已安装JDK环境
- 可以通过本文的代码自己创建工程,也可以下载测试源码参考
项目搭建
1 引入pom依赖,包括grpc框架jar包和相关插件
<?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>a.b.c</groupId>
<artifactId>grpc-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.34.1</grpc.version>
<protobuf.version>3.12.0</protobuf.version>
<protoc.version>3.12.0</protoc.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-bom</artifactId>
<version>${grpc.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<scope>runtime</scope>
</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-util</artifactId>
<version>${protobuf.version}</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</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>
<protoSourceRoot>src/main/resources/proto</protoSourceRoot>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2 proto文件编写,proto3是没有required和optional字段的
syntax = "proto3";
package a.b.c.grpc;
option java_multiple_files = true;
service AddService{
rpc add(AddRequest) returns (AddReply){}
}
message AddRequest{
string requestId = 1;
int32 a = 2;
int32 b = 3;
}
message AddReply{
string requestId = 1;
int32 res = 2;
}
3 使用protobuf插件生成GRPC通信类,在maven插件中,点击Plugins,然后点击protobuf,然后点击protobuf:compile和compile-custom,如下图所示 4 生成grpc通信类 5 模拟微服务客户端
package a.b.c.client;
import a.b.c.grpc.AddRequest;
import a.b.c.grpc.AddResponse;
import a.b.c.grpc.AddServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class AddClient {
AddServiceGrpc.AddServiceBlockingStub stub;
ManagedChannel channel;
public static void main(String[] args) {
int a = 101;
int b = 102;
AddClient client = new AddClient();
AddRequest addRequest = AddRequest.newBuilder()
.setRequestId("abc")
.setA(a)
.setB(b)
.build();
try {
AddResponse response = client.stub.add(addRequest);
System.out.println(response.getRes());
}catch (Exception e){
System.out.println(e.getMessage());
}
}
public AddClient() {
channel = ManagedChannelBuilder
.forAddress("127.0.0.1", 9090)
.usePlaintext()
.build();
stub = AddServiceGrpc.newBlockingStub(channel);
}
}
6 模拟微服务服务端
package a.b.c.server;
import a.b.c.grpc.AddRequest;
import a.b.c.grpc.AddResponse;
import a.b.c.grpc.AddServiceGrpc;
import io.grpc.ServerBuilder;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
public class AddServer extends AddServiceGrpc.AddServiceImplBase {
public static void main(String[] args) throws IOException {
ServerBuilder.forPort(9090)
.addService(new AddServer())
.build()
.start();
System.out.println("server start at 9090");
while (true) {
}
}
@Override
public void add(AddRequest request, StreamObserver<AddResponse> responseObserver) {
System.out.println(request.getRequestId().getClass());
if(request.getRequestId().equals("")) {
responseObserver.onError(Status.INVALID_ARGUMENT.withDescription("requestId is null").asRuntimeException());
responseObserver.onCompleted();
}
System.out.println("aaa");
int res = myAdd(request.getA(), request.getB());
AddResponse response = AddResponse.newBuilder().setRes(res).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
private int myAdd(int a, int b) {
return a + b;
}
}
7 整个项目文件目录如下
测试步骤
1 先启动server端 2 启动客户端,a=101,b=102,求和,返回为203
心得
- 微服务之间的通信,grpc用起来很方便,微服务之间定好协议,效率更高。还可以使用postman自己进行测试
- proto的message顺序,微服务之间一定要对齐,不然会出现不必要的问题
作为程序员第 23 篇文章,每次写一句歌词记录一下,看看人生有几首歌的时间,wahahaha …
Lyric: 我醒来还笑着
|