目录
- 1. 引言
- 2. 定义gRPC服务
- 3. 抓包Unary方法
- 3.1 gRPC请求解析
- 3.2 gRPC响应解析
- 4. 抓包Bidirectional Stream方法
1. 引言
平时我们在浏览器中(如Chrome)可以通过开发者工具中的Network非常方便的查看HTTP/1.1和HTTP/2协议,
比如可以查询HTTP请求的protocol、host、method、path、headers、payload及response信息等相关数据,非常直观。
gRPC协议也是构建在HTTP/2上,并使用protobuf序列化通信数据,
我们可以通过Wireshark工具对gRPC通信进行抓包, 以查看其是如何运转在HTTP/2协议之上的,并且和我们平时的HTTP协议有何区别。
注: 使用WireShark抓取gRPC协议需要一些特殊设置, 具体设置可参见我之前的文章:《wireshark支持gRPC协议》
2. 定义gRPC服务
测试抓包使用的gRPC服务定义可参见我之前的一篇文章《gRPC Java入门示例》的Hello服务定义。
/*
* HelloWorld入门示例
*/
//使用proto3语法
syntax = "proto3";
//proto包名
package hello;
//生成多个Java文件
option java_multiple_files = true;
//指定Java包名
option java_package = "com.luo.demo.grpc.hello";
//指定Java输出类名
option java_outer_classname = "HelloProto";
//gRPC服务定义
service Hello {
//gRPC服务方法定义 - Unary
rpc sayHello (HelloRequest) returns (HelloReply) {}
//gRPC服务方法定义 - Server Streaming - 服务端流
rpc sayHelloServerStream (HelloRequest) returns (stream HelloReply) {}
//gRPC服务方法定义 - Client Streaming - 客户端流
rpc sayHelloClientStream (stream HelloRequest) returns (HelloReply) {}
//gRPC服务方法定义 - BiDirection Streaming - 双向流
rpc sayHelloBiStream (stream HelloRequest) returns (stream HelloReply) {}
}
//请求参数定义
message HelloRequest {
string name = 1;
}
//响应结果定义
message HelloReply {
string message = 1;
}
如上proto定义了Hello服务的4个方法,分别对应不同的类型:
包名package | 服务名 | 方法名 | 方法类型 |
hello | Hello | sayHello | Unary |
hello | Hello | sayHelloServerStream | Server Streaming |
hello | Hello | sayHelloClientStream | Client Streaming |
hello | Hello | sayHelloBiStream | BiDirection Streaming |
入门抓包使用Unary方法sayHello,
进阶使用Bidirectional Stream方法sayHelloBiStream。
注:
由于Bidirecitional Stream是Client Stream和Server Stream的超集,
故不在对sayHelloClientStream和sayHelloServerStream进行抓包演示,
具体细节可参见sayHelloBiStream。
3. 抓包Unary方法
启动gRPC Server端和Client端,发起一次sayHello请求,使用Wireshark抓包后一个完整的请求如下图:
这里直接讲解此次gRPC通信的几个重点步骤:
-
#6444
gRPC请求 -
#6458
gRPC响应头 -
#6467
gRPC响应数据
3.1 gRPC请求解析
查看#6444
gRPC请求对应的协议解析详情,如下图:
如上图可以发现HTTP2请求对应到gRPC请求,关系如下:
HTTP2协议 | GRPC协议 |
:authority | Server端地址 |
:method | POST |
:path |
即
|
content-type | application/grpc |
grpc-accept-encoding | gzip |
DATA(payload OR 请求数据) | Protobuf message定义的参数, 即 |
3.2 gRPC响应解析
查看#6458
gRPC响应头对应的协议解析详情,如下图:
查看#6467
gRPC响应数据对应的协议解析详情,如下图:
如上图可以发现HTTP2响应对应到gRPC响应,关系如下:
HTTP2协议 | GRPC协议 |
:status HTTP响应码 | grpc-status grpc响应码 |
content-type | application/grpc |
grpc-accept-encoding | gzip |
grpc-encoding | identity |
DATA(响应数据 ) | Protobuf message定义的返回结果), 即 |
4. 抓包Bidirectional Stream方法
发起一次sayHelloBIStream调用,示例代码中Client端发送了3次请求,相应的Server端也回应了3次,
注:
实际测试时发现,若Client端连续发送多次请求且间隔较短,Client端会合并多次请求为1次,但Server端还是分多次返回。
故在此次测试中将Client端2次发送间添加了2~3秒间隔,以便更直观展示抓取效果。
使用Wireshark抓包后效果如下图:
可以发现一共发送了3次gRPC双向通信且使用同一个连接(同一个tcp.stream=23),
每一次的gRPC请求及返回与之前的Unary调用类似,故不在展开,
需要注意的是仅第一次gRPC通信发送了请求HEADERS和响应HEADERS
,后续的请求都不在发送相关HEADERS。
参考:
https://imququ.com/post/header-compression-in-http2.html
https://grpc.github.io/grpc/core/md_doc_statuscodes.html
https://pingcap.com/zh/blog/grpc