基于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进程等代码,只利用该系统传递消息。
  • 高可靠
    • 在创建任务后,客户端得到查询结果所用的key,这个过程资源消耗极少,立即返回,不会失败。
    • 而在查询任务的时候,是基于LongPull的长连接,如果客户端请求断开,由于已经得到了key,只需要再由客户端,发起一起基于该key的查询请求即可。不会丢失数据,也不会改变查询的key,也不需要重新建立任务。
  • 实时性
    • 由于返回结果是基于LongPull的请求,当消息队列收到结果时,会立即推送给web服务器,web服务器则把结果返回给客户端,没有发生阻塞的可能。
  • 高性能
    • 客户端无需轮询,无需等待,不消耗资源。