gRPC快速整合SpringCloud

gRPC是由 google开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于HTTP/2协议标准而设计,同时支持大多数流行的编程语言。它是一种与语言、平台无关、可扩展的序列化结构数据。它的定位类似于JSON、XML,但是比他们更小、更快、更简单。

优势

gRPC基于HTTP/2协议传输,而HTTP/2相比HTTP1.x,还是有需要优势的:

HTTP/2采用二进制格式传输协议,而非HTTP1.x的文本格式。



多路复用

HTTP/2支持通过一个连接发送多个并发的请求。

服务器推送

服务端推送是一种在客户端请求之前发送数据的机制。在HTTP/2中,服务器可以对客户端的一个请求发送多个响应。而不像HTTP/1.X一样,只能通过客户端发起request,服务端才产生对应的response。

减少网络流量的头部压缩

HTTP/2对消息头进行了压缩传输,能够节省消息头占用的网络流量。

工作方式


从上图可以看出,简单了解一下grpc的工作模式。用gRPC来进行远程调用服务,客户端(client) 仅仅需要gRPC Stub ,通过Proto Request向gRPC Server发起服务调用,然后 gRPC Server通过Proto Response(s)将调用结果返回给调用的client。

使用场景

接口约束:需要对接口有严格的管控,比如对外部提供接口时,并不希望客户端随意传递数据,这是我们就可以使用gRPC来对接口约束。

性能要求:对传输性能有较高要求,如果我们传输的消息体过大,或调度过于频繁不希望影响系统性能时,可以考虑使用gRPC,它的消息体比JSON或者文本传输要小的多。

Protobuf语法

基本规范

文件以.proto做为文件后缀,除结构定义外的语句以分号结尾

结构定义可以包含:message、service、enum

rpc方法定义结尾的分号可有可无

Message命名采用驼峰命名方式,字段命名采用小写字母加下划线分隔方式

Enums类型名采用驼峰命名方式,字段命名采用大写字母加下划线分隔方式

Service与rpc方法名统一采用驼峰式命名

message SongServerRequest {

    required string song_name = 1; 

}

enum Foo {     

  FIRST_VALUE = 1;     

  SECOND_VALUE = 2; 

}

限定修饰符

Required: 表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。

Optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。

Repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。

数据类型

.protoC++JavaPythonGoRubyC#

doubledoubledoublefloatfloat64Floatdouble

floatfloatfloatfloatfloat32Floatfloat

int32int32intintint32Fixnum or Bignumint

int64int64longing/long[3]int64Bignumlong

uint32uint32int[1]int/long[3]uint32Fixnum or Bignumuint

uint64uint64long[1]int/long[3]uint64Bignumulong

sint32int32intintjint32Fixnum or Bignumint

sint64int64longint/long[3]int64Bignumlong

fixed32uint32int[1]intuint32Fixnum or Bignumuint

fixed64uint64long[1]int/long[3]uint64Bignumulong

sfixed32int32intintint32Fixnum or Bignumint

sfixed64int64longint/long[3]int64Bignumlong

boolboolbooleanbooleanboolTrueClass/FalseClassbool

stringstringStringstr/unicode[4]stringString(UTF-8)string

bytesstringByteStringstr[]byteString(ASCII-8BIT)ByteString

gRPC整合SpringCloud & Nacos

其实,第一次了解gRPC,也是在Nacos2.0升级的时候,Nacos2.0版本相比1.X新增了gRPC的通信方式。

端口与主端口的偏移量描述

98481000客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求

98491001服务端gRPC请求服务端端口,用于服务间同步等

核心依赖

<properties>

        <java.version>8</java.version>

        <nacos.version>2.2.5.RELEASE</nacos.version>

        <mapstruct.version>1.3.1.Final</mapstruct.version>

        <grpc.starter.version>2.10.1.RELEASE</grpc.starter.version>

        <grpc.client.version>2.10.1.RELEASE</grpc.client.version>

        <lombok.version>1.18.12</lombok.version>

        <fastjson.version>1.2.76</fastjson.version>

        <freemarker.verson>2.3.28</freemarker.verson>

        <nacos.client>2.0.0</nacos.client>

    </properties>

    <dependency>

      <groupId>net.devh</groupId>

      <artifactId>grpc-client-spring-boot-starter</artifactId>

      <version>${grpc.client.version}</version>

    </dependency>

    <dependency>

        <groupId>net.devh</groupId>

        <artifactId>grpc-server-spring-boot-starter</artifactId>

        <version>${grpc.starter.version}</version>

    </dependency>

项目结构


API

编写pom配置。

<dependencies>

        <dependency>

            <groupId>net.devh</groupId>

            <artifactId>grpc-server-spring-boot-starter</artifactId>

        </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.xolstice.maven.plugins</groupId>

                <artifactId>protobuf-maven-plugin</artifactId>

                <version>0.6.1</version>

                <configuration>

                    <protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact>

                    <pluginId>grpc-java</pluginId>

                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.34.1:exe:${os.detected.classifier}</pluginArtifact>

                    <!--设置grpc生成代码到指定路径-->

                    <outputDirectory>${project.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.codehaus.mojo</groupId>

                <artifactId>build-helper-maven-plugin</artifactId>

                <version>3.0.0</version>

                <executions>

                    <!-- 添加主源码目录 -->

                    <execution>

                        <id>add-source</id>

                        <phase>generate-sources</phase>

                        <goals>

                            <goal>add-source</goal>

                        </goals>

                        <configuration>

                            <sources>

                                <source>${project.basedir}/src/main/gen</source>

                                <source>${project.basedir}/src/main/java</source>

                            </sources>

                        </configuration>

                    </execution>

                </executions>

            </plugin>

        </plugins>

    </build>


新建 src\main\proto 目录,编写 user.ptoto。

syntax = "proto3";

option java_multiple_files = true;

option java_package = "com.yx.grpc.user";

service UserService {

  rpc queryUser(UserRequest) returns (UserReply) {}

}

message UserRequest {

  int64 id = 2;

}

message UserReply {

  int32 code = 1;

  string msg = 2;

  bool success = 3;

  message Data {

    UserPb userPb = 1;

  }

  Data data = 4;

}

message UserPb {

  int64 id = 1;

  string name = 2;

  string sex = 3;

}

执行 mvn compile,生成代码。


服务端

核心服务实现类。

@GrpcService

public class UserServiceImpl  extends UserServiceGrpc.UserServiceImplBase{

    @Override

    public void queryUser(UserRequest request, StreamObserver<UserReply> responseObserver) {

        UserReply.Builder userReply =  UserReply.newBuilder();

        TblUser tblUser = new TblUser(11L, "syx", "nan");

        userReply.setCode(200).setMsg("SUCCESS").setSuccess(true);

        userReply.setData(UserReply.Data.newBuilder()

                .setUserPb(UserPb.newBuilder()

                        .setId(tblUser.getId())

                .setName(tblUser.getName())

                .setSex(tblUser.getSex())));

        responseObserver.onNext(userReply.build());

        responseObserver.onCompleted();

        super.queryUser(request, responseObserver);

    }

}

客户端

gRPC配置。

grpc:

  client:

    GLOBAL:

      negotiation-type: plaintext

      enable-keep-alive: true

      keep-alive-without-calls: true


自定义请求转换器。

@Configuration

public class MessageConverter {

    @Bean

    public HttpMessageConverters protobufHttpMessageConverter() {

        ProtobufHttpMessageConverter protobufHttpMessageConverter = new ProtobufHttpMessageConverter();

        protobufHttpMessageConverter.setSupportedMediaTypes(Lists.newArrayList(MediaType.APPLICATION_JSON, MediaType.parseMediaType(MediaType.TEXT_PLAIN_VALUE + ";charset=ISO-8859-1")));

        return new HttpMessageConverters(protobufHttpMessageConverter);

    }

}

请求测试类。

@RestController

@RequestMapping("/user")

@Slf4j

public class UserController {

    @GrpcClient("yx-grpc-service")

    UserServiceGrpc.UserServiceFutureStub futureStub;

    @RequestMapping(value="/queryUser/{id}")

    public UserReply queryUser(@PathVariable Integer id)  {

        UserReply userReply = null;

        try {

            userReply = futureStub.queryUser(UserRequest.newBuilder().setId(id).build()).get();

            return userReply;

        } catch (Exception e) {

        }

        return userReply;

    }

}


测试

启动服务端和客户端,访问 http://localhost:8002/user/queryUser/1 。



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容

  • 1.简介 1.1 问题 目前程序开发中,一个程序基本上是以各个服务组成,例如一个简单的系统,用户发起rest请求,...
    秃头猿猿阅读 2,741评论 0 3
  • 1、linux下nacos安装 1-1、下载安装包 官网(https://nacos.io/zh-cn/docs/...
    big2j阅读 532评论 0 0
  • gRPC SkyLB gRPC 作为一款高性能、通用的 RPC 框架,相比传统的RPC框架有着自己天然的优势: p...
    彬臣阅读 446评论 0 0
  • 1. Spring Cloud简介 Spring Cloud只是将各家公司开发的比较成熟、经得起实际考验的服务框架...
    皇天阅读 262评论 0 0
  • 简介 GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x...
    固安李庆海阅读 5,150评论 0 1