基于Long Pull的HTTP异步请求,处理高延时外部IO的设计方案。Long Pull With External IO Request and Callback
背景
- 接受请求的http服务器,需要处理一次高延时的外部IO
- 实时性,当外部IO处理完毕后,请求者需要第一时间获得请求结果
- 部署简单,不对现有系统进行大改造
- 可靠性高,http断开后也不影响后续的请求结果获取
- 高性能,客户端不需要轮询太频繁,这会让客户端消耗太多资源
现实场景
电视淘宝
项目,扫码绑定功能。
介绍
该功能流程如下:
- 用户打开账户管理页面
- 浏览器向后台同步申请一个二维码
- 浏览器通过img标签展示生成的二维码
- 浏览器同时轮询请求后台,询问该用户的绑定状态
- 后台服务器轮询淘宝,询问该用户的绑定状态
- 用户掏出手机淘宝主客
- 用户用主客扫描二维码,并且确认登陆
- 电视淘宝后台服务器在下一次轮询的时候,将得到用户扫描后的确认状态
- 浏览器当前打开的页面,在下一次轮询的时候,将得到用户扫描后的确认状态
需求
由于淘宝主客服务器,并没有实现绑定后回掉的功能。所以电视淘宝后台服务器,向淘宝主客服务器轮询不可避免。但希望能解决浏览器轮询后台绑定状态,避免轮询。因为浏览器所在的机顶盒性能严重不足,多次轮询会有很高几率导致死机,所以希望能通过长连接的方式解决。
现有框架
- web服务器:rainbows,支持Eventmachine,可实现异步IO
- 后台任务队列:resque,无缝集成到capistrano部署系统,完善的后台任务解决方案。
方案
- 基于Long Pull的Http请求
- Eventmachine的非阻塞IO
- RabbitMQ的消息队列
- resque的后台任务
架构图
优点
- 易部署
- 在现有系统上,只增加了一套AMQP系统,可通过
apt-get install rabbitmq
安装,属于系统软件,和代码无耦合,不依赖部署系统,也不需要为该系统写后台任务、daemon进程等代码,只利用该系统传递消息。
- 在现有系统上,只增加了一套AMQP系统,可通过
- 高可靠
- 在创建任务后,客户端得到查询结果所用的key,这个过程资源消耗极少,立即返回,不会失败。
- 而在查询任务的时候,是基于LongPull的长连接,如果客户端请求断开,由于已经得到了key,只需要再由客户端,发起一起基于该key的查询请求即可。不会丢失数据,也不会改变查询的key,也不需要重新建立任务。
- 实时性
- 由于返回结果是基于LongPull的请求,当消息队列收到结果时,会立即推送给web服务器,web服务器则把结果返回给客户端,没有发生阻塞的可能。
- 高性能
- 客户端无需轮询,无需等待,不消耗资源。