首页 > 代码库 > "个性化空间"性能优化方案设计初步
"个性化空间"性能优化方案设计初步
一、问题的提出
在九月中开始,我们要打造个性化空间,领导要求的是只进行原型的设计,逻辑的设计,不进行技术开发。其实是严重不正确的,因为个性化空间其特点与现有的技术模型完全不同,现有的技术方案未必能适应开发工作,会造成看起来工作正常,但一旦大规模压力测试将性能一塌糊涂.....
所以,我们当然要听从领导安排,但私下准备好个性化空间的技术方案也是势在必行。
二、初步技术方案
根据以往的性能优化方案,我们一般采用REDIS进行一级缓存,特殊场景应对大并发,采用二级缓存办法。如果按以前的方式,那么方案是这样的:
1、在REDIS中记录此空间ID,比如ID:5,有几个模块,都是什么模块ID,比如:模块3,模块9,模块10,模块20,等。
2、每个模块的内容都单独保存到REDIS中。
3、每个模块单独记录最后的UPDATE时间,比如如果某个模块的内容删除了,更新了等,都需要在缓存中更新一下此模块的最后UPDATE时间为当前时间戳。
4、当用户初次来访问时,由LUA查询到此个性化空间有哪些模块, 然后根据每个模块的REDIS缓存,组装成一个JSON串,同时在REDIS中记录一个HASH,
包含如下信息:哪个空间ID(在KEY里体现),都有哪些模块,这些模块都是最后的更新时间是啥?
5、JSON数据经NGINX的GZIP压缩后返回。
6、当用户再次访问时,LUA查询此个性化空间有哪些模块,是不是在模块个数(或个数相同,同容变成其它模块了),模块的最后更新时间有区别,如果没有,则不重复组装,直接拿现成的JSON数据返回即可。
7、当某个模块的数据变化时,要求JAVA修改模块的最后修改时间,这样,LUA再次查询时,将不再读取保存好的JSON数据,而是重新组装返回,并再次缓存JSON数据。
三、技术方案进化
上面的方案应对一般的需求是很好的,在资源库列表的压力测试中取得了很好的成绩,由1000并发上升到3000并发应该不是问题,但应对这个需求就怕是要有问题了:
个性化空间具有可扩展性,比如,现在只开发了十个模块,用户最多可以启用十个模块,每个模块的数据量在10K左右,那么最多是100K,数据量不大,后期随着项目的进展,很可能空间出现大规模模块增加,我们以短期内可以接受的50个为上限计算,那么就在500K左右。大家知道,NGINX我们是启用了GZIP压缩的,本来GZIP压缩的效率很高,对于简单的JSON数据我们可以放心的使用GZIP压缩提高传输效率,但对于一个500K的流量,每请求一次就要实时压缩一下,效率可想而知。而此请求是一个动态请求,还不能使用效率更好的STATIC_GZIP方式,那么如果在这样的场景下,CPU的疲劳是可想而知的。因为小的JSON它压缩起来不费力,但大的呢?它也是十分吃力的,这一点我们以前在看JQUERY.MIN.JS每次让它压缩就看的出来,JQUERY.MIN.JS才只有120K左右,它就疲于奔命了,所以,这个方案存在先天的问题。
为此,黄海提出了一个新的设计思路:JSON数据的压缩不由GZIP实时进行,而是一次性在服务器端生成,然后直接发给JAVASCRIPT,由JS去解压解码后再运行。
(当然,为什么这种数据能不经过NGINX压缩呢?可能需要一些测试,比如:
gzip_types text/plain application/x-javascript text/css text/html application/xml; 将这种传输修改为一种不常用的mime,应该可以让NGINX不进行压缩,直接传输)。
核心思路:
1、由JAVA进行第一次的组装,一旦组装完成,将JSON数据先BASE64后,然后经JAVA进行Deflater压缩,得到的数据保存到REDIS中,LUA发现数据无变化 ,直接读取缓存数据并返回。
2、JAVASCRIPT得到数据后,先进行字符串解压,然后将BASE64字符串还原为普通字符串,进行渲染即可。
3、其它策略与上面的方式基本一致。
4、此优化的方案最核心的是JAVA生成Deflater压缩,BASE64化,然后在JAVASCRIPT中找到办法可以解压,并反BASE64化。
附: JAVA与JAVASCRIPT通用的字符串压缩,BASE64加解方法
JS通用加密解密方法.rar
JAVA通用加密解密方法.rar
四、不尽人意的地方
第一次请求需要JAVA进行处理,LUA的ZLIB库黄海没有安装起来,是不是能与JAVA,JAVASRIPT的压缩,解压保持一致还不知道,需要进一步测试。
LUA在检查到没有生成过时,需要转发ACTION给JAVA,那么如何转发,这里存在一个测试的内容。现在黄海只知道可以使用ngx.redirect,那么其它参数如何传递?用cookie可以吧?
"个性化空间"性能优化方案设计初步