SpringBoot 整合gRPC

gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架。

gRPC 的主要优点是:

  • 现代高性能轻量级 RPC 框架。
  • 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。
  • 可用于多种语言的工具,以生成强类型服务器和客户端。
  • 支持客户端、服务器和双向流式处理调用。
  • 使用 Protobuf 二进制序列化减少对网络的使用。

这些优点使 gRPC 适用于:

  • 效率至关重要的轻量级微服务。
  • 需要多种语言用于开发的 Polyglot 系统。
  • 需要处理流式处理请求或响应的点对点实时服务。

     

关于GRPC,官方的介绍是:gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。从定义上可以看到这个主要是给移动应用做通信用的,其次他支持双向的通信,因此可以说GRPC是一个RPC框架没错,但是它的功能已经强于RPC,因为普通RPC是定义是一应一答的单向通信模式,而GRPC支持双向通信,毕竟做不到双向通信怎么能说是给移动应用设计的呢?
 

gRPC主要有4种请求/响应模式,分别是:

(1) 简单模式(Simple RPC)

客户端发起一次请求,服务端响应一个数据,即标准RPC通信。

ClientRequest:1,ServerResponse:1

(2) 服务端数据流模式(Server-side streaming RPC)

这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端。

ClientRequest:1,ServerResponse:N

(3) 客户端数据流模式(Client-side streaming RPC)

与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。典型的例子是物联网终端向服务器报送数据。

ClientRequest:N,ServerResponse:1

(4) 双向数据流模式(Bidirectional streaming RPC)

这是客户端和服务端都可以向对方发送数据流,这个时候双方的数据可以同时互相发送,也就是可以实现实时交互。比如聊天应用。

ClientRequest:N,ServerResponse:N

grpc:数据的序列化以及进程数据通信的交互方式
主要有以下几个过程:
(1)通过 .proto文件定义传输的接口和消息体
(2)通过protocol编译器生成server端和client端的stub程序
(3)将请求封装成Http2的Stream
(4)通过Channel作为数据通信的通道使用Socket进行数据传输


快速开发:
SpringBoot构建grpc的demo
SpringBoot版本:2.1.4.RELEASE
JDK1.8

创建2个工程:
服务提供方:grpc-provider
服务消费方:grpc-consumer

server端
步骤1:创建server端工程 grpc-provier,目录结果如下
 grpc-provider(多模块)
        - controller //请求接入
        - common  //vo,po,DTO以及和java目录同一级的proto
            - java    //存放vo, po, DTO以及根据proto生成的server端和client端的sub
            - proto
                - helloworld.proto
        - model
        - service

步骤2:common模块的依赖:(除了通用的作用,这里主要增加了proto相关的操作)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>

<groupId>com.ccb</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<os.plugin.version>1.6.0</os.plugin.version>
<grpc.version>1.15.1</grpc.version>
<protoc.version>3.6.1</protoc.version>
<protobuf.plugin.version>0.6.1</protobuf.plugin.version>
</properties>

<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>${grpc.version}</version>
</dependency>
</dependencies>

<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os.plugin.version}</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
<!--默认值-->
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<!--默认值-->
<!--<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>-->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
<clearOutputDirectory>false</clearOutputDirectory>
<!--更多配置信息可以查看" target="_blank">https://www.xolstice.org/protobuf-maven-plugin/compile-mojo.html-->;
</configuration>
<executions>
<execution>
<!--在执行mvn compile的时候会执行以下操作-->
<phase>compile</phase>
<goals>
<!--生成OuterClass类-->
<goal>compile</goal>
<!--生成Grpc类-->
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>

步骤3:创建proto
在src/main 目录下,和java同级目录创建proto目录,在该目录下创建.proto文件
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.ccb.common"; //定义输出的目录,生成的目录就是“net/devh/examples/grpc/lib”下面
option java_outer_classname = "DeviceFixProto"; //定义输出的文件名称,生成在lib下的就是HelloWorldProto.class

package device;

// The device service definition.
service DeviceFixService {
// Sends a message
rpc insertDeviceFix (deviceFix) returns (booleanReply){}
rpc updateDeviceFix (deviceFix) returns (booleanReply){}
rpc searchDeviceFix (conditionsRequest) returns (deviceFix){}
rpc deleteDeviceFix (conditionsRequest) returns (booleanReply){}
}

// The request message .
message conditionsRequest {
string id = 1;
}
message deviceFix {
string id=1;
string serialNum=2;
string userNum=3;
int32 status=4;
int32 type=5;
string address=6;
string createtime=7;
string updatetime=8;
}

// The response message
message booleanReply {
bool reply = 1;
}

// The response message
message objectReply {
bool reply = 1;
}

步骤4:根据上述proto文件生成server端和client端的stub程序:

在这里插入图片描述


步骤5:service模块的pom依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
</parent>

<groupId>com.ccb</groupId>
<artifactId>service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Demo project for Spring Boot</description>


<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>com.common</groupId>
<artifactId>grpc-springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

步骤6:service模块引入grpc依赖,重写方法
package com.ccb.service.Impl;

import com.ccb.common.DeviceFixServiceGrpc;
import com.ccb.common.booleanReply;
import com.ccb.common.deviceFix;
import io.grpc.stub.StreamObserver;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;

/**
* <p>项目名称: a </p>
* <p>文件名称: b </p>
* <p>功能描述: c </p>
* <p>创建时间: 2020/11/12 </p>
* @author Top
* @version v1.0
*/
@GrpcService(DeviceFixServiceGrpc.class)
public class DeviceGrpcService extends DeviceFixServiceGrpc.DeviceFixServiceImplBase {

@Override
public void insertDeviceFix(deviceFix request, StreamObserver<booleanReply> responseObserver) {

// 返回体构建,入参在request中,这边省略业务代码
booleanReply reply = booleanReply.newBuilder().build();
// 返回参数
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}

步骤7:相关配置信息
server.port=8080
spring.application.name=grpc-server

#grpc通信端口
grpc.server.port=9898
 

client端
步骤1:创建client工程grpc-consumer,目录如下
grpc-consumer(多层)
    - controller //请求接入
    - common
    - model     //持久层
    - service   //业务逻辑层

步骤2:pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>

<groupId>com.example</groupId>
<artifactId>demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
<description>gRPC - Spring Boot Hello World Example</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>com.common</groupId>
<artifactId>grpc-springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
</plugins>
</build>

</project>

步骤3:controller层请求接入
package com.example.demo2.controller;

import com.ccb.common.deviceFix;
import com.example.demo2.common.Result;
import com.example.demo2.common.ResultCode;
import com.example.demo2.service.impl.GrpcClientService;
import com.example.demo2.utils.ResultBulider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @Description: TODO
* @Author: Top
* @Version: V1.0
* @Date: 2020-01-15 15:03
*/
@RestController
@RequestMapping("/api/{edition}")
public class ConsumerController {

@Autowired
private GrpcClientService grpcClientService;

@GetMapping("/getUser")
@ResponseBody
public Result getUser(HttpServletRequest request, HttpServletResponse response) {
try {
deviceFix device = deviceFix.newBuilder().setAddress("北京").setSerialNum("1000").setUserNum("20").build();
return ResultBulider.succuss("成功", grpcClientService.sendMessage(device));
} catch (Exception e) {
e.printStackTrace();
return ResultBulider.faile(ResultCode.DATA_IS_WRONG);
}
}
}

步骤4:service层
package com.example.demo2.service.impl;

import com.ccb.common.DeviceFixServiceGrpc;
import com.ccb.common.booleanReply;
import com.ccb.common.deviceFix;
import io.grpc.Channel;
import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;
import org.springframework.stereotype.Service;

/**
* <p>项目名称: a </p>
* <p>文件名称: b </p>
* <p>功能描述: c </p>
* <p>创建时间: 2020/11/12 </p>
* @author Top
* @version v1.0
*/
@Service
public class GrpcClientService {

@GrpcClient("grpc-server")
private Channel serverChannel;

public booleanReply sendMessage(deviceFix request) {
DeviceFixServiceGrpc.DeviceFixServiceBlockingStub stub = DeviceFixServiceGrpc.newBlockingStub(serverChannel);
booleanReply response = stub.insertDeviceFix(request);
return response;
}

}

步骤5:配置项
grpc.client.grpc-server.host=127.0.0.1
grpc.client.grpc-server.port=9898
grpc.client.grpc-server.enableKeepAlive=true
grpc.client.grpc-server.keepAliveWithoutCalls=true

--------------------------------------------------------------------------------------------------------
以上是集成grpc是基于依赖:
<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-spring-boot-starter</artifactId>
    <version>2.5.1.RELEASE</version>
</dependency>
还有一种集成grpc的方式是基于依赖:
<dependency>
    <groupId>io.github.lognet</groupId>
    <artifactId>grpc-spring-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
这种方式的参考文档:https://blog.csdn.net/21aspnet/article/details/100727562

参考资料:
https://gitee.com/chis123/grpc-spring-boot-starter
https://blog.csdn.net/JHC23/article/details/102568845
https://blog.csdn.net/qq_35875671/article/details/106012835 (SpringBoot + gRPC + nacos)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值