GRpc学习笔记
因为公司需要用到grpc,所以自己手写了一个rpc框架后,又学习了一下怎么使用别人的rpc框架,这里演示了如何使用grpc来进行服务调用,使用步骤如下:
一、新建maven项目
step1 new project -->选择maven项目
step2 设置文件地址、groupid、artifactld信息
step 3 点击finish创建项目
二、导入pom依赖
pom这块最主要的就是版本,通过properties统一管理版本号
需要protobuf、grpc、protoc、lombok、maven等
<?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><!-- CURRENT_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>
</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>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
三、写profo文件
3.1 新建proto的存放位置
因为上面pom中设置了proto的存放位置,所以要在相应位置下新建文件 add.protro
3.2 新建add.proto文件
3.3 protobuf maven插件下载
因为protobuf需要和maven插件进行编译,所以需要下载相关的插件,去setting中的plugins的marketplace下载插件,重启IDEA即可
3.4 编写proto文件
这里我们需要在一个.proto文件中定义我们的服务以及参数,不熟悉的童鞋可以去自行了解一下具体的语法,不过直接看我的代码应该也没什么问题,毕竟语法相对还是比较好理解的。
我们首先在main目录下创建一个proto文件夹,在这个文件夹中创建我们的.proto文件,比如我们这里取名为add.proto,
add.proto文件的具体定义如下:
syntax = "proto3";
package grpc;
option java_package = "a.b.c";
option java_outer_classname = "AddServiceProto";
option java_multiple_files = true;
//添加一个 加法 服务 计算两数之和
service AddService{
//入参 和 出参 用于根据 AddRequest 获取 AddReply 结果的服务
rpc add(AddRequest) returns (AddReply){}
}
// int类型要指定位 其中 a为其序列为1的字段 b为其序列为2的字段
message AddRequest{
int32 a = 1;
int32 b = 2;
}
// int类型要指定位 res为其序列为1的字段
message AddReply{
int32 res = 1;
}
3.5 编译proto文件
step1 点击右侧install
step2 出现build success 即 编译成功
step3 查看target ,可以看到生成的编译后的文件,其中最重要的一个类 AddServiceGrpc
3.6 服务方法
有一个很重要的AddServiceImplBase实现类,
add方法就对应着proto文件中的add方法,
以及 入参 AddRequest 和 出参 AddReply 都对应上
---------略---------
public static abstract class AddServiceImplBase implements io.grpc.BindableService {
/**
* <pre>
*入参 和 出参
* </pre>
*/
public void add(a.b.c.AddRequest request,
io.grpc.stub.StreamObserver<a.b.c.AddReply> responseObserver) {
asyncUnimplementedUnaryCall(getAddMethod(), responseObserver);
}
---------略---------
}
四、服务代码编写
4.1 Server服务
我们真正要实现这个方法,就是需要写一个实现类继承AddServiceImplBase这个抽象类,然后重写add方法。
step 1 创建一个实现类AddServer,继承AddServiceGrpc.AddServiceImplBase,重写add方法
step 2 自定义myadd方法,该方法是服务自己的方法,为了更好看,降低耦合度
step3 书写server的add逻辑,供其他服务调用
step 4 通过 responseObserver.onNext(AddReply.newBuilder().setRes(res).build()); 将计算的结果封装为AddReply返回
step 5 结束观察状态
step 6 写main方法,将add方法暴露出去,设置监听的端口,暴漏的而服务,然后build和start即可
step7 为了避免很快关闭,写一个while循环阻塞该线程
package a.b.c;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
/**
* @Author CandyDingDing
* @Version 1.0
* @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
* @Describe
* @Date 2022/4/4
*/
public class AddServer extends AddServiceGrpc.AddServiceImplBase {
public static void main(String[] args) throws IOException {
ServerBuilder.forPort(9999)
.addService(new AddServer())
.build()
.start();
System.out.println("server start at 9999");
while (true){
}
}
public void add(AddRequest request, StreamObserver<AddReply> responseObserver) {
//从request中获取 a 和 b,作为方法的入参
int res = myAdd(request.getA(),request.getB());
responseObserver.onNext(AddReply.newBuilder().setRes(res).build());
responseObserver.onCompleted();
}
private int myAdd(int a, int b){
return a + b;
}
}
4.2 Clint客户端
step1 写AddClient方法,把信息放在通道里,需要一个stub,把参数传给stub,shub拿到数据后发送到网络
step2 写主方法,new 一个AddClient实例
step3 new一个Addrequest作为入参,通过stub发送出去
step4 输出结果
package a.b.c;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
/**
* @Author CandyDingDing
* @Version 1.0
* @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
* @Describe
* @Date 2022/4/4
*/
public class AddClient {
AddServiceGrpc.AddServiceBlockingStub stub;
ManagedChannel channel;
public static void main(String[] args) {
int a = 101;
int b = 102;
AddClient client = new AddClient();
AddReply reply = client.stub.add(AddRequest.newBuilder().setA(a).setB(b).build());
System.out.println(reply.getRes());
}
public AddClient(){
channel = ManagedChannelBuilder
.forAddress("127.0.0.1",9999)
.usePlaintext()
.build();
stub = AddServiceGrpc.newBlockingStub(channel);
}
}
参考
视频链接:https://www.bilibili.com/video/BV1Np4y1x7JB?p=2&spm_id_from=pageDriver
笔记连接:https://www.yuque.com/lililil-9bxsv/kb/hxx1fd
代码地址:https://gitee.com/candydingding/g-rpc.git