”抓包gRPC调用并分析具体抓包数据加深对gRPC的理解“
写在前面
最近团队里预计开发一套基于gRPC的网关,而恰逢国庆假期,可以抽出时间来整理一下早期对gRPC的一些研究。如果只是在应用层使用gRPC,我相信学习gRPC官网里的示例便足够了。但是如果打算在团队中大量地使用gRPC,会面对很多的挑战,比如服务之间的鉴权方案、多地域服务的路由方案、与已有RESTful服务的兼容方案等。
我最近感悟到,对一个技术栈的应用,需要掌握此技术栈的大量信息,如此才能保证此技术栈在生产使用时的稳定性。本文从最基本的抓包切入,简单介绍一次gRPC调用的数据流动情况。
工具及源码
- Wireshark 一款抓包工具
- grpc-go/examples/helloworld gRPC官方golang版本的helloword,本文基于此进行gRPC调用
抓包细节
首先应该明白,gRPC是HTTP/2和protobuf的结合体,认识到这两点,在抓包时便方便很多。比如,在使用Wireshark抓包时把未识别的HTTP/2协议手动设置为HTTP/2(否则会仅以TCP方式解析二进制);在查看HTTP/2时不要找JSON的那种数据展示(protobuf有自己的压缩算法)。
一次gRPC调用总览
【图-gRPC调用总览】
从上图可以大体看出,在gRPC的helloworld中从client端调用server端,会有多次的HTTP2请求,大体上可以分为:Magic->Settings->Headers->Data->Settings->Window-update,Ping->Ping->Headers,Data,Headers->Window_update,ping->Ping
。
Settings
从gRPC调用总览图可以看到,总共有两次的Settings设置,不过两次setting有相同的数据,具体数据如下:
Headers
gRPC发送请求的Header的截图如下,可以发现其中一些细节:
- HTTP/2的Header数据是被压缩了的;
- Header中包含了method(POST)、scheme(http)、path(/helloword.Greeter/SayHello)、content-type(application/grpc)等,很全。
Data
Headers部分主要由client向server发送请求相关的数据,在Data部分由server向client发送数据。
再一次的Settings
再一次的settings与第一次基本上没有区别,除了ACK的标识位为True。
Window_update, Ping
从下面可以看到,在HTTP/2的一次请求中,可以包含两个stream块。
ping(pong)
当client向server端发送了一个ping请求,server端会发回pong响应。上面的ping为client发起的,下面的ping为server端发起的。
headers,data,headers
这里的数据为server向client端发送的数据(包含了header及body),具体截图如下图所示。
window_update,ping
可以发现,不仅仅client可以向server发起ping,也可以反向由server向client进行ping的操作。
再一次ping(pong)
当然,在server发起ping操作后,client会发起pong操作。
gRPC中的context数据
有一天,小黄老师跑过来问:如果在gRPC从client调用server端服务时,在context中添加了一些数据,那么这些数据是如何传输到server端的?其实这些context中的数据会以header头的形式进行传输,比如上面图中所展示的代码,在context中塞了abc=>ccc
的键值对。
通过抓包可以看到,abc=>ccc
的键值对写入了header中,如下图:
小结
本文通过对gRPC的helloworld进行抓包,跟踪了一次gRPC调用过程可能包含的数据流过程。在学习了gRPC的理论性知识后,再结合本文的抓包内容,应该能对gRPC(侧重HTTP/2技术)有一个更好的理解。
参考
- grpc / grpc.io gRPC的官网,里面有各个语言的应用示例
- HTTP/2 HTTP/2的官方文档
- Protocol Buffers protobuf的官方文档,需要科学上网才能够访问