Grpc框架+Protobuf 搭建以及使用(入门)

1.Grpc框架简介

Google开发的一个高性能、开源和通用的 RPC 框架,基于ProtoBuf(Protocol Buffers) 序列化协议开发,且支持众多开发语言。面向服务端和移动端,基于 HTTP/2 设计。

2.Grpc框架特性

  • grpc可以跨语言使用。支持多种语言 支持C++、Java、Go、Python、Ruby、C#、Node.js、Android Java、Objective-C、PHP等编程语言
  • 基于 IDL ( 接口定义语言(Interface Define Language))文件定义服务,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub;
  • 通信协议基于标准的 HTTP/2 设计,支持·双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量;
  • 序列化支持 PB(Protocol Buffer)和 JSON,PB 是一种语言无关的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 调用的高性能。
  • 安装简单,扩展方便(用该框架每秒可达到百万个RPC)

3.Grpc执行流程

Grpc框架+Protobuf 搭建以及使用(入门)_第1张图片

1、客户端(gRPC Stub)调用 A 方法,发起 RPC 调用。
2、对请求信息使用 Protobuf 进行对象序列化压缩(IDL)。
3、服务端(gRPC Server)接收到请求后,解码请求体,进行业务逻辑处理并返回。
4、对响应结果使用 Protobuf 进行对象序列化压缩(IDL)。
5、客户端接受到服务端响应,解码请求体。回调被调用的 A 方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果。

4.Rpc与HttpAPI的优劣势

Grpc(远程过程调用)与HTTP远程调用

5. Grpc框架特性搭建

  5.1.框架准备条件

  ①:JDK11(上文也提及基于 HTTP/2,JDK11之后才开始正式使用HTTP/2)

  ②:Protobuf插件(上文也提及基于protobuf序列化协议,用插件读.proto生成Stub代码)

  5.2.工程搭建

  ①:spring-grpc:一个主工程做依赖管理

  ②:client:Grpc的客户端

  ③:server:Grpc的服务端

  ④:grpc-lib:通过.proto文件生成stub的java文件 

  Grpc框架+Protobuf 搭建以及使用(入门)_第2张图片

 5.3.各工程依赖

  ①:主工程依赖(此处的net.devh的两个starter集成了Grpc的一些繁琐配置,开包即用很方便)

          另外感谢yindongnan作者为开源做出的贡献



    4.0.0

    org.example
    spring-grpc
    pom
    1.0-SNAPSHOT
    
        client
        server
        grpc-lib
    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.13.RELEASE
        
    
    
        11
        11
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            net.devh
            grpc-client-spring-boot-starter
            2.10.1.RELEASE
        
        
            net.devh
            grpc-server-spring-boot-starter
            2.10.1.RELEASE
        
    

  ②:grpc-lib工程依赖(此处完全是抄别人的,主要是配置proto生成的stub路径等等)



    
        spring-grpc
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    grpc-lib

    
        11
        11
    
    
        
            
                kr.motd.maven
                os-maven-plugin
                1.4.1.Final
            
        
        
            
                org.xolstice.maven.plugins
                protobuf-maven-plugin
                0.5.0
                
                    com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}
                    grpc-java
                    io.grpc:protoc-gen-grpc-java:1.34.1:exe:${os.detected.classifier}
                    
                    ${project.basedir}/src/main/java
                    
                    false
                
                
                    
                        
                            compile
                            compile-custom
                        
                    
                
            

            
            
                org.codehaus.mojo
                build-helper-maven-plugin
                3.0.0
                
                    
                    
                        add-source
                        generate-sources
                        
                            add-source
                        
                        
                            
                                ${project.basedir}/src/main/gen
                                ${project.basedir}/src/main/java
                            
                        
                    
                
            

        
    

  ③:server端依赖(没什么特别的,client也雷同)



    
        spring-grpc
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    client
    
        
            org.example
            grpc-lib
            1.0-SNAPSHOT
            compile
        
    

    
        11
        11
    

5.4.编写proto文件

  proto 3 语法不熟悉的可以去查一查

// 基于proto3版本
syntax = "proto3";

option java_multiple_files = true;
// 生成java代码的包路径
option java_package = "com.yuwenwen.grpc";

// grpc服务
service YuWenWenService{
// 一个查询接口
rpc CheckUser(ApiIn) returns (ApiOut) {}
}
// 定义接口入参数
message ApiIn{
  string name = 1;
  string code = 2;
  int64 age =3;
}
// 定义接口返回参数
message ApiOut {
  bool success = 1;
  string auth=2;
}

5.5.compile生成Stub java代码

  此处注意:在grpc-lib的工程下,java包和proto包保持平级。

  Grpc框架+Protobuf 搭建以及使用(入门)_第3张图片

  compile代码之后就会按照指定的路径生成Stub代码 

 

   生成完的效果

Grpc框架+Protobuf 搭建以及使用(入门)_第4张图片

 5.6.Grpc服务端

  ①:application定义服务端的端口和名称

grpc:
  server:
    port: 8888
spring:
  application:
    name: grpc-server
server:
  port: 8890

  ②:业务Service继承生成的java代码

在用工具生成的代码中(YuWenWenServiceGrpc.java)有很多内部类

选择继承 YuWenWenServiceImplBase.java并标注上starter中封装好的@GrpcService注解

Grpc框架+Protobuf 搭建以及使用(入门)_第5张图片

 注意:responseObserver.onNext方法被调用,可以向客户端输出数据,最后通过          responseObserver.onCompleted结束输出

package com.yu.service;

import com.yuwenwen.grpc.ApiIn;
import com.yuwenwen.grpc.ApiOut;
import com.yuwenwen.grpc.YuWenWenServiceGrpc.YuWenWenServiceImplBase;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;

@GrpcService
public class YuWenWenServiceImpl extends YuWenWenServiceImplBase {

    @Override
    public void checkUser(ApiIn request, StreamObserver responseObserver) {
        ApiOut rep = ApiOut.newBuilder().setAuth("admin").setSuccess(true).build();
        responseObserver.onNext(rep);
        responseObserver.onCompleted();
    }
}

5.6.1. StreamObserver深研究

这个接口有三个抽象方法,而且命名规则来看是用了观察者模式。

public interface StreamObserver {
    void onNext(V var1);

    void onError(Throwable var1);

    void onCompleted();
}
其中的onNext、onError以及onComplete⽅法均会调⽤内部的ServerCall实例发送消息。
具体发送逻辑实现这⾥不做深⼊,总之可以明确的是,这⾥的StreamObserver回调接⼝,其实现逻辑就是将消息发送⾄客户端,这就是观
察者的逻辑。再看下被观察者,也就是StreamObserver回调接⼝的调⽤⽅。其实就是实现类⾥返回值的⽣成的逻辑,我们需要根据
request取到参数,然后⽣成返回值,调⽤StreamObserver回调接⼝,来通知Grpc框架层发送返回值。⾄此服务端实现⽅法⾥的
StreamObserver已经清晰了:被观察的对象就是返回值,Grpc框架层是观察者,提供发送逻辑作为回调函数,实现类是被观察者,每⼀
次返回值的⽣成都会调⽤回调函数通知Grpc。还有⼀点,StreamObserver接⼝的定义其实和stream息息相关。我们知道stream模式意
味着可以在⼀个连接中发送多条消息,所以该接⼝提供了onNext回调函数,该函数可以被多次调⽤,每⼀次对onNext的调⽤都代表⼀条消
息的发送。如果全部发送完了或者发送出错,那么就需要调⽤onError或者onComplete来告知对⽅本次stream已经结束。所以该接⼝的设
计也与stream的概念也完全契合。

  ③:启动类

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

5.7.客户端

  ①:依赖Stub代码

  RPC(Remote Procedure Call)的中文:远程过程调用
  RPC框架追求的就是,两个服务之间的调用就如同调本地方法一样

package com.yuwenwen.controller;

import com.yuwenwen.grpc.ApiIn;
import com.yuwenwen.grpc.ApiOut;
import com.yuwenwen.grpc.YuWenWenServiceGrpc.YuWenWenServiceBlockingStub;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/userInfo")
public class UserInfoController {

    @GrpcClient("grpc-server")
    YuWenWenServiceBlockingStub yuWenWenStub;

    @RequestMapping(value = "/query")
    public String queryUser() {
        ApiOut apiOut = yuWenWenStub.checkUser(ApiIn.newBuilder().setAge(25).setCode("1124").build());
        String result = apiOut.getSuccess() ? "successfully" : "failed";
        return result;
    }
}

②:application定义客户端和服务端的端口和名称

grpc:
  client:
    grpc-server:
      // # gRPC服务端地址
      address: static://localhost:8888
      enableKeepAlive: true
      keepAliveWithoutCalls: true
      negotiationType: plaintext
spring:
  application:
    name: grpc-client
server:
  port: 8891

③:启动类

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

6.Postman测试

 Grpc框架+Protobuf 搭建以及使用(入门)_第6张图片

 结果:

 Grpc框架+Protobuf 搭建以及使用(入门)_第7张图片

 以上就可以完成一个简易版的Grpc框架以及服务之间的调用

你可能感兴趣的:(rpc,java,spring,boot)