Tengine
Tengine 作为代理服务器,在集团有着广泛的应用基础,从 部署在 应用单机上的 Tengine ,到作为集群式部署的统一接入 Aserver ,可以说集团几乎所有应用机器均运行着 Tengine 。当然, Tengine 的不同部署形态,其作用也不经相同,这都得益于Tengine 作为优秀的反向代理服务器,有着 高性能、低延迟、高可用 等特性。
下图是常见的统一接入模型:
当前HTTP长连接业务现状
无论客户端发起的请求是 HTTP2 还是 HTTP 1.1,Tengine 作为反向代理服务器,和应用服务器之间均是短连接(除非 Tengine 配置 keepalive ),如下图所示:
Tengine 负责和客户端进行长连接的保活、和应用服务器使用具体负载均衡算法进行短连接调度。
当前HTTP的推送解决方案
通常推送的诉求,是需要定时的往端上发送数据,
轮询
端上 定时发送请求来轮询获取业务数据。
这是最简单且最容易想到的手段,但往往也是在实际项目中最不可能使用的方案。因为其缺点非常明显:
1、较短间隔的轮询请求会导致 Server 端无端的处理无用的 QPS ,且 QPS 与端的数量成线性正比
2、较长间隔的轮询请求,其推送时效性无法保证
应用服务处理
即,Tengine 作为反向代理服务器只完成基本的转发能力,业务 Hold 住 HTTP 的请求,并且在必要时,对其进行 response 。
缺点很明显,应用需要自己维护该长连接的生命周期,而往往推送场景的使用者均是超大规模的终端设备,超大规模的长连接很明显会消耗大量应用机器资源。
HTTP2 推送(Server Push)
实际上 HTTP2 的推送功能指的是单个 request 有多个 response ,与我们长连接通道持续传输数据的需求不匹配。
这里贴上 RFC 对 Server Push 功能的介绍,在这里就不再展开了。
- HTTP/2 allows a server to pre-emptively send (or "push") responses
- (along with corresponding "promised" requests) to a client in
- association with a previous client-initiated request. This can be
- useful when the server knows the client will need to have those
- responses available in order to fully process the response to the
- original request.
Tengine 单机推送
目前,主流开源 Nginx 模块有支持单机推送功能 。
推送流程
实际上和 MQTT 的 SUB PUB 模式非常相似,只是用 HTTP 来实现而已,下面是具体流程如下:
1、A 发起请求,Tengine 劫持请求 Hold 住, Tengine 对其生产一个对应的 KeyA 。
2、B 若期望推送数据到 A ,可用 KeyA 作为参数(或者 Header ),发送 POST 数据到指定Tengine。
3、 Tengine 将收到的 B 的 POST 的数据,获取到 KeyA 对应的连接,即可返回给 A 。
缺点
1、 B 需要感知 A 的存在 B
即当A的请求到达 Tengine 时, Tengine 需要旁路发送到 B ,即需要 告知 B ,A 的存在,并且 B 需要记录 A 对应的 KeyA 。
解决方案:可以使用 Tengine 的 auth_request 功能,当然等价的也可以使用 Lua 的ngx.location.capture 方法。
2、Tengine 若是集群化部署,B 需要中心化存储
B 通常是非单体应用,即由多个微服务组成,无论在哪个环节,当 B 需要推送消息到A时,显然需要知道 A 在 Tengine 集群中的哪台机器,故B应用中,至少某个微服务需要由中心化存储(例如 redis、memcache )来决定将请求发送至哪台 Tengine 。
Tengine实现方案
一、Tengine 自带 中心 化存储
Tengine 对 每个 TCP 连接生成一个 key(也可以使用请求 Header 等作为 Key ),在中心化存储中保存 key 和对应机器ip的映射信息。应用只需要往Tengine集群的任意一台机器推送数据,由 Tengine 来做分布式路由。下图从推送角度描述了 Tengine 如何工作。
1、应用往 Tengine 集群随机一台机器推送,推送是携带对应的的 Key 以表示自己期望推送至哪个连接
2、Sc 收到 推送消息,在 Tair 中查找对应请求由哪台 Tengine 机器维护,例如查找到该推送目的连接在 Sb 。
3、Sc 转发到 Sb。
4、Sb 收到后,找到对应的客户端连接,将数据推送至客户端。
应用可以是用 vipserver 随机查找 Tengine 机器, Tengine 也可以申请一个 vip/slb ,供业务访问,依靠 vip/slb 的负载均衡能力,随机访问 Tengine 。
二、支持流式传输
通常,一个长连接希望能够接受多个推送消息,而不是一个推送消息结束后再次新建, Tengine 依托其丰富的 HTTP 处理能力,使用 multipart/form-data ,是的推送数据拥有明确的 boundary ,多次推送数据都能有明确的分界线,客户端只需单个连接,就能获得多次推送数据。
三、多协议支持
Tengine 本身支持多种协议, 无论客户端发起的是 HTTP 还是HTTP2,均能继承上述推送功能。
四、高性能
Tengine 本身作为代理服务器,转发性能是业界的标杆,我们在Tengine转发流程加入了 中心化存储能力使得 Tengine 有了分布式路由的功能。