什么是Grpc
gRPC 是一个现代开源的高性能 RPC 框架,可以在任何环境下运行。它可以有效地将数据中心内和跨数据中心的服务与可插拔支持进行负载均衡、跟踪、健康检查和认证。它也适用于分布式计算,将不同设备、移动应用程序和浏览器连接到后端服务。
在gRPC中,一个客户应用程序可以直接访问另外一台机器上的服务应用程序中的一个方法,就好像这个方法是一个本地对象一样,这种功能使得创建分布式应用程序和服务更加简单。和很多其他的RPC系统一样,gRPC是基于这样的思想:定义一个服务,指定一些方法,这些方法可以通过它的形式参数和返回值类型远程调用。在服务器端,服务器实现了这个接口,并且运行了一个gRPC的服务端去处理这些客户端调用。
gRPC客户端和服务端在各种环境下都能相互通信,从google内部的服务器到你自己台式机上的服务器,而且可以使用gRPC支持的各种语言来实现gRPC客户端和服务器端。因此,你可以非常容易地创建一个用java语言写的gRPC服务器和一个用go语言或者Python语言或者Ruby语言写gRPC客户端。除此之外,最新的Google API也有gRPC版本的接口,这样用户可以非常方便的将Google的功能集成到自己的应用程序中。
使用场景
- 在微服务架构中有效地连接多个服务
- 将移动设备、浏览器客户端连接到后端服务
- 生成高效的客户端库
- 不同项目、产品之间的交互
使用Protocol Buffers
默认情况下,gRPC使用Protocol Buffers,这是Google的开源成熟序列化结构化数据的机制(不过,gRPC也可以和其他的数据格式一起使用,比如JSON)。这是一份关于如何使用Protocol Buffers的快速介绍。如果你已经对Protocol Buffers比较熟悉了,可以先跳到下一节。
使用Protocol Buffers的第一步是在一个proto文件中定义你想要序列化的数据结构,Proto文件是一个扩展名为.proto的普通文本文件。Protocol Buffers数据是结构化为message的,一个message是一个小的逻辑信息单元,这个逻辑信息单元包含一系列的键值对,这些键值对被称为字段。这里有一个例子: ```java // The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} }
// The request message containing the user’s name. message HelloRequest { string name = 1; }
// The response message containing the greetings message HelloReply { string message = 1; }
<a name="F7Zca"></a>
# Springboot集成Grpc
<a name="T0HUo"></a>
## 创建qingfeng-grpc项目
项目创建好之后,继续创建qingfeng-grpclib模块、qingfeng-server模块、qingfeng-client模块。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12591990/1651403439991-c2d7e4e6-8fd8-4bae-a6bc-542bc82be355.png#clientId=u3222c419-0fae-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=245&id=u3f5ec06c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=294&originWidth=417&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21335&status=done&style=none&taskId=u8ad85317-df23-49d5-8cfc-58d64b5050d&title=&width=347.4999861915912)<br />引入pom依赖
```java
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>qingfeng-grpclib</module>
<module>qingfeng-server</module>
<module>qingfeng-client</module>
<module>qingfeng-protobuf</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.qingfeng</groupId>
<artifactId>qingfeng-grpc</artifactId>
<version>1.0-SNAPSHOT</version>
<name>qingfeng-grpc</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.com.qingfeng</groupId>
<artifactId>com.qingfeng-grpclib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--核心grpc-spring-boot依赖-->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
创建qingfeng-grpclib
引入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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qingfeng-grpc</artifactId>
<groupId>com.qingfeng</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.qingfeng</groupId>
<artifactId>qingfeng-grpclib</artifactId>
<version>1.0-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>
<!--更多配置信息可以查看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>
在线构建protobuf代码
<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>
<!--更多配置信息可以查看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>
创建Greeter.proto
syntax = "proto3";
option java_package = "com.qingfeng.grpc.lib";
// The greeting service definition.
service Greeter{
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
执行maven compile 编译
创建qingfeng-server服务端
引入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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qingfeng-grpc</artifactId>
<groupId>com.qingfeng</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qingfeng-server</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.qingfeng</groupId>
<artifactId>qingfeng-grpclib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<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>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
创建application.yml
spring:
application:
name: qingfeng-server
grpc:
server:
port: 9000
server:
port: 9002
创建GreeterService
package com.qingfeng.service;
import com.qingfeng.grpc.lib.GreeterGrpc;
import com.qingfeng.grpc.lib.GreeterOuterClass;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;
@Slf4j
@GrpcService(GreeterOuterClass.class)
public class GreeterService extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(GreeterOuterClass.HelloRequest request, StreamObserver<GreeterOuterClass.HelloReply> responseObserver) {
String message = "Hello " + request.getName();
final GreeterOuterClass.HelloReply.Builder replyBuilder = GreeterOuterClass.HelloReply.newBuilder().setMessage(message);
responseObserver.onNext(replyBuilder.build());
responseObserver.onCompleted();
log.info("Returning " + message);
}
}
完成后-启动服务
创建qingfeng-client客户端
引入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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qingfeng-grpc</artifactId>
<groupId>com.qingfeng</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qingfeng-client</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.qingfeng</groupId>
<artifactId>qingfeng-grpclib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
创建application.yml
server:
port: 9001
spring:
application:
name: qingfeng-client
grpc:
client:
qingfeng-server:
port: 9000
enableKeepAlive: true
keepAliveWithoutCalls: true
创建GrpcClientService
package com.qingfeng.service;
import com.qingfeng.grpc.lib.GreeterGrpc;
import com.qingfeng.grpc.lib.GreeterOuterClass;
import com.qingfeng.grpc.lib.InterruptGrpc;
import com.qingfeng.grpc.lib.InterruptStatus;
import io.grpc.Channel;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Service
public class GrpcClientService {
@GrpcClient("qingfeng-server")
private Channel serverChannel;
public String sendMessage(String name) {
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverChannel);
GreeterOuterClass.HelloReply response = stub.sayHello(GreeterOuterClass.HelloRequest.newBuilder().setName(name).build());
return response.getMessage();
}
}
创建GrpcClientController
@RestController
public class GrpcClientController {
@Autowired
private GrpcClientService grpcClientService;
@RequestMapping("/")
public String printMessage(@RequestParam(defaultValue = "青锋") String name) {
return grpcClientService.sendMessage(name);
}
}
完成后-启动客户端测试
在浏览器输入 http://localhost:9001/