使用Nginx+Lua对某新闻站进行架构优化
缘由:
某IIS新闻站点(地区门户),原先部署了nginx做反向代理;squid缓存;以及1IIS源+2台文件存储服务器
预期要改造为cms站点,仅有静态文件;cms后台由其它server运行
方案一
使用2台文件存储服务器安装nginx,通过rsync做文件同步
上线后发现以下几个问题:
1.首页加载需要8秒以上
2.双机文件同步耗时过长,每次同步都在5min以上
3.磁盘IO过高
经过详细检查,存在以下问题:
1.新闻编辑人员经常在页面中插入多张上百K图片,导致页面过大,特别是首页经常达到2~3M
2.旧文件数据过多过大,350G文件总量,但文件数上千万
好吧,其实海量小文件的解决方案才是需要说明的重点,于是就有了……
sa:上缓存吧,速度快,效果好
dev:不行,上缓存我还要写程序purge,代码改动很麻烦
sa:…
sa:那旧文件删除,0x年的新闻页面现在还有谁看
dev:不行,业务领导那边不同意
sa:怎么什么都不行,那你想个法
dev:我们做冷热数据分离吧
sa:说的容易,怎么实施,首先怎么判断数据冷热?
dev:新的就是热的,旧的就是冷的
sa:废话- -,怎么判断...
dev:像http://news.qq.com/a/20140514/007123.htm,url中会带有时间戳
sa:那你这个时间肯定是动态的,如果说最近3个月为热数据,1月份的热数据就是去年11月至今;5月份的热数据就是3月份至今
dev:对呀,而且时间戳还有好多种,有yyyymmdd/hh/的,也有yyyy/mm/dd,也有yymm/dd的
sa:卧槽,格式又多,判断条件也要随时间变化,哪个设备哪个服务都做不到啊
sa:==我想到一个好像可以,nginx+lua
方案二
其实从往常的应用经验看,【nginx+不多的静态文件】即使是稍微老一点的服务器,服务性能也是非常好的;而本新闻站的最大拖累就在LOSF(海量小文件)
这些几百G,上千万的小文件,其实多数是2006年-2012年的历史文件,作为一个新闻站点来讲,这种历史文件的访问量是非常小,几乎为0的
所以我们决定,上线2台新设备,承担新文件的访问;而目前的设备,作为文件存储及承担旧文件访问的用途
为什么选择lua?
lua是目前所遇到过的速度最快的嵌入式脚本语言;一个完整的lua解释器不过200K;
在下的脚本肯定会有多if等判断,引入lua在web server上做7层代理,不至于对server造成过大负载
如果将lua应用到我们现在的架构中?当然是先学习,后部署
首先,学习lua
lua官方手册是最好的学习地址:http://www.codingnow.com/2000/download/lua_manual.html
其次,了解nginx的lua module
最后,可以参考其它同学的应用经验
那么就开始lua安装
1: tar zxvf LuaJIT-2.0.0.tar.gz
2: cd LuaJIT-2.0.0
3: make && make install
nginx安装,加入lua module即可
1: ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-ld-opt="-Wl,-rpath,$LUAJIT_LIB" --add-module=ngx_module/echo-nginx-module-master --add-module=ngx_module/lua-nginx-module-0.7.14rc2/
2: make && make install
编辑nginx.conf,主要的地方就在于
1.引入lua脚本
2.制定访问的location
server {
...
# 引入lua file
location / {
content_by_lua_file 'conf/proxy_pass.lua';
}
# 建两个location,@local为访问本地,@proxy_pass为访问后端
location @local {
#echo "@local";
root /www/webadmin;
index index.shtml index.html;
}
location @proxy_pass {
#echo "@proxy_pass";
proxy_pass http://backend;
include /usr/local/nginx/conf/proxy.conf;
}
...
}
编辑proxy_pass.lua文件,架构上线时间为2013年5月,lua脚本最后一次更新为2013年8月
只po干货,判断部分就不说了,每个人业务情况不一样~
-- Version 0.9999 -- 2013/08/01 potaski@qq.com
ngx.req.read_body()
-- 获取url
url = string.gsub(ngx.unescape_uri(ngx.var.request_uri),'\\%','')
-- 上面获取url的方式,如果url为"news.qq.com/"这样的话,取得的值为nil,我被坑了一回~
...
-- 当判断结束后,可以通过ngx.exec('@location_name'),进行跳转处理
if url_date == jgp_time_1 or url_date == jpg_time_2 then
ngx.exec('@local')
else
ngx.exec('@proxy_pass')
end
目前此架构已稳定运行一年,现在运行nginx+lua的设备,为2008年的单颗E2180,内存4G服务器,单台高峰时连接1K+,CPU损耗峰值在50%
nginx+lua设备只存放最近3个月的文件数据,并定期删除;其余数据全部由后端存储;磁盘压力大大减小
效果不错,所有人都很满意