springboot 使用 GRPC


说明:

GRPC是什么?

首先我们知道 RPC是远程过程调用。

而GRPC是RPC的一种实现。

那么为什么要用GRPC呢?

因为它支持跨语言的开发,换句话说,大家都用过FeignRPC,尤其在spring cloud中。

然而它只支持java语言,而作为微服务,可能有很多其他的服务不是java开发的。因此需要满足这个需求,就需要一个跨语言的RPC,所以就会考虑使用GRPC

好了,下面进入正题

直接上代码。

我们做一个Service和一个Client 进行交互。

一,Service端
1,POM

注意:

grpc-spring-boot-starter

os-maven-plugin

protobuf-maven-plugin

<?xml version="1.0" encoding="UTF-8"?>

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.6
         
    
    com.leadtrans
    report
    1.6.0
    report
    Demo project for Spring Boot
    
        11
        2020.0.4
        
        2.3.2
        1.6.0
        0.5.1
    
    
 
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.boot
            spring-boot-starter-web
        
 
        
        
            com.alibaba
            fastjson
            1.2.78
        
 
        
        
            org.lognet
            grpc-spring-boot-starter
            ${grpc-spring-boot-starter.version}
        
 
    
 
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    
    
        
            
            
                kr.motd.maven
                os-maven-plugin
                ${os-maven-plugin.version}
            
        
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            repackage
                        
                    
                
            
            
                org.apache.maven.plugins
                maven-surefire-plugin
                
                    true
                
            
            
            
                org.xolstice.maven.plugins
                protobuf-maven-plugin
                ${protobuf-maven-plugin.version}
                
                    com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}
                    grpc-java
                    io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}
                    ${project.build.sourceDirectory}
                    false
                
                
                    
                        
                            compile
                            compile-custom
                        
                    
                
            
        
    
 

2,创建Proto

PS:Proto文件夹,必须和JAVA同级!

HelloWorld.protp

PS:请使用 option java_package="xxxx",

而不是 package xxxx

package xxxx 会导致你引用其他包时,会报错

syntax = "proto3";
 
option java_multiple_files = true;
option java_package="com.example.test.helloworld";
 
//请求
message Request {
  double num1 = 1;
  double num2 = 2;
  OperateType opType = 3;
}
 
//操作类型
enum OperateType {
  Addition = 0;
  Division = 1;
  Multiplication = 2;
  Subtraction = 3;
}
message Response {
  double result = 1;
}
 
//定义服务
service Operate {
  rpc Calculate (Request) returns (Response);
}

3,执行命令,生成文件

mvn clean install

或者点击

可以看到生成了文件:

4,实现接口

为了简单演示,这里就直接设置Response.Result=2

OperateImpl

@GRpcService
public class OperateImpl extends OperateGrpc.OperateImplBase {
    @Override
    public void calculate(Request request,
                          StreamObserver responseObserver) {
        Response response=Response.newBuilder().setResult(2).build();
        System.out.println(response);
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

二,Client端

 1,POM(同Service端)

<?xml version="1.0" encoding="UTF-8"?>

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.6
         
    
    com.example
    test1
    1.0
    test1
    Demo project for Spring Boot
    
        11
        2021.0.0
        2.3.2
        1.6.0
        0.5.1
    
    
        
            org.springframework.boot
            spring-boot-starter
        
 
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            org.lognet
            grpc-spring-boot-starter
            ${grpc-spring-boot-starter.version}
        
    
 
    
        
            
            
                kr.motd.maven
                os-maven-plugin
                ${os-maven-plugin.version}
            
        
        
            
            
                org.springframework.boot
                spring-boot-maven-plugin
            
            
            
                org.xolstice.maven.plugins
                protobuf-maven-plugin
                ${protobuf-maven-plugin.version}
                
                    com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}
                    grpc-java
                    io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}
                    ${project.build.sourceDirectory}
                    false
                
                
                    
                        
                            compile
                            compile-custom
                        
                    
                
            
        
    
 

2,拷贝Proto

和java同级目录

3,执行命令

mvn clean install

4,调用方法

CalculateService

其中 main方法,是测试方法。

GRPC启动的默认端口是6565,在main中设置了。

public class CalculateService {
    private final ManagedChannel channel;
    private final OperateGrpc.OperateBlockingStub blockingStub;
 
    private CalculateService(ManagedChannel channel) {
        this.channel = channel;
        blockingStub = OperateGrpc.newBlockingStub(channel);
    }
 
    public CalculateService(String host, int port) {
        this(ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build());
    }
 
    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }
 
    public float operate(float num1, float num2, OperateType operateType) {
        Request request = Request.newBuilder().setNum1(num1).setNum2(num2).setOpType(operateType).build();
        Response response = blockingStub.calculate(request);
        return (float) response.getResult();
    }
 
    public static void main(String[] args) {
        try {
            CalculateService service = new CalculateService("localhost", 6565);
            System.out.println(service.operate(100, 0, OperateType.Division));
            service.shutdown();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
 
}

三,结果