网站目录结构如下:
/public/en.html
/public/zh_cn.html
/public/index.php
之前所有的非静态资源请求都交给 index.php
现在要把首页的请求 不走PHP了,提高下网站性能。Nginx会根据cookie值 lang=en 直接返回en.html 根据 lang=zh_cn 直接返回 zh_cn.html。如果没有cookie的话,默认返回 zh_cn.html.
首页请求地址有3个,分别为:
/
/index
/index/index
求Nginx 配置。
现在的Ngxin配置如下:
location / {
index index.php;
if ($http_cookie ~* "lang=en"){
rewrite ^/$ /en.html;
rewrite /index /en.html;
rewrite /index/index /en.html;
}
if ($http_cookie ~* "lang=zh_cn"){
rewrite ^/$ /zh_cn.html;
rewrite /index /zh_cn.html;
rewrite /index/index /zh_cn.html;
}
root /www/wwwroot/public;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
但是不好使啊,网上说 location里,if 和 try_files同时使用会有问题,http://wiki.nginx.org/IfIsEvil
搞了一天了,还是没整好,好郁闷。感觉到了瓶颈了。
1
invite 2015-03-04 10:31:43 +08:00 1
这种设计,完全就是渣。
|
2
mahone3297 2015-03-04 10:58:47 +08:00
单一入口不是很好?。。。性能能提高多少?你遇到性能问题了?
|
3
wingoo 2015-03-04 11:09:49 +08:00
这叫臆想中的性能问题
|
4
nameldk OP 这样做的目的是让首页不走PHP了,减少PHP请求,不啥不对呢?
|
5
nameldk OP |
6
invite 2015-03-04 11:40:27 +08:00 1
@nameldk 你的cookie谁来生成?生成cookie的时间,顺带location已经够了。
而且遇到攻击,靠这点来减缓,基本跟没有一样。 先判断cookie,set变量,在try_files里用变量。 |
7
jarlyyn 2015-03-04 11:50:02 +08:00 1
@nameldk 个人觉得,减少php请求意义不大,因为一般瓶颈不在php上,网速/mysql的压力会更大。php的话开个apc预编译基本不会是瓶颈。
更靠谱的是在php里耗时/mysql的地方做缓存。 而且个人意见,觉得语言信息靠cookie有点不太符合我的审美。 |
9
sophymax 2015-03-04 12:59:57 +08:00 via iPad
这种场景你去搜下ngx_lua模块,需要重新编译nginx ,最近很多问题都是它解决的,好吧,我们只是不喜欢nginx配置的蛋疼语法而已,http://wiki.nginx.org/HttpLuaModule
|
10
qq286735628 2015-03-04 14:13:55 +08:00
index参数里面,你在index.php前面加一个index.html,这样就不默认先请求index.html,没有才会请求index.php
|
11
ryd994 2015-03-04 14:28:24 +08:00
If is evil,官方已经多次强调过了。能不用就不用。
另外我比较喜欢利用header判断,然后302。这样会更符合http规范,如果错了,用户依然可以手动改回去。网页里的链接全部指向相同语言的对应页面,也就是说不同语言不同入口,不知道这个对你来说会不会很难实现。 但是即使用cookie也是类似的。用cookie代替header,用try_files代替rewrite而已。Well, you know the pattern. map ${http_accept_language} ${index_name} { ~^zh.* zh_cn.html; ~^en.* en.html; default en.html; } location / { rewrite ^(.*)$ /${1}/${index_name}.html redirect; } 未测试,但是思路应该没大问题。 效果参考: http://www.crystalacg.com/help会根据使用的系统转向help-win或help-mac 其实我是因为本来网站全静态不想引入动态内容罢了。如果你已经是用PHP的话我建议你继续用,这点成本应该不是瓶颈。做个timing看看哪里消耗最多和最值得优化吧。 |
12
ryd994 2015-03-04 14:35:33 +08:00 via Android
首页请求频繁,你应当考虑的是如何缓存和如何限制不正常请求频率。遇到攻击应该研究安全设置。判断语言这点消耗,说白了是O(1)的,能有多少?哪怕你不判断语言,把这部分完全去掉,人家加一台肉鸡也就补上了。
@sophymax Nginx配置文件本来就是配置文件,而非脚本语言。是declarative而不是imperative。这一点搞错了当然会不顺手。 |
13
nameldk OP @jarlyyn mysql 的查询有缓存的,首页如果直接抛静态页面,就是不想再连mysql redis。
语言信息不靠cookie就在url体现吧,差别不大吧,只是展现形式不同。 |
14
luw2007 2015-03-04 15:16:45 +08:00
@nameldk @jarlyyn
首先做的是分析日志, 直接iptables 禁止攻击ip访问. 1. 分析nginx的日志, 看看那些ip 短时间大量访问, 通过简单的linux命令行工具, awk, sort, uniq 就可以统计ip了. 阻止掉前十个ip基本就能保住了 iptables -A INPUT -s XX.XX.XX.XX -j DROP 2. 如果不会看日志怎么办, 发给我吧,免费分析. 解决不掉攻击源的情况下 1. 配置一个中文页, 等攻击过去. 英文页面纯粹是一般只是为了提升公司的颜值. 2. 如果一个静态页面还抗不住, 怎么折腾都没辙, 技术上搞不定就给黑客掏钱吧. 3. 黑客不要钱, 就找运营商看看能不能收费帮你们抗住流量. 4. 运营商要价高, 那就就把域名指向baidu, 让他攻击吧. 服务器调整优化: 如果是自己的vps, 调优tcp 相关的系统参数 ulimit , backlog 之类的, 网上很多. 至于优化nginx 等攻击完了再说吧. 临时改配置没多大作用. 毕竟你总有页面访问慢. 找到了,继续攻击之. 优化可以看看 @ryd994 写的. |
15
nameldk OP @luw2007 做这个的根源还是为了防DDOS,网站被打的很厉害,扛不住了就切加速乐了。ip的话很多,肉鸡太多,有次貌似在在加速乐上还是一直打不开。网站已受到了攻击者的敲诈。
|
16
xiaoyaoking 2015-03-04 15:42:43 +08:00 via Android
@nameldk ddos 打的不是ip么?
|
17
luw2007 2015-03-04 16:13:43 +08:00
肉鸡多不是关键. 分析日志照样可以挡住他的ip.
你先全站只放一个首页吧. 接下来的事情就是看idc了. 最大的问题: @xiaoyaoking idc的网络带宽才是问题吧, ddos 占满带宽, idc会直接拔网线. |
18
jarlyyn 2015-03-04 16:14:44 +08:00
@nameldk 缓存又不是只有mysql,redis.
直接存成文件也可以啊,和nginx跑比可能也就是多跑了遍php而已。 说实话,真的是文件还未必比从redis里取快吧? 我也被攻击过。被攻击的时候最怕的就是带宽跑满。 http://v2ex.com/t/145842#reply80 你的index.php总不可能比yii+我写的一堆到处套的模块重吧? 有缓存的话mysql根本没压力的。 哪怕是文件缓存,就算阿里云的烂IO也是妥妥的。 |
19
jarlyyn 2015-03-04 16:17:50 +08:00
|
20
luw2007 2015-03-04 16:20:08 +08:00
nginx + 静态文件 抗攻击还是可以的.
前提是vps配置的当. 不然一个1024 can not open files 就让你崩溃. @jarlyyn 能做的就是拼封ip的速度, 如果可以分钟级别封ip, 剩下的就是看idc了. 至于正常业务, 攻击了之下肯定用不了, 赶紧切换个备用域名/服务器 临时用着. |
21
luw2007 2015-03-04 16:26:30 +08:00
|
22
jarlyyn 2015-03-04 16:38:08 +08:00
@luw2007
基本上很难判断出来哪个是垃圾攻击ip,哪个不是。日志我也分析过,频率都很低。我都怀疑是不是做了个隐藏iframe嵌在了某个访问量很大的网站里。 想想其实只有做js跳转+定期调整临时域名才相对靠谱点啊。 |
23
luw2007 2015-03-04 16:45:36 +08:00
@jarlyyn js跳转不解决你的问题, 毕竟图片路径在那里, nginx rewrite 替换掉图片路径中的父目录,让 之前的外链都死掉.
如果iframe , 看来源url就可以直到怎么过来的. |
24
GuangXiN 2015-03-04 18:17:54 +08:00
不过PHP解释器是能提升不少性能的,我压过nginx,一个Hello world页面,如果后缀是.html不过PHP解器,能得到8000+ rps,如果改后缀名为.php过PHP解释器,就马上降到4900+rps
|
25
nameldk OP |
28
nameldk OP |
29
luw2007 2015-03-05 10:16:22 +08:00
@nameldk 看上去目前访问还行. 静态资源都分到二级域名了.
让运维同学看日志, 确认正常用户的访问阀值. 设置下 模块limit_zone与limit_req_zone, 测试机器上用压力测试工具跑下压力看看. |
30
jarlyyn 2015-03-05 11:24:12 +08:00
@nameldk Yii本来就很重,我改的模块后就更重了,这个不提了……
redis需要链接那就是php本身的锅了,要不换nodejs? 感觉要优化自然是哪里不足优化哪里了。 相对而言,php本身应该只影响到内存和cpu占用。且不说个人认为这不是最大的瓶颈。这往往也是最好解决的方案,大不了内网多几个服务器,做一个负载均衡就可以了。 而之所以我觉得觉得cookie不美。 除了cookie需要更多的解析/处理步骤,逻辑更复杂外。 我最喜欢的多语言版本切换是通过域名来的。 哪怕是在同一个服务器。 这样在dns这一步就可以开始分流了。 都仅仅是个人意见,肯定没有受到攻击的你了解清楚。 而且说实话,打首页我觉得毫无价值,首页是最容易缓存的地方。 真的要打,打搜索,登录,忘记密码之类,ip多的时候才真心蛋疼。 |
31
desperatecat 2015-03-05 11:24:40 +08:00
|
32
nameldk OP @jarlyyn 不知道对方是怎么想的,一直打的首页,可能首页的链接地址不会变,可能是其他原因。因为首页打不开,其他的页面部分是可以访问的。多语言版本当初没想太多,只是觉得cookie简单,种个cookie方便记住用户的选择。域名的话感觉让不同的模块瞳子域名比较合适。
@luw2007 回头看下,个人对Nginx的各种模块不是太熟,这回可以好好看看。。 @desperatecat 这个是正则表达式不严谨的问题。。。 @ryd994 之前没用过map,这个指令不错,感觉可以代替if。但是为啥rewrite后 首页会404了 rewrite ^/$ $index_name; 还有rewrite和try_files同时用没问题吧? 我想 map 根据cookie确定首页lang,通过rewrite 首页 指向静态页。再通过 try_files 把其他请求丢给index.php |
33
ryd994 2015-03-05 23:53:24 +08:00 via Android
@nameldk 是因为$index_name没有开头的/吧,看errorlog
没试过rewrite和try_files同时用,一般没必要 单独给首页开个location会好点 location = / 这样就会只精确匹配首页了 |
35
nameldk OP @ryd994 确实是开头没写/,看errlog发现了。
同时发现了个Nginx比较好的教程: http://blog.sina.com.cn/s/articlelist_1834459124_0_1.html |
36
ryd994 2015-03-06 19:26:29 +08:00
@nameldk 这个我以前看过,作为入门是不错,对于语法和变量。
agentzh就是rewrite模块的主要作者,lua模块也有很多贡献,是大牛。 不过现在再看,其实感觉这两个模块于Nginx哲学其实不太合拍(纯静态,纯声明)。 作为Nginx功能的补充很好,对于cdn之类的应用非常有用,但过度依赖就会出问题。 指令执行顺序什么的不必太纠结,不要钻这个牛角尖。如果你发现你需要纠结指令执行顺序的话,说明这个工作实际并不适合nginx(尽管可以写出来,而且性能很不错,但是有其他更方便的解)。熟悉执行阶段的关系的话,可以快速排除一些不切实际的想法,而不是写了半天配置就是不行。 如果你英文过得去的话,我最建议的还是官方文档: http://nginx.org/en/docs/beginners_guide.html http://nginx.com/resources/admin-guide/ 看过之后就能写出不错的配置。要进一步调优就去啃reference里用到的模块的所有指令好了。 |
37
nameldk OP @ryd994 感谢!
最终搞好了: 1. nginx.conf 中的http 块添加: map $cookie_lang $page_lang { zh_cn zh_cn.html; zh_tw zh_tw.html; en en.html; default en.html; } 2. location / { index index.php; root /www/wwwroot/public; rewrite ^/index/index$ /${page_lang}; rewrite ^/index$ /${page_lang}; rewrite ^/$ /${page_lang}; try_files $uri $uri/ /index.php?q=$uri&$args; } 其实配置挺简单的 最关键的还是变量的处理,用map代替了if,之前一直不知道有map。 取cookie的值可以用 $cookie_变量名。 写rewrite时 正则要严谨。 尽量不用if 挺坑。 |
38
luw2007 2015-03-23 15:29:07 +08:00
|