envoy 代理http1.1
最近处理了一个envoy代理http1.1的问题,先简单介绍一下背景
背景
我们有一个长连接通道的项目,原来是通过http2.0连接。后来因为要做扫码登录的业务,所以使用 socket.io 支持了http1.1的连接,这是同事当时支持http1.1以后的博客。 代理当初用的envoy是1.6 v1 API ,现在由于其他问题想升级envoy到新版本,而新版本已经不支持v1 API,在升级的过程中遇到一些问题,也花了不少时间,搞定以后以此文作为笔记。
服务部署结构
- front-envoy
这是一个网关。需要处理客户端http1.1的请求,在envoy API v1的时候非常简单,只需要在Route中加上use_websocket=true
即可,参考文档。
但是在API v2,这个配置修改了,参考文档,在http_connection_mananger
中加upgrade_configs
配置。
- envoy1
这实际上是k8s ingress,本来其实这个envoy就可以直接对外了,由于在阿里云slb的连接数有限制,所以才有在前面加了frontenvoy,有了frontenvoy连接会收敛,虽然front-envoy有一百多万连接,但到这里的连接数就很少了。
- envoy2
看得出来这是sidecar envoy。只需要加上sio的upstream cluster即可。
问题
背景已经交代清楚了,这里再说下问题。
-
envoy升级以后,按照配置设置了
upgrade_configs
,请求发现front-envoy一直报错,503 UR,即upstream reset。 再跟踪envoy1的trace日志,发现有一行日志invalid frame: Invalid HTTP header field was received
。 -
查了好久都没找到答案,上github提了一个issue,后来回复,由于envoy之间是http2连接,需要设置
allow_connect=true
才行,参考文档描述。 由于之前文档没有描述allow_connect
,现在看到的是我提了issue才加上的描述。所以自己查了很久也没搞定。 -
设置上
allow_connect
以后,frontenvoy的日志从503 UR变成503了。 查看envoy1的日志,503 UR 以及invalid frame: Invalid HTTP header field was received
。和刚才envoy1一样的。
而envoy2已经设置了allow_connect
啊。后来查明原来我是在cluster
里面的http2_protocol_options
中设置了allow_connect=true
,需要在http_connection_mananger
中的http2_protocol_options
中设置。
- 设置完成,envoy2又出现以下日志
|
|
再检查一遍配置,发现我在upstream cluster中加了http2_protocol_options{}
这就指定协议为http2,v1配置可以用"features":"http2",
配置为http2,默认http。而在v2配置中,需要通过http2_protocol_options{}
指定协议为http2,http_protocol_options{}
或不填表示http。
再总结一下几个envoy需要修改的地方
- frontenvoy
http_connection_mananger
中指定
|
|
- envoy1、envoy2
http_connection_mananger
中指定
|
|
且upstream cluster配置中不能将协议指定为http2。