V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
nameldk
V2EX  ›  NGINX

关于 Nginx 配置的一些疑惑

  •  
  •   nameldk · 2015-03-04 09:53:44 +08:00 · 6169 次点击
    这是一个创建于 3552 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网站目录结构如下:
    /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
    搞了一天了,还是没整好,好郁闷。感觉到了瓶颈了。

    38 条回复    2015-03-23 15:29:07 +08:00
    invite
        1
    invite  
       2015-03-04 10:31:43 +08:00   ❤️ 1
    这种设计,完全就是渣。
    mahone3297
        2
    mahone3297  
       2015-03-04 10:58:47 +08:00
    单一入口不是很好?。。。性能能提高多少?你遇到性能问题了?
    wingoo
        3
    wingoo  
       2015-03-04 11:09:49 +08:00
    这叫臆想中的性能问题
    nameldk
        4
    nameldk  
    OP
       2015-03-04 11:29:17 +08:00
    这样做的目的是让首页不走PHP了,减少PHP请求,不啥不对呢?
    nameldk
        5
    nameldk  
    OP
       2015-03-04 11:34:02 +08:00
    @invite 求不渣设计。
    @mahone3297 单一入口是不错,现在就是单一入口。不过不是得经过PHP么,现在不想走了。只为遇到攻击,首页请求很频繁,所以才想让Nginx直接吐静态页了。
    invite
        6
    invite  
       2015-03-04 11:40:27 +08:00   ❤️ 1
    @nameldk 你的cookie谁来生成?生成cookie的时间,顺带location已经够了。

    而且遇到攻击,靠这点来减缓,基本跟没有一样。

    先判断cookie,set变量,在try_files里用变量。
    jarlyyn
        7
    jarlyyn  
       2015-03-04 11:50:02 +08:00   ❤️ 1
    @nameldk 个人觉得,减少php请求意义不大,因为一般瓶颈不在php上,网速/mysql的压力会更大。php的话开个apc预编译基本不会是瓶颈。
    更靠谱的是在php里耗时/mysql的地方做缓存。

    而且个人意见,觉得语言信息靠cookie有点不太符合我的审美。
    invite
        8
    invite  
       2015-03-04 12:28:09 +08:00
    @jarlyyn

    @nameldk 而且按这个配置,所有404页面都请求到了index.php,哪来什么攻击防范功能。
    sophymax
        9
    sophymax  
       2015-03-04 12:59:57 +08:00 via iPad
    这种场景你去搜下ngx_lua模块,需要重新编译nginx ,最近很多问题都是它解决的,好吧,我们只是不喜欢nginx配置的蛋疼语法而已,http://wiki.nginx.org/HttpLuaModule
    qq286735628
        10
    qq286735628  
       2015-03-04 14:13:55 +08:00
    index参数里面,你在index.php前面加一个index.html,这样就不默认先请求index.html,没有才会请求index.php
    ryd994
        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看看哪里消耗最多和最值得优化吧。
    ryd994
        12
    ryd994  
       2015-03-04 14:35:33 +08:00 via Android
    首页请求频繁,你应当考虑的是如何缓存和如何限制不正常请求频率。遇到攻击应该研究安全设置。判断语言这点消耗,说白了是O(1)的,能有多少?哪怕你不判断语言,把这部分完全去掉,人家加一台肉鸡也就补上了。

    @sophymax Nginx配置文件本来就是配置文件,而非脚本语言。是declarative而不是imperative。这一点搞错了当然会不顺手。
    nameldk
        13
    nameldk  
    OP
       2015-03-04 15:01:05 +08:00
    @jarlyyn mysql 的查询有缓存的,首页如果直接抛静态页面,就是不想再连mysql redis。
    语言信息不靠cookie就在url体现吧,差别不大吧,只是展现形式不同。
    luw2007
        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 写的.
    nameldk
        15
    nameldk  
    OP
       2015-03-04 15:37:45 +08:00
    @luw2007 做这个的根源还是为了防DDOS,网站被打的很厉害,扛不住了就切加速乐了。ip的话很多,肉鸡太多,有次貌似在在加速乐上还是一直打不开。网站已受到了攻击者的敲诈。
    xiaoyaoking
        16
    xiaoyaoking  
       2015-03-04 15:42:43 +08:00 via Android
    @nameldk ddos 打的不是ip么?
    luw2007
        17
    luw2007  
       2015-03-04 16:13:43 +08:00
    肉鸡多不是关键. 分析日志照样可以挡住他的ip.
    你先全站只放一个首页吧. 接下来的事情就是看idc了.
    最大的问题:
    @xiaoyaoking idc的网络带宽才是问题吧, ddos 占满带宽, idc会直接拔网线.
    jarlyyn
        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也是妥妥的。
    jarlyyn
        19
    jarlyyn  
       2015-03-04 16:17:50 +08:00
    @luw2007 我上次被人打是refnece为网站首页,行为为下载首页所有图片,一天9000多ip的攻击。
    http://v2ex.com/t/145842
    luw2007
        20
    luw2007  
       2015-03-04 16:20:08 +08:00
    nginx + 静态文件 抗攻击还是可以的.
    前提是vps配置的当. 不然一个1024 can not open files 就让你崩溃.

    @jarlyyn 能做的就是拼封ip的速度, 如果可以分钟级别封ip, 剩下的就是看idc了.
    至于正常业务, 攻击了之下肯定用不了, 赶紧切换个备用域名/服务器 临时用着.
    luw2007
        21
    luw2007  
       2015-03-04 16:26:30 +08:00
    nginx 模块limit_zone与limit_req_zone, 这个不知道效果如何, 楼主可以试试看(至少不用分析日志什么的)

    @jarlyyn 上面那个模块应该适合你们那种. 资源限制.
    jarlyyn
        22
    jarlyyn  
       2015-03-04 16:38:08 +08:00
    @luw2007
    基本上很难判断出来哪个是垃圾攻击ip,哪个不是。日志我也分析过,频率都很低。我都怀疑是不是做了个隐藏iframe嵌在了某个访问量很大的网站里。
    想想其实只有做js跳转+定期调整临时域名才相对靠谱点啊。
    luw2007
        23
    luw2007  
       2015-03-04 16:45:36 +08:00
    @jarlyyn js跳转不解决你的问题, 毕竟图片路径在那里, nginx rewrite 替换掉图片路径中的父目录,让 之前的外链都死掉.
    如果iframe , 看来源url就可以直到怎么过来的.
    GuangXiN
        24
    GuangXiN  
       2015-03-04 18:17:54 +08:00
    不过PHP解释器是能提升不少性能的,我压过nginx,一个Hello world页面,如果后缀是.html不过PHP解器,能得到8000+ rps,如果改后缀名为.php过PHP解释器,就马上降到4900+rps
    nameldk
        25
    nameldk  
    OP
       2015-03-04 23:18:29 +08:00
    @jarlyyn 之前也用过Yii,现在感觉有点重,启动个框架就加载好多文件。感觉文件缓存要比redis缓存强,之前项目里实践过。缓存 内存级xcache>文件>redis. redis的话还得来一次连接,当然也可以做长连接,但远没文件高效。
    @luw2007 没有做过日志的IP分析,不过运维同学说IP很多,满世界都有,有段时间攻击较猛烈加速乐都扛不住了,直接不扛了,把请求直接丢给我们了,于是我们就挂了。
    现在的做法还是拿程序生成静态页,到Nginx直接丢静态页面。
    nameldk
        26
    nameldk  
    OP
       2015-03-04 23:24:59 +08:00
    @jarlyyn 我们受的攻击都是直接上G的。。
    luw2007
        27
    luw2007  
       2015-03-04 23:40:09 +08:00
    @nameldk 求域名,帮看看。
    nameldk
        28
    nameldk  
    OP
       2015-03-05 09:32:08 +08:00
    luw2007
        29
    luw2007  
       2015-03-05 10:16:22 +08:00
    @nameldk 看上去目前访问还行. 静态资源都分到二级域名了.

    让运维同学看日志, 确认正常用户的访问阀值. 设置下 模块limit_zone与limit_req_zone,
    测试机器上用压力测试工具跑下压力看看.
    jarlyyn
        30
    jarlyyn  
       2015-03-05 11:24:12 +08:00
    @nameldk Yii本来就很重,我改的模块后就更重了,这个不提了……
    redis需要链接那就是php本身的锅了,要不换nodejs?
    感觉要优化自然是哪里不足优化哪里了。
    相对而言,php本身应该只影响到内存和cpu占用。且不说个人认为这不是最大的瓶颈。这往往也是最好解决的方案,大不了内网多几个服务器,做一个负载均衡就可以了。
    而之所以我觉得觉得cookie不美。
    除了cookie需要更多的解析/处理步骤,逻辑更复杂外。
    我最喜欢的多语言版本切换是通过域名来的。
    哪怕是在同一个服务器。
    这样在dns这一步就可以开始分流了。
    都仅仅是个人意见,肯定没有受到攻击的你了解清楚。

    而且说实话,打首页我觉得毫无价值,首页是最容易缓存的地方。
    真的要打,打搜索,登录,忘记密码之类,ip多的时候才真心蛋疼。
    desperatecat
        31
    desperatecat  
       2015-03-05 11:24:40 +08:00
    nameldk
        32
    nameldk  
    OP
       2015-03-05 23:34:55 +08:00
    @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
    ryd994
        33
    ryd994  
       2015-03-05 23:53:24 +08:00 via Android
    @nameldk 是因为$index_name没有开头的/吧,看errorlog
    没试过rewrite和try_files同时用,一般没必要
    单独给首页开个location会好点
    location = / 这样就会只精确匹配首页了
    ryd994
        34
    ryd994  
       2015-03-05 23:57:19 +08:00 via Android
    @nameldk 还有,最重要的:缓存做了没有?频率限制作了没有?这两条没做,怎么优化都不会有用。
    nameldk
        35
    nameldk  
    OP
       2015-03-06 19:09:07 +08:00
    @ryd994 确实是开头没写/,看errlog发现了。

    同时发现了个Nginx比较好的教程: http://blog.sina.com.cn/s/articlelist_1834459124_0_1.html
    ryd994
        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里用到的模块的所有指令好了。
    nameldk
        37
    nameldk  
    OP
       2015-03-07 11:15:29 +08:00
    @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 挺坑。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2739 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:16 · PVG 20:16 · LAX 04:16 · JFK 07:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.