一、背景
开发Web平台时,经常会需要定时向服务器轮询获取数据状态,并且通常不仅只开一个轮询,而是根据业务需要会产生数个轮询。这种情况下,性能低下的Ajax长轮询已经不能满足需求,频繁的访问还会造成线程阻塞。最优的解决方案当然是用Websocket,采用服务器推送的方式来减少频繁开关连接造成的开销。但是Websocket对于我来说还只是个新事物,在未完成论证的情况下不能直接开发完就上,因此只好采用过渡方案,使用队列的方式,暂时优化多AJax长轮询的情况下造成的线程阻塞问题。
我所用的Web平台框架是国产开源的DWZ框架。该框架不使用经典的iframe模式,所有的视图、数据访问都是通过Ajax获取后在前台进行加载渲染,页面迁移跳转极少,因此本质上来说基于DWZ框架的网页都是Single Page页面。在这种情况下,除了长轮询外,还会根据用户的操作产生其它Ajax链接。这就要求在优化的同时,还要保证用户操作的优先度。毕竟长轮询只是后台默认执行的操作,对用户的体验影响不大;但用户的操作因为长轮询造成延迟的话,用户体验就十分糟糕。
此外,我还发现处理这些Ajax轮询所用的Controller是MVC默认的,然而这些Controller不支持异步处理请求操作,在多个请求访问时,新请求必须等待旧请求完成后才能继续下去。
综上所述,优化Ajax轮询造成的线程阻塞问题的过渡方案中,有以下两点要求:
1.使用Ajax队列的方式,不推倒现有的技术方案,在原有的基础上快速修改。
2.在Ajax队列优化过程中,必须保证用户操作的优先度,保证用户操作的及时响应。
3.替换原有只支持同步Action的Controller,使用可支持异常Action的Controller。
二、前台代码解析
总体思路是:
1.重写jquery既有的ajax方法,将所有调用该方法的ajax全部注册到自定义的ajax程序池中。
2.自定义ajax程序池分全局和非全局两类,长轮询发起的ajax为非全局,用户发起的ajax为全局。
3.排队执行两个程序池中的请求,一个请求完成后才继续执行下一个,而非异步将所有ajax同时发起请求。
4.全局ajax的优先度高,如果当前正在执行非全局ajax且有未发起的全局ajax,则停止正在执行的非全局ajax,优先发送全局ajax。
5.非全局ajax只有在全局ajax全部完毕的情况下才会发送请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
|