常用的RPC架构系列---gRPC

gRPC是谷歌的一个高性能,开源的高性能 RPC 框架,gRPC面向移动和HTTP/2设计。gRPC隐藏了底层的实现细节,包括序列化(json,xml),数据传输(TCP,HTTP,UDP),反序列化等,它可以有效地将数据中心内和跨数据中心的服务与可插拔支持进行负载均衡、跟踪、健康检查和认证。gRPC使用在移动设备上能表现更好的特性,例如更省电,更省空间。

gRPC设计理念

定义一个服务,指定其能够被远程调用的方法。在服务端实现这个接口,并运行一个gRPC服务来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。gRPC客户端和服务端都可以在这种环境中运行和交互。

file

gRPC主要使用场景

在gRPC项目中,客户端应用可以像调用本地对象一样直接调用另一台不同机器的服务端应用,更能够容易的创建分布式应用和服务。

  • 在微服务架构中有效的连接多个服务
  • 将移动设备,浏览器客户端连接到后端服务
  • 生成高效的客户端

spring boot集成gRPC

因为gRPC依赖Protocol Buffers,所以先简单看看什么是Protocol Buffers。

Protocol Buffers 简称protobuf,是一种高效,轻便,易用的结构化数据存储格式。数据存储格式使用最多的是JSON,XML,他们简单,易读,与平台,语言无关。那么既然有JSON,XML,为什么还要有protobuf。普遍认为有两种原因:

  • protobuf具有了JSON,XML格式所有有点
  • protobuf解析速度比JSON,XML快,效率高
  • protobuf序列化数据非常紧凑,简洁

1,idea安装protobuf插件。

setting-->Plugins ,搜到protobuf support,然后点击安装即可,最后重启idea

file

2,新建grpc父项目。

分别新建三个模块:grpc-lib,grpc-server(使用开源grpc-server-spring-boot-starter组件),grpc-client(使用开源grpc-client-spring-boot-starter组件)

组件官网:https://github.com/yidongnan/grpc-spring-boot-starter

因为使用父项目的pom.xml来管理,所以pom.xml内容如下:



    4.0.0

    com.grpc
    grpc
    pom
    1.0-SNAPSHOT
    
        grpc-lib
        grpc-server
        grpc-client
    


    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.5.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
        2.0.5.RELEASE
        2.0.1.RELEASE

    

    
        
            
            
                io.spring.platform
                platform-bom
                Cairo-RELEASE
                pom
                import
            
            
            
                com.grpc
                grpc-lib
                ${project.version}
            
            
            
                net.devh
                grpc-client-spring-boot-starter
                ${net-devh-grpc.version}
            
            
                net.devh
                grpc-server-spring-boot-starter
                ${net-devh-grpc.version}
            
        
    


  • grpc-lib

其中grpc-lib的pom.xml:



    
        grpc
        com.grpc
        1.0-SNAPSHOT
    
    4.0.0

    grpc-lib

    
        1.6.0
        1.15.1
        3.6.1
        0.6.1
    

    
        
            io.grpc
            grpc-all
            ${grpc.version}
        
    

    
        
            
                kr.motd.maven
                os-maven-plugin
                ${os.plugin.version}
            
        
        
            
                org.xolstice.maven.plugins
                protobuf-maven-plugin
                ${protobuf.plugin.version}
                true
                
                    com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
                    grpc-java
                    io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
                    
                    ${project.basedir}/src/main/proto
                    
                    
                    ${project.basedir}/src/main/java
                    
                    false
                    
                
                
                    
                        
                        compile
                        
                            
                            compile
                            
                            compile-custom
                        
                    
                
            
        
    

在lib模块下新建proto文件夹,加入以下ptoro文件:

syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.grpc.proto.service";
service HelloService{
    rpc SayHello(HelloRequest) returns (HelloResponse){}
}
message HelloRequest{
    string username = 1;
}
message HelloResponse{
    string message = 1;
}

上面的ptoro文件中

  • syntax指定了protobuf版本为proto3。
  • option java_package:指定生成类的报名
  • option java_multiple_files有两个值,true和false。如果为true,每个message和service都会被生成为一个类。如果是false,则所有的message和service都将会是java_outer_classname的内部类
  • service HelloService:定义Rpc的Service,这里需要注意:下面的方法的传入参数和返回类型都必须是message
  • message HelloRequest:相当于请求参数,为string类型
  • message HelloResponse:相当于返回参数,为string类型。

运行protobuf插件的compile和compile-custom功能,生成java代码到src/main/java目录下。见图:

file
  • grpc-server
    grpc-server模块pom.xml文件如下:

      
      
          grpc
          com.grpc
          1.0-SNAPSHOT
      
      4.0.0
      grpc-server
      
          
              com.grpc
              grpc-lib
          
          
              org.springframework.boot
              spring-boot-starter
          
          
              org.springframework.boot
              spring-boot-starter-test
              test
          
          
              org.projectlombok
              lombok
          
          
              net.devh
              grpc-server-spring-boot-starter
          
      
    

(1)application.yml文件:

file

说明:在使用grpc-server-spring-boot-starter组件时,可以设置 gRPC 的 host(默认:0.0.0.0) 跟 port (默认9090)

(2)HelloService类

@GrpcService(HelloServiceGrpc.class)
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase {
    @Override
    public void sayHello(HelloRequest request, StreamObserver responseObserver) {
        System.out.println("GRPC servier "+ request.getUsername());
        HelloResponse helloResponse = HelloResponse.newBuilder().setMessage("GRPC servier "+ request.getUsername()).build();
        responseObserver.onNext(helloResponse);
        responseObserver.onCompleted();
    }
}

这里,server端就完成了。

  • grpc-client

grpc-client模块的pom.xml:



    
        grpc
        com.grpc
        1.0-SNAPSHOT
    
    4.0.0
    grpc-client
    
        
            com.grpc
            grpc-lib
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.projectlombok
            lombok
        
        
            net.devh
            grpc-client-spring-boot-starter
        
    

(1)application.yml文件:

file

说明:这里我没有配置指定grpc-server地址和端口,如果没有配置,那将会按照下面的方式进行解析:

  • 如果存在一个 DiscoveryClient 的 bean,这时会使用 client name 去注册中心上进行获取对应服务的 address
  • 否则 client 端将使用 localhost 和 9090 端口

(2)HelloClient类

@Service
public class HelloClient {
    @GrpcClient("grpc-server")
    private Channel serverChannel;
    public String sayHello(String username){
        return HelloServiceGrpc.newBlockingStub(serverChannel).sayHello(HelloRequest.newBuilder().setUsername(username).build()).getMessage();
    }
}

说明:@GrpcClient("grpc-server"),指定的值为grpc服务提供方名称,这里是grpc-server。

(3)HelloController类

@RestController
public class HelloController {
    @Autowired
    private HelloClient client;
    @GetMapping("/sayHello")
    public String sayHello(String username){
        return client.sayHello(username);
    } 
}

这里,client端就完成了。

3,测试

先启动server,再启动client。使用浏览器访问client端接口:http://localhost:8081/sayHello?username=张三

server端打印:

file

client端效果:

file

总结,spring boot与gRPC整合还是很简单,最重要的是版本要一致,然后对proto语法有个大致的了解。

本人水平有限,难免有错误或遗漏之处,望大家指正和谅解,提出宝贵意见,愿与之交流。

你可能感兴趣的:(常用的RPC架构系列---gRPC)