gRPC是谷歌的一个高性能,开源的高性能 RPC 框架,gRPC面向移动和HTTP/2设计。gRPC隐藏了底层的实现细节,包括序列化(json,xml),数据传输(TCP,HTTP,UDP),反序列化等,它可以有效地将数据中心内和跨数据中心的服务与可插拔支持进行负载均衡、跟踪、健康检查和认证。gRPC使用在移动设备上能表现更好的特性,例如更省电,更省空间。
gRPC设计理念
定义一个服务,指定其能够被远程调用的方法。在服务端实现这个接口,并运行一个gRPC服务来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。gRPC客户端和服务端都可以在这种环境中运行和交互。
gRPC主要使用场景
在gRPC项目中,客户端应用可以像调用本地对象一样直接调用另一台不同机器的服务端应用,更能够容易的创建分布式应用和服务。
- 在微服务架构中有效的连接多个服务
- 将移动设备,浏览器客户端连接到后端服务
- 生成高效的客户端
spring boot集成gRPC
因为gRPC依赖Protocol Buffers,所以先简单看看什么是Protocol Buffers。
Protocol Buffers 简称protobuf,是一种高效,轻便,易用的结构化数据存储格式。数据存储格式使用最多的是JSON,XML,他们简单,易读,与平台,语言无关。那么既然有JSON,XML,为什么还要有protobuf。普遍认为有两种原因:
- protobuf具有了JSON,XML格式所有有点
- protobuf解析速度比JSON,XML快,效率高
- protobuf序列化数据非常紧凑,简洁
1,idea安装protobuf插件。
setting-->Plugins ,搜到protobuf support,然后点击安装即可,最后重启idea
2,新建grpc父项目。
分别新建三个模块:grpc-lib,grpc-server(使用开源grpc-server-spring-boot-starter组件),grpc-client(使用开源grpc-client-spring-boot-starter组件)
组件官网:https://github.com/yidongnan/grpc-spring-boot-starter
因为使用父项目的pom.xml来管理,所以pom.xml内容如下:
4.0.0
com.grpc
grpc
pom
1.0-SNAPSHOT
grpc-lib
grpc-server
grpc-client
org.springframework.boot
spring-boot-starter-parent
2.0.5.RELEASE
UTF-8
UTF-8
1.8
2.0.5.RELEASE
2.0.1.RELEASE
io.spring.platform
platform-bom
Cairo-RELEASE
pom
import
com.grpc
grpc-lib
${project.version}
net.devh
grpc-client-spring-boot-starter
${net-devh-grpc.version}
net.devh
grpc-server-spring-boot-starter
${net-devh-grpc.version}
- grpc-lib
其中grpc-lib的pom.xml:
grpc
com.grpc
1.0-SNAPSHOT
4.0.0
grpc-lib
1.6.0
1.15.1
3.6.1
0.6.1
io.grpc
grpc-all
${grpc.version}
kr.motd.maven
os-maven-plugin
${os.plugin.version}
org.xolstice.maven.plugins
protobuf-maven-plugin
${protobuf.plugin.version}
true
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
${project.basedir}/src/main/proto
${project.basedir}/src/main/java
false
compile
compile
compile-custom
在lib模块下新建proto文件夹,加入以下ptoro文件:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.grpc.proto.service";
service HelloService{
rpc SayHello(HelloRequest) returns (HelloResponse){}
}
message HelloRequest{
string username = 1;
}
message HelloResponse{
string message = 1;
}
上面的ptoro文件中
- syntax指定了protobuf版本为proto3。
- option java_package:指定生成类的报名
- option java_multiple_files有两个值,true和false。如果为true,每个message和service都会被生成为一个类。如果是false,则所有的message和service都将会是java_outer_classname的内部类
- service HelloService:定义Rpc的Service,这里需要注意:下面的方法的传入参数和返回类型都必须是message
- message HelloRequest:相当于请求参数,为string类型
- message HelloResponse:相当于返回参数,为string类型。
运行protobuf插件的compile和compile-custom功能,生成java代码到src/main/java目录下。见图:
-
grpc-server
grpc-server模块pom.xml文件如下:grpc com.grpc 1.0-SNAPSHOT 4.0.0 grpc-server com.grpc grpc-lib org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test org.projectlombok lombok net.devh grpc-server-spring-boot-starter
(1)application.yml文件:
说明:在使用grpc-server-spring-boot-starter组件时,可以设置 gRPC 的 host(默认:0.0.0.0) 跟 port (默认9090)
(2)HelloService类
@GrpcService(HelloServiceGrpc.class)
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver responseObserver) {
System.out.println("GRPC servier "+ request.getUsername());
HelloResponse helloResponse = HelloResponse.newBuilder().setMessage("GRPC servier "+ request.getUsername()).build();
responseObserver.onNext(helloResponse);
responseObserver.onCompleted();
}
}
这里,server端就完成了。
- grpc-client
grpc-client模块的pom.xml:
grpc
com.grpc
1.0-SNAPSHOT
4.0.0
grpc-client
com.grpc
grpc-lib
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
net.devh
grpc-client-spring-boot-starter
(1)application.yml文件:
说明:这里我没有配置指定grpc-server地址和端口,如果没有配置,那将会按照下面的方式进行解析:
- 如果存在一个 DiscoveryClient 的 bean,这时会使用 client name 去注册中心上进行获取对应服务的 address
- 否则 client 端将使用 localhost 和 9090 端口
(2)HelloClient类
@Service
public class HelloClient {
@GrpcClient("grpc-server")
private Channel serverChannel;
public String sayHello(String username){
return HelloServiceGrpc.newBlockingStub(serverChannel).sayHello(HelloRequest.newBuilder().setUsername(username).build()).getMessage();
}
}
说明:@GrpcClient("grpc-server"),指定的值为grpc服务提供方名称,这里是grpc-server。
(3)HelloController类
@RestController
public class HelloController {
@Autowired
private HelloClient client;
@GetMapping("/sayHello")
public String sayHello(String username){
return client.sayHello(username);
}
}
这里,client端就完成了。
3,测试
先启动server,再启动client。使用浏览器访问client端接口:http://localhost:8081/sayHello?username=张三
server端打印:
client端效果:
总结,spring boot与gRPC整合还是很简单,最重要的是版本要一致,然后对proto语法有个大致的了解。
本人水平有限,难免有错误或遗漏之处,望大家指正和谅解,提出宝贵意见,愿与之交流。