介绍
gRPC简介
gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment.
gRPC是一个现代、开源、高性能的远程调用(RPC) 框架,可以在任何环境中运行
适合场景
gRPC非常适合以下场景:
- 微服务 - gRPC设计为低延迟和高吞吐量通信。gRPC非常适用于效率至关重要的轻型微服务。
- 点对点实时通信 - gRPC对双向流媒体提供出色的支持。gRPC服务可以实时推送消息而无需轮询。
- 多语言混合开发环境 - gRPC工具支持所有流行的开发语言,使gRPC成为多语言开发环境的理想选择。
- 网络受限环境 - 使用Protobuf(一种轻量级消息格式)序列化gRPC消息。gRPC消息始终小于等效的JSON消息。
不建议使用场景
在以下场景中,建议使用其他框架而不是gRPC:
- 浏览器可访问的API - 浏览器不完全支持gRPC。gRPC-Web可以提供浏览器支持,但它有局限性并引入了服务器代理。
- 广播实时通信 - gRPC支持通过流媒体进行实时通信,但不存在向已注册连接广播消息的概念。例如,在应该将新聊天消息发送到聊天室中的所有客户端的聊天室场景中,需要每个gRPC呼叫以单独地将新的聊天消息流传输到客户端。对于这种场景,SignalR是这种情况的有用框架。SignalR具有持久连接的概念和对广播消息的内置支持。
- 进程间通信 - 进程必须承载HTTP/2服务才能接受传入的gRPC调用。对于Windows,进程间通信管道是一种快速,轻量级的通信方法。
Protocol Buffers
一种轻便、高效的结构化数据存储方式,与语言、平台无关
- gRPC框架默认使用的数据交换格式
- 文件名以
.proto结尾 - 字段类型包含常见的数字、字符串、布尔、枚举、数组
- 每个字段需要一个数字标识符,定义好后不能改变。最小的标识号可以从1开始,最大到2^29 - 1, or 536,870,911。不可以使用其中的[19000-19999]的标识号, Protobuf协议实现中对这些进行了预留。如果非要在.proto文件中使用这些预留标识号,编译时就会报警
示例:
person.proto
1 | message Person { |
gRPC的四种通信模式
- unary call 一元通信
- Server-side streaming RPC 服务端流式通信
- Client-side streaming RPC 客户端流式通信
- Bidirectional streaming RPC 双向流式通信
maven依赖
1 | <dependencies> |
定义gRPC服务
定义proto文件
1 | syntax = "proto3"; |
生成代码
compile: 生成proto文件compile-custom: 生成gRPC文件
gRPC
服务端
自己写一个类,继承
GreeterGrpc.GreeterImplBase1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public class GreeterService extends GreeterGrpc.GreeterImplBase {
public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
System.out.println(request.getName());
// 构造返回对象
HelloReply helloReply = HelloReply.newBuilder()
.setMessage("okok")
.build();
responseObserver.onNext(helloReply);
// 结束调用
responseObserver.onCompleted();
}
public void sayHelloAgain(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
System.out.println(request.getName());
for (int i = 0; i < 10; i++) {
HelloReply helloReply = HelloReply.newBuilder()
.setMessage("okok" + i)
.build();
// 多次调用onNext()
responseObserver.onNext(helloReply);
}
// 结束调用
responseObserver.onCompleted();
}
}启动服务
1
2
3
4
5
6
7
8
9public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(8527)
.addService(new GreeterService())
.build()
.start();
System.out.println("server started");
System.out.println("==============");
server.awaitTermination();
}
客户端
使用stub调用进行远程调用
1 | public class GreeterClient { |