软件编程
位置:首页>> 软件编程>> java编程>> 一文详解gRPC快速整合SpringCloud

一文详解gRPC快速整合SpringCloud

作者:东小西  发布时间:2021-12-11 05:01:02 

标签:gRPC,SpringCloud,快速整合

gRPC

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

优势

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

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

一文详解gRPC快速整合SpringCloud

  • 多路复用

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

  • 服务器推送

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

  • 减少网络流量的头部压缩

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

工作方式

一文详解gRPC快速整合SpringCloud

从上图可以看出,简单了解一下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>

项目结构

一文详解gRPC快速整合SpringCloud

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,生成代码。

一文详解gRPC快速整合SpringCloud

服务端

  • 核心服务实现类。

@GrpcService
public class UserServiceImpl  extends UserServiceGrpc.UserServiceImplBase{
   @Override
   public void queryUser(UserRequest request, StreamObserver&lt;UserReply&gt; 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 。

一文详解gRPC快速整合SpringCloud

一文详解gRPC快速整合SpringCloud

Gitee 地址:gitee.com/renxiaoshi/&hellip;

来源:https://juejin.cn/post/7212942861519306789

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com