Author:放翁(文初)
Email:fangweng@taobao.com
Blog:http://blog.csdn.net/cenwenchu79
当前问题:
1. 不小比重的Rest请求都是无效请求,全部接纳数据消耗比较多的时间。
2. Multipart类型的大文件流请求无法做到合理快速过滤。(参数错误请求,数据文件过多请求,文件大小过大请求)
归结来说,TOP平台处理的服务在解析参数时比较消耗时间和带宽(客户端网络速度慢导致传输字节流比较慢,文件比较大导致带宽占用严重)
处理方式:
通过自行解析字节流方式来lazy化处理请求,减少无效请求对于解析参数时间消耗(导致web容器连接消耗)及带宽消耗。
优化目标:
Get由于内容长度有限不列入在优化范围。
优化Post方式的请求(普通的和Multipart),要求优化后:在正常请求处理上两者处理速度不低于传统方式,非正常请求在策略命中情况下(后面会谈到什么情况下优化失效),性能有明显提高。
具体实现:
由于现在用的是传统IO模式,因此可以用流的方式来lazy解析和处理请求(NIO用channel + buffer package就无法lazy了)。
一共有三个组件角色:
1. 请求处理配置策略:配置在解析参数时,优先的规则(参数可以从header,uri,post body中获取,相互之间的优先性),异常抛出规则(字节流长度,文件大小,文件个数限制等),字节流解析模块的参数配置(字节流解析的窗口大小,超时时间等)。
2. 线程上下文:用来保存处理过的请求参数。一来复用,二来也是由于请求字节流处理不可逆(不保存字节流副本),必须保留。
3. Http请求字节流解析模块。根据具体的配置以及解析策略来解析字节流,同时将解析结果保存在线程上下文中。主要的实现代码在于对Post消息体逐步解析部分(普通的Post和multipart)
压力测试结果:
• 正常请求场景( 100并发用户,multipart 文件大小300k,当前业务场景这个值已经满足了):
普通post的处理能力1000TPS。(servlet方式处理差不多,不过有波动)
multipart处理能力610TPS。(apache开源项目fileupload,处理能力400TPS左右)
错误请求场景
异常情况的处理有了很大提高,对于远程客户端传输较慢或者是大流量图片的错误请求都有很大的优化。
优化存在问题:
1. 参数缺失导致优化失效。
2. sign类似的交验,导致获取所有的参数。
3. 当前图片限制在300k,由于考虑处理速度快,就都没有设置超过阀值存储到本地,因此在高并发大流量的情况下也会有内存问题,当然已经做了部分保护。
针对上面的两个问题,作了部分的协议限制,对于API2.0希望将所有的系统参数和业务参数区分开,放入到Http header中或者url中,这样可以避免系统参数缺失导致优化失败,同时大量过滤系统参数出现问题的无效请求。
Sign类似的交验放在流程最后,避免过早获取所有参数。
作安全保护,设定简单丢弃或者io交互来缓解这个问题。
这部分内容还有很多可以做得工作,其实最初的目的就是为了防止系统对于无效请求的处理消耗,我想在很多系统都会有这样的问题,利用缓存设置黑名单防止攻击也是这样的初衷。因此这点可以考虑在很多系统设计的时候都作一样的优化,对正常的不能优化,起码对错误的可以做一些优化,防止在异常请求高涨的时候,系统被击垮.