Let's Go!

发布新日志

  • php-fpm – 配置详解(转)

    2011-12-14 17:55:39

    php-fpm – 配置详解(转)

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://duyongguang.blogbus.com/logs/156375484.html

    php5.3自带php-fpm

    /usr/local/php/etc/php-fpm.conf

    pid = run/php-fpm.pid
    pid设置,默认在安装目录中的var/run/php-fpm.pid,建议开启

    error_log = log/php-fpm.log
    错误日志,默认在安装目录中的var/log/php-fpm.log

    log_level = notice
    错误级别. 可用级别为: alert(必须立即处理), error(错误情况), warning(警告情况), notice(一般重要信息), debug(调试信息). 默认: notice.

    emergency_restart_threshold = 60
    emergency_restart_interval = 60s
    表示在emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启。这两个选项一般保持默认值。

    process_control_timeout = 0
    设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0.

    daemonize = yes
    后台执行fpm,默认值为yes,如果为了调试可以改为no。

    在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。

    listen = 127.0.0.1:9000
    fpm监听端口,即nginx中php处理的地址,一般默认值即可。
    可用格式为: ‘ip:port’, ‘port’, ‘/path/to/unix/socket’. 每个进程池都需要设置.

    listen.backlog = -1
    backlog数,-1表示无限制,由操作系统决定,此行注释掉就行。backlog含义参考:

    http://www.3gyou.cc/?p=41

    listen.allowed_clients = 127.0.0.1
    允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。
    每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接

    listen.owner = www
    listen.group = www
    listen.mode = 0666
    unix socket设置选项,如果使用tcp方式访问,这里注释即可。

    user = www
    group = www
    启动进程的帐户和组

    pm = dynamic
    如何控制子进程,选项有static和dynamic。
    如果选择static,则由pm.max_children指定固定的子进程数。
    如果选择dynamic,则由下开参数决定:
    pm.max_children ,子进程最大数
    pm.start_servers ,启动时的进程数
    pm.min_spare_servers ,保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
    pm.max_spare_servers ,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理
    对于专用服务器,pm可以设置为static。

    pm.max_requests = 1000
    设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0.

    pm.status_path = /status
    FPM状态页面的网址. 如果没有设置, 则无法访问状态页面. 默认值: none.

    ping.path = /ping
    FPM监控页面的ping网址. 如果没有设置, 则无法访问ping页面. 该页面用于外部检测FPM是否存活并且可以响应请求. 请注意必须以斜线开头 (/)。

    ping.response = pong
    用于定义ping请求的返回相应. 返回为 HTTP 200 的 text/plain 格式文本. 默认值: pong.

    request_terminate_timeout = 0
    设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的’max_execution_time’因为某些特殊原因没有中止运行的脚本有用. 设置为 ’0′ 表示 ‘Off’.
    当经常出现502错误时可以尝试更改此选项。

    request_slowlog_timeout = 10s
    当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 ’0′ 表示 ‘Off’

    slowlog = log/$pool.log.slow
    慢请求的记录日志,配合request_slowlog_timeout使用

    rlimit_files = 1024
    设置文件打开描述符的rlimit限制. 默认值: 系统定义值
    系统默认可打开句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。

    rlimit_core = 0
    设置核心rlimit最大限制值. 可用值: ‘unlimited’ 、0或者正整数. 默认值: 系统定义值.

    chroot =
    启动时的Chroot目录. 所定义的目录需要是绝对路径. 如果没有设置, 则chroot不被使用.

    chdir =
    设置启动目录,启动时会自动Chdir到该目录. 所定义的目录需要是绝对路径. 默认值: 当前目录,或者/目录(chroot时)

    catch_workers_output = yes
    重定向运行过程中的stdout和stderr到主要的错误日志文件中. 如果没有设置, stdout 和 stderr 将会根据FastCGI的规则被重定向到 /dev/null . 默认值: 空.


    转自:http://hi.baidu.com/bianxuehui/blog/item/411c3decada90ec8b21cb1c5.html
  • nginx+php 502 bad gateway解决方法

    2011-11-29 18:18:53

    Nginx的502错误

    重启服务器后发现Nginx在我的WordPress报502 Bad Gateway错误。
    查了好久,以为是nginx.conf或者php-fpm.conf的错,突然想起来,好像哪里看到说php.ini中memory_limit设低了会出错,
    修改了php.ini的memory_limit为64M,重启nginx,发现真好了~
    原来是PHP的内存不足了。
    360M内存的服务器,扛这点应用应该OK~

    ------------------------------------------------------------------------------------------

    nginx+php 502 bad gateway解决方法

    打开 /usr/local/php/etc/php-fpm.conf

          调大以下两个参数(根据服务器实际情况,过大也不行)

        <value name=”max_children”>5120</value>

          <value name=”max_requests”>600</value>

    修改后速度快了,好象mysql占用cpu也下降了

    -----------------------------------------------------------------------------------------

    nginx 502 bad故障原因及解决方法收集

    如题,最近网站频繁出现502错误,简直无法正常运转,出现这种情况大多是php-cgi超时没有返回信息,或进程僵死等情况造成的,参考张宴的这 篇关于502错误的解决办法(http://blog.s135.com/read.php?361),并咨询系统管理员高手,我们的nginx已经配置到极致这些都已经老早做过修改了,但现在又出然出现。

    经过分析将nginx的error log打开,发现”pstream sent too big header while reading response header from upstream”这样的错误提示,查阅了一下资料,大意是nginx缓 冲区有一个bug造成的,我们网站的页面消耗占用缓冲区可能过大。参考老外写的修改办法增加了缓冲区容量大小设置,502问题彻底解决,后来系统管理员又 对参数做了调整只保留了2个设置参数:client head buffer,fastcgi buffer size。

    参考:

    http://www.sudone.com/nginx/nginx_400_bad_request.html

    http://blog.rackcorp.com/?p=14

    二、昨天装上nginx后在高负载的时候,论坛上传图片或者执行较长时间脚本的时候就不停的出现502 Bad Gateway ,网上搜了,大多数都是张大师的那篇解决方案,他的解决方案是

    http
    {
    ……
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    ……
    }

    增加了fastcgi的相应请求时间。但是我在实际中碰到了这个问题,设置到500,还是会出现,只是比我设置120的时候要少一些。后来发现主要是在一些post或者数据库操作的时候出现这种情况,静态页面是不会出现的。

    反复的查问题,调试,也加大了CGI的进程数。

    128

    256再加上去可能会变得很慢。占用内存大了。

    在php-fpm.conf设置中还有一项,可能当时没注意到,无意中改了这个值。

    request_terminate_timeout

    这个值是max_execution_time,就是fast-cgi的执行脚本时间。

    0s

    0s为关闭,就是无限执行下去。(当时装的时候没仔细看就改了一个数字)

    发现,问题解决了,执行很长时间也不会出错了。

    优化fastcgi中,还可以改改这个值5s 。看看效果

    终于发现502的错误其实不是nginx的问题,哈哈

    php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误

    三、

    一台服务器上运行着nginx php(fpm) xcache,访问量日均 300W pv左右
    最近经常会出现这样的情况: php页面打开很慢,cpu使用率突然降至很低,系统负载突然升至很高,查看网卡的流量,也会发现突然降到了很低。这种情况只持续数秒钟就恢复了
    检查php-fpm的日志文件发现了一些线索
    Sep 30 08:32:23.289973 [NOTICE] fpm_unix_init_main(), line 271: getrlimit(nofile): max:51200, cur:51200
    Sep 30 08:32:23.290212 [NOTICE] fpm_sockets_init_main(), line 371: using inherited socket fd=10, “127.0.0.1:9000″
    Sep 30 08:32:23.290342 [NOTICE] fpm_event_init_main(), line 109: libevent: using epoll
    Sep 30 08:32:23.296426 [NOTICE] fpm_init(), line 47: fpm is running, pid 30587
    在这几句的前面,是1000多行的关闭children和开启children的日志
    原来,php-fpm有一个参数 max_requests ,该参数指明了,每个children最多处理多少个请求后便会被关闭,默认的设置是500。因为php是把请求轮询给每个children,在大流量 下,每个childre到达max_requests所用的时间都差不多,这样就造成所有的children基本上在同一时间被关闭。
    在这期间,nginx无法将php文件转交给php-fpm处理,所以cpu会降至很低(不用处理php,更不用执行sql),而负载会升至很高(关闭和开启children、nginx等待php-fpm),网卡流量也降至很低(nginx无法生成数据传输给客户端)

    解决问题很简单,增加children的数量,并且将 max_requests 设置未 0 或者一个比较大的值,重启php-fpm

    四、

    nginx 502错 误的原因比较多,是因为在代理模式下后端服务器出现问题引起的。这些错误一般都不是nginx本身的问题,一定要从后端找原因!但nginx把这些出错都 揽在自己身上了,着实让nginx的推广者备受置疑,毕竟从字眼上理解,bad gateway?不就是bad nginx吗?让不了解的人看到,会直接把责任推在nginx身上,希望nginx下一个版本会把出错提示写稍微友好一些,至少不会是现在简单的一句 502 Bad Gateway,另外还不忘附上自己的大名。

    502错误最通常的出现情况就是后端主机当机,当然还有。在upstream配置里有这么一项配置:proxy_next_upstream,这个 配置指定了nginx在从一个后端主机取数据遇到何种错误时会转到下一个后端主机,里头写上的就是会出现502的所有情况拉,默认是error timeout,error就是当机、断线之类的,timeout就是读取堵塞超时,比较容易理解。我一般是全写上的:

    proxy_next_upstream error timeout invalid_header http_500 http_503;

    不过现在可能我要去掉http_500这一项了,http_500指定后端返回500错误时会转一个主机,后端的jsp出错的话,本来会打印一堆 stacktrace的错误信息,现在被502取代了。但公司的程序员可不这么认为,他们认定是nginx出现了错误,我实在没空跟他们解释502的原理 了……

    invalid_header我也没认真查清到底指的什么,我也很想先把它弄下来。

    503错误就可以保留,因为后端通常是apache resin,如果apache死机就是error,但resin死机,仅仅是503,所以还是有必要保留的。

    对nginx fastcgi使用的情况,我现在用得不多,不熟就不乱说了。


    转自:http://apps.hi.baidu.com/share/detail/17351945

  • 解决Nginx + PHP(FastCGI)遇到的502 Bad Gateway错误(转载)

    2011-11-29 17:54:04

    [文章作者:张宴 本文版本:v1.0 最后修改:2008.07.30 转载请注明原文链接:http://blog.s135.com/read.php/361/]

      昨日,有朋友问我,他将Web服务器换成Nginx 0.6.31  + PHP 4.4.7(FastCGI)后,有时候访问会出现“502 Bad Gateway”错误,如何解决。

      我让按照以下两个步骤去解决,最后在第2步中将FastCGI的timeout时间增加为300,问题解决:

      PS:比较羡慕迅雷的Web服务器,16G内存。



      1、查看当前的PHP FastCGI进程数是否够用:
    netstat -anpo | grep "php-cgi" | wc -l

      如果实际使用的“FastCGI进程数”接近预设的“FastCGI进程数”,那么,说明“FastCGI进程数”不够用,需要增大。



      2、部分PHP程序的执行时间超过了Nginx的等待时间,可以适当增加nginx.conf配置文件中FastCGI的timeout时间,例如:
    ......
    http
    {
    ......
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    ......
    }
    ......





    acky
    2008-7-30 09:02
    不太理解:
    netstat -an | grep "php-cgi" | wc -l

    netstat -an 不是显示端口, grep php-cgi 能得到什么?
    # netstat -an | grep "php-cgi" | wc -l
    0
    张宴 回复于 2008-7-30 09:25
    不要意思,写错了,是:
    netstat -anpo | grep "php-cgi" | wc -l
    lhwmzy
    2008-7-30 09:08
    命令写错了吧
    gusingchen
    2008-7-30 09:18
    1、502是php执行时间过长造成,有问题的话加大进程数也没用.  2、web  服务器没有必要这么大的内存吧。cpu消耗多些。
    张宴 回复于 2008-7-30 09:27
    php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误。
    wayne Email Homepage
    2008-7-30 11:06
    预先设置的FastCGI数,是不是就是php-fpm.conf里的max_children值
    willko
    2008-7-31 22:44
    方便面没打开也会出现这个错误。。。
    JulyClyde
    2008-8-1 11:49
    504 Gateway Timeout才需要增加等待时间吧?
    502是Bad Gateway,是sock、端口没被监听造成的
    ww
    2008-8-1 20:06
    老师有2个问题。。
    1.按照你的方法配置,,但是修改php.in 的display_errors = on。。用phpinfo()看还是off的。。。已经重启并且没改错php.ini文件
    2.请问下nginx怎么才能支持index.php/id/2这样的路径呢?
    我发现只支持index.php?/id/2

    谢谢
    blankyao Email Homepage
    2008-8-3 23:44
    刚注册,我试下头像是否显示正常
    Dewei Email
    2008-8-10 17:07
    large_client_header_buffers 4 32k;
    请问上次我问的时候,你回答的这样的,要不要再加了?
    张宴 回复于 2008-8-11 10:21
    如果报的是400错误,就增大header_buffers值为32k(默认为4k)
    large_client_header_buffers 4 32k;
    wayne
    2008-8-14 16:46
    nginx里的错误日志是不是不记录 502错误的,我没有发现呀
    dodoup
    2008-8-15 17:19
    10309 daemon    15   0 7570m 2.7g  812 S    0  0.6   0:02.63 nginx                                                                  
    10310 daemon    15   0 7552m 2.7g  812 S    0  0.6   0:01.26 nginx                                                                  
    10313 daemon    15   0 75464  25m  812 S    0  0.6   0:01.23 nginx                                                                  
    10318 daemon    15   0 7543m 2.7g  812 S    0  0.6   0:01.31 nginx  

    有谁遇到过这样的问题米?
    wayne
    2008-8-20 22:37
    兄弟,帮我看一下,nginx的日志,出现好多400的错误,这样是什么原因呢?

    220.255.7.194 - - [20/Aug/2008:22:38:30 +0800] "-" 400 0 "-" "-" -
    60.190.0.78 - - [20/Aug/2008:22:38:31 +0800] "-" 400 0 "-" "-" -
    220.202.4.12 - - [20/Aug/2008:22:38:31 +0800] "-" 400 0 "-" "-" -
    220.202.4.12 - - [20/Aug/2008:22:38:31 +0800] "-" 400 0 "-" "-" -
    58.220.236.250 - - [20/Aug/2008:22:38:33 +0800] "-" 400 0 "-" "-" -
    117.40.118.93 - - [20/Aug/2008:22:38:33 +0800] "-" 400 0 "-" "-" -
    222.242.65.94 - - [20/Aug/2008:22:38:34 +0800] "-" 400 0 "-" "-" -
    58.220.236.250 - - [20/Aug/2008:22:38:34 +0800] "-" 400 0 "-" "-" -
    219.152.214.89 - - [20/Aug/2008:22:38:34 +0800] "-" 400 0 "-" "-" -
    58.33.12.209 - - [20/Aug/2008:22:38:35 +0800] "-" 400 0 "-" "-" -
    60.50.171.133 - - [20/Aug/2008:22:38:36 +0800] "-" 400 0 "-" "-" -
    jspshiwo
    2008-8-27 23:15
    我刚新安装的 ngnix 就提示 502 Bad Gateway 错误 请问为什么啊 ?

     我用 netstat -anpo | grep "php-cgi" | wc -l  查看你 显示 1
    uddtm
    2008-9-23 19:46
    还是不行呀,我的/usr/local/webserver/php/bin/里边就没有php-cgi这个文件呀,我这样该怎样启动php-cgi进程

    安装过程都正常,启动nginx后显示的也是502 Bad Gateway .
    weiwei Email Homepage
    2008-10-24 17:04
    502/504错误,改那个不顶用,而且PHP-CGI经常大片小时,网站很卡,一会又好了,感觉
    php跑PHP-CGI很不稳定,快的时候真的很快,但慢起来就是 502、504

    http://bbs.woyool.com
    hanliuyj
    2008-10-31 17:39
    我这里是这样的设置的,并发请求一多,还是出现502的错误哦
       fastcgi_connect_timeout 300;
       fastcgi_send_timeout 300;
       fastcgi_read_timeout 300;
    amazergling
    2008-11-28 13:09
    我这边用跑在按张sir手顺配置的环境下,不知为何也很不稳定,即便是测试期间只有一两个节点的访问量也会莫名其妙的出现空白页,有时候多点几下又好了,再点又空白,急煞我也 :(

    现在只好改回apache暂时将就着,但对于nginx的高负载能力很是垂涎三尺,希望尽早能够构建出稳定的nginx下的php环境,即便放弃fcgi也在所不惜......:-P
    zhifang
    2008-12-22 12:19
    张老师,我想请教个问题。
    我原来的环境是:freebsd 6.3  apache-2.2.6_2  php5.2.5
    改用nginx后是:freebsd 6.3  nginx-devel-0.6.17   php5.2.5   spawn-fcgi-1.4.18

    在换的时候我先把php5   make deinstall  
    然后make config 里把[ ] APACHE     Build Apache module  模块去掉再make install
    fast-cgi以前都是有安装的,扩展也没变。
    启动/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/local/bin/php-cgi 时超慢,2分钟左右才启动起来,restart也一样要2分钟。(能启动起来)
    但新装的系统,再安装nginx的这些环境就没有这种现象。

    请张老师或高手们指点一下,谢谢!
    zhifang
    2008-12-23 18:40
    张老师,我又碰到新问题了。
    服务器:DELL 2950   4G内存
    系统是刚装的:freebsd 7.0 amd64  nginx-devel-0.6.17   php5.2.5   spawn-fcgi-1.4.18
    /usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/local/bin/php-cgi -C 250
    fastcgi启动正常,但到生产环境上时报错:zend_mm_heap corrupted
    而且PHP-CGI的CPU占用超高,不加-C 250或调小负载还是一样很重。
    我的配置如下:
           server {
                   listen          80;
                   server_name    www.XX.com *.XX.com;
           location / {
               root   /usr/local/www/www;
               index  index.php index.html index.htm;
           }
           location ~ \.php$ {
               fastcgi_pass   127.0.0.1:9000;
               fastcgi_index  index.php;
               fastcgi_param  SCRIPT_FILENAME  /usr/local/www$fastcgi_script_name;
               include        fastcgi_params;
            }
           }
    请指点一下!谢谢!
    cfans Email Homepage
    2008-12-25 17:04
    增加fastcgi_connect_timeout 等三个参数值的方法效果也不好
    经过长时间反复测试,发现静态页面不会出现该错误,只有在运行动态页面或者长时间操作数据库时才会出现这个错误,重启Nginx+FastCGI后即可解决,但是几分钟到几个小时后又会出现该错误。
    经过测试,发现修改php-fpm.conf文件中 request_terminate_timeout即FastCGI脚本运行时间可以有效改善该问题,增加CGI进程数也可以改善该问题,但占资源太多效率太低。
    还可以修改
    <value name=\"request_terminate_timeout\">0s</value>
    <value name=\"process_control_timeout\">5s</value>
    等值对FastCGI进行优化,所以出现502的错误其实不是nginx的问题
    php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误




    转自:http://blog.s135.com/post/361/
  • linux和windows下TIME_WAIT过多的解决办法

    2011-11-29 17:52:47


    linux和windows下TIME_WAIT过多的解决办法 http://yuxu9710108.blog.163.com/blog/static/23751534201101244616211/

    如果使用了nginx代理,那么系统TIME_WAIT的数量会变得比较多,这是由于nginx代理使用了短链接的方式和后端交互的原因,使得 nginx和后端的ESTABLISHED变得很少而TIME_WAIT很多。这不但发生在安装nginx的代理服务器上,而且也会使后端的app服务器 上有大量的TIME_WAIT。查阅TIME_WAIT资料,发现这个状态很多也没什么大问题,但可能因为它占用了系统过多的端口,导致后续的请求无法获 取端口而造成障碍。

    虽然TIME_WAIT会造成一些问题,但是要完全枪毙掉它也是不正当的,虽然看起来这么做没什么错。具体可看这篇文档:

    http://hi.baidu.com/tim_bi/blog/item/35b005d784ca91d5a044df1d.html

    所以目前看来最好的办法是让每个TIME_WAIT早点过期。

    在linux上可以这么配置:

    #让TIME_WAIT状态可以重用,这样即使TIME_WAIT占满了所有端口,也不会拒绝新的请求造成障碍
    echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
    #让TIME_WAIT尽快回收,我也不知是多久,观察大概是一秒钟
    echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle

    很多文档都会建议两个参数都配置上,但是我发现只用修改tcp_tw_recycle就可以解决问题的了,TIME_WAIT重用TCP协议本身就是不建议打开的。

    不能重用端口可能会造成系统的某些服务无法启动,比如要重启一个系统监控的软件,它用了40000端口,而这个端口在软件重启过程中刚好被使用了,就可能会重启失败的。linux默认考虑到了这个问题,有这么个设定:

    #查看系统本地可用端口极限值
    cat /proc/sys/net/ipv4/ip_local_port_range

    用这条命令会返回两个数字,默认是:32768 61000,说明这台机器本地能向外连接61000-32768=28232个连接,注意是本地向外连接,不是这台机器的所有连接,不会影响这台机器的 80端口的对外连接数。但这个数字会影响到代理服务器(nginx)对app服务器的最大连接数,因为nginx对app是用的异步传输,所以这个环节的 连接速度很快,所以堆积的连接就很少。假如nginx对app服务器之间的带宽出了问题或是app服务器有问题,那么可能使连接堆积起来,这时可以通过设 定nginx的代理超时时间,来使连接尽快释放掉,一般来说极少能用到28232个连接。

    因为有软件使用了40000端口监听,常常出错的话,可以通过设定ip_local_port_range的最小值来解决:

    echo "40001 61000" > /proc/sys/net/ipv4/ip_local_port_range

    但是这么做很显然把系统可用端口数减少了,这时可以把ip_local_port_range的最大值往上调,但是好习惯是使用不超过32768的端口来侦听服务,另外也不必要去修改ip_local_port_range数值成1024 65535之类的,意义不大。

    因为使用了nginx代理,在windows下也会造成大量TIME_WAIT,当然windows也可以调整:

    在注册表(regedit)的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,值就是秒数,即可。

    windows默认是重用TIME_WAIT,我现在还不知道怎么改成不重用的,本地端口也没查到是什么值,但这些都关系不大,都可以按系统默认运作。

    ------------------------------------------------------------------------------------------------------------------------

    TIME_WAIT状态

    根据TCP协议,主动发起关闭的一方,会进入TIME_WAIT状态,持续2*MSL(Max Segment Lifetime),缺省为240秒,在这个post中简洁的介绍了为什么需要这个状态。

    值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可想而知, 对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个 TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的 TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。

    HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个request/response,一个主要 原因就是发现了这个问题。还有一个方法减缓TIME_WAIT压力就是把系统的2*MSL时间减少,因为240秒的时间实在是忒长了点,对于 Windows,修改注册表,在HKEY_LOCAL_MACHINE\ SYSTEM\CurrentControlSet\Services\ Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,一般认为不要少于60,不然可能会有麻烦。

    对于大型的服务,一台server搞不定,需要一个LB(Load Balancer)把流量分配到若干后端服务器上,如果这个LB是以NAT方式工作的话,可能会带来问题。假如所有从LB到后端Server的IP包的 source address都是一样的(LB的对内地址),那么LB到后端Server的TCP连接会受限制,因为频繁的TCP连接建立和关闭,会在server上留 下TIME_WAIT状态,而且这些状态对应的remote address都是LB的,LB的source port撑死也就60000多个(2^16=65536,1~1023是保留端口,还有一些其他端口缺省也不会用),每个LB上的端口一旦进入 Server的TIME_WAIT黑名单,就有240秒不能再用来建立和Server的连接,这样LB和Server最多也就能支持300个左右的连接。 如果没有LB,不会有这个问题,因为这样server看到的remote address是internet上广阔无垠的集合,对每个address,60000多个port实在是够用了。

    一开始我觉得用上LB会很大程度上限制TCP的连接数,但是实验表明没这回事,LB后面的一台Windows Server 2003每秒处理请求数照样达到了600个,难道TIME_WAIT状态没起作用?用Net Monitor和netstat观察后发现,Server和LB的XXXX端口之间的连接进入TIME_WAIT状态后,再来一个LB的XXXX端口的 SYN包,Server照样接收处理了,而是想像的那样被drop掉了。翻书,从书堆里面找出覆满尘土的大学时代买的《UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI》,中间提到一句,对于BSD-derived实现,只要SYN的sequence number比上一次关闭时的最大sequence number还要大,那么TIME_WAIT状态一样接受这个SYN,难不成Windows也算BSD-derived?有了这点线索和关键字 (BSD),找到这个post,在NT4.0的时候,还是和BSD-derived不一样的,不过Windows Server 2003已经是NT5.2了,也许有点差别了。

    做个试验,用Socket API编一个Client端,每次都Bind到本地一个端口比如2345,重复的建立TCP连接往一个Server发送Keep-Alive=false 的HTTP请求,Windows的实现让sequence number不断的增长,所以虽然Server对于Client的2345端口连接保持TIME_WAIT状态,但是总是能够接受新的请求,不会拒绝。那 如果SYN的Sequence Number变小会怎么样呢?同样用Socket API,不过这次用Raw IP,发送一个小sequence number的SYN包过去,Net Monitor里面看到,这个SYN被Server接收后如泥牛如海,一点反应没有,被drop掉了。

    按照书上的说法,BSD-derived和Windows Server 2003的做法有安全隐患,不过至少这样至少不会出现TIME_WAIT阻止TCP请求的问题,当然,客户端要配合,保证不同TCP连接的sequence number要上涨不要下降。

    ----------------------------------------------------------------------------------------------------------------------------

    Socket中的TIME_WAIT状态

    在高并发短连接的server端,当server处理完client的请求后立刻closesocket此时会出现 time_wait状态然后如果client再并发2000个连接,此时部分连接就连接不上了,用linger强制关闭可以解决此问题,但是linger 会导致数据丢失,linger值为0时是强制关闭,无论并发多少多能正常连接上,如果非0会发生部分连接不上的情况!(可调用setsockopt设置套接字的linger延时标志,同时将延时时间设置为0。
    TCP/IP的RFC文档。TIME_WAIT是TCP连接断开时必定会出现的状态。
    是无法避免掉的,这是TCP协议实现的一部分。
    在WINDOWS下,可以修改注册表让这个时间变短一些

    time_wait的时间为2msl,默认为4min.
    你可以通过改变这个变量:
    TcpTimedWaitDelay
    把它缩短到30s
    TCP要保证在所有可能的情况下使得所有的数据都能够被投递。当你关闭一个socket时,主动关闭一端的socket将进入 TIME_WAIT状态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。当一个socket关闭的时候,是通过两端互发信息 的四次握手过程完成的,当一端调用close()时,就说明本端没有数据再要发送了。这好似看来在握手完成以后,socket就都应该处于关闭 CLOSED状态了。但这有两个问题,首先,我们没有任何机制保证最后的一个ACK能够正常传输,第二,网络上仍然有可能有残余的数据包 (wandering duplicates),我们也必须能够正常处理。
    通过正确的状态机,我们知道双方的关闭过程如下
    linux和windows下TIME_WAIT过多的解决办法 - 笨笨猫 - 我的博客

    假设最后一个ACK丢失了,服务器会重发它发送的最后一个FIN,所以客户端必须维持一个状态信息,以便能够重发ACK;如果不维持这种状态,客户 端在接收到FIN后将会响应一个RST,服务器端接收到RST后会认为这是一个错误。如果TCP协议能够正常完成必要的操作而终止双方的数据流传输,就必 须完全正确的传输四次握手的四个节,不能有任何的丢失。这就是为什么socket在关闭后,仍然处于 TIME_WAIT状态,因为他要等待以便重发ACK。

    如果目前连接的通信双方都已经调用了close(),假定双方都到达CLOSED状态,而没有TIME_WAIT状态时,就会出现如下的情况。现在 有一个新的连接被建立起来,使用的IP地址与端口与先前的完全相同,后建立的连接又称作是原先连接的一个化身。还假定原先的连接中有数据报残存于网络之 中,这样新的连接收到的数据报中有可能是先前连接的数据报。为了防止这一点,TCP不允许从处于TIME_WAIT状态的socket建立一个连接。处于 TIME_WAIT状态的socket在等待两倍的MSL时间以后(之所以是两倍的MSL,是由于MSL是一个数据报在网络中单向发出到认定丢失的时间, 一个数据报有可能在发送图中或是其响应过程中成为残余数据报,确认一个数据报及其响应的丢弃的需要两倍的MSL),将会转变为CLOSED状态。这就意味 着,一个成功建立的连接,必然使得先前网络中残余的数据报都丢失了。

    由于TIME_WAIT状态所带来的相关问题,我们可以通过设置SO_LINGER标志来避免socket进入TIME_WAIT状态,这可以通过发送RST而取代正常的TCP四次握手的终止方式。但这并不是一个很好的主意,TIME_WAIT对于我们来说往往是有利的。

    客户端与服务器端建立TCP/IP连接后关闭SOCKET后,服务器端连接的端口
    状态为TIME_WAIT
    是不是所有执行主动关闭的socket都会进入TIME_WAIT状态呢?
    有没有什么情况使主动关闭的socket直接进入CLOSED状态呢?
    主动关闭的一方在发送最后一个 ack 后
    就会进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间
    这个是TCP/IP必不可少的,也就是“解决”不了的。

    也就是TCP/IP设计者本来是这么设计的
    主要有两个原因
    1。防止上一次连接中的包,迷路后重新出现,影响新连接
       (经过2MSL,上一次连接中所有的重复包都会消失)
    2。可靠的关闭TCP连接
       在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发
       fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以
       主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。

    TIME_WAIT 并不会占用很大资源的,除非受到攻击。

    还有,如果一方 send 或 recv 超时,就会直接进入 CLOSED 状态

    socket-faq中的这一段讲的也很好,摘录如下:
    2.7. Please explain the TIME_WAIT state.

    Remember that TCP guarantees all data transmitted will be delivered,
    if at all possible. When you close a socket, the server goes into a
    TIME_WAIT state, just to be really really sure that all the data has
    gone through. When a socket is closed, both sides agree by sending
    messages to each other that they will send no more data. This, it
    seemed to me was good enough, and after the handshaking is done, the
    socket should be closed. The problem is two-fold. First, there is no
    way to be sure that the last ack was communicated successfully.
    Second, there may be "wandering duplicates" left on the net that must
    be dealt with if they are delivered.

    Andrew Gierth (andrew@erlenstar.demon.co.uk) helped to explain the
    closing sequence in the following usenet posting:

    Assume that a connection is in ESTABLISHED state, and the client is
    about to do an orderly release. The client's sequence no. is Sc, and
    the server's is Ss. Client Server
    ====== ======
    ESTABLISHED ESTABLISHED
    (client closes)
    ESTABLISHED ESTABLISHED
    ------->>
    FIN_WAIT_1
    <<--------
    FIN_WAIT_2 CLOSE_WAIT
    <<-------- (server closes)
    LAST_ACK
    , ------->>
    TIME_WAIT CLOSED
    (2*msl elapses...)
    CLOSED

    Note: the +1 on the sequence numbers is because the FIN counts as one
    byte of data. (The above diagram is equivalent to fig. 13 from RFC
    793).

    Now consider what happens if the last of those packets is dropped in
    the network. The client has done with the connection; it has no more
    data or control info to send, and never will have. But the server does
    not know whether the client received all the data correctly; that's
    what the last ACK segment is for. Now the server may or may not care
    whether the client got the data, but that is not an issue for TCP; TCP
    is a reliable rotocol, and must distinguish between an orderly
    connection close where all data is transferred, and a connection abort
    where data may or may not have been lost.

    So, if that last packet is dropped, the server will retransmit it (it
    is, after all, an unacknowledged segment) and will expect to see a
    suitable ACK segment in reply. If the client went straight to CLOSED,
    the only possible response to that retransmit would be a RST, which
    would indicate to the server that data had been lost, when in fact it
    had not been.

    (Bear in mind that the server's FIN segment may, additionally, contain
    data.)

    DISCLAIMER: This is my interpretation of the RFCs (I have read all the
    TCP-related ones I could find), but I have not attempted to examine
    implementation source code or trace actual connections in order to
    verify it. I am satisfied that the logic is correct, though.

    More commentarty from Vic:

    The second issue was addressed by Richard Stevens (rstevens@noao.edu,
    author of "Unix Network Programming", see ``1.5 Where can I get source
    code for the book [book title]?''). I have put together quotes from
    some of his postings and email which explain this. I have brought
    together paragraphs from different postings, and have made as few
    changes as possible.

    From Richard Stevens (rstevens@noao.edu):

    If the duration of the TIME_WAIT state were just to handle TCP's full-
    duplex close, then the time would be much smaller, and it would be
    some function of the current RTO (retransmission timeout), not the MSL
    (the packet lifetime).

    A couple of points about the TIME_WAIT state.

    o The end that sends the first FIN goes into the TIME_WAIT state,
    because that is the end that sends the final ACK. If the other
    end's FIN is lost, or if the final ACK is lost, having the end that
    sends the first FIN maintain state about the connection guarantees
    that it has enough information to retransmit the final ACK.

    o Realize that TCP sequence numbers wrap around after 2**32 bytes
    have been transferred. Assume a connection between A.1500 (host A,
    port 1500) and B.2000. During the connection one segment is lost
    and retransmitted. But the segment is not really lost, it is held
    by some intermediate router and then re-injected into the network.
    (This is called a "wandering duplicate".) But in the time between
    the packet being lost & retransmitted, and then reappearing, the
    connection is closed (without any problems) and then another
    connection is established between the same host, same port (that
    is, A.1500 and B.2000; this is called another "incarnation" of the
    connection). But the sequence numbers chosen for the new
    incarnation just happen to overlap with the sequence number of the
    wandering duplicate that is about to reappear. (This is indeed
    possible, given the way sequence numbers are chosen for TCP
    connections.) Bingo, you are about to deliver the data from the
    wandering duplicate (the previous incarnation of the connection) to
    the new incarnation of the connection. To avoid this, you do not
    allow the same incarnation of the connection to be reestablished
    until the TIME_WAIT state terminates.

    Even the TIME_WAIT state doesn't complete solve the second problem,
    given what is called TIME_WAIT assassination. RFC 1337 has more
    details.

    o The reason that the duration of the TIME_WAIT state is 2*MSL is
    that the maximum amount of time a packet can wander around a
    network is assumed to be MSL seconds. The factor of 2 is for the
    round-trip. The recommended value for MSL is 120 seconds, but
    Berkeley-derived implementations normally use 30 seconds instead.
    This means a TIME_WAIT delay between 1 and 4 minutes. Solaris 2.x
    does indeed use the recommended MSL of 120 seconds.

    A wandering duplicate is a packet that appeared to be lost and was
    retransmitted. But it wasn't really lost ... some router had
    problems, held on to the packet for a while (order of seconds, could
    be a minute if the TTL is large enough) and then re-injects the packet
    back into the network. But by the time it reappears, the application
    that sent it originally has already retransmitted the data contained
    in that packet.

    Because of these potential problems with TIME_WAIT assassinations, one
    should not avoid the TIME_WAIT state by setting the SO_LINGER option
    to send an RST instead of the normal TCP connection termination
    (FIN/ACK/FIN/ACK). The TIME_WAIT state is there for a reason; it's
    your friend and it's there to help you :-)

    I have a long discussion of just this topic in my just-released
    "TCP/IP Illustrated, Volume 3". The TIME_WAIT state is indeed, one of
    the most misunderstood features of TCP.

    I'm currently rewriting "Unix Network Programming" (see ``1.5 Where
    can I get source code for the book [book title]?''). and will include
    lots more on this topic, as it is often confusing and misunderstood.

    An additional note from Andrew:

    Closing a socket: if SO_LINGER has not been called on a socket, then
    close() is not supposed to discard data. This is true on SVR4.2 (and,
    apparently, on all non-SVR4 systems) but apparently not on SVR4; the
    use of either shutdown() or SO_LINGER seems to be required to
    guarantee delivery of all data.

    -------------------------------------------------------------------------------------------

    讨厌的 Socket TIME_WAIT 问题

    netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

    会得到类似下面的结果,具体数字会有所不同:

    LAST_ACK 1
    SYN_RECV 14
    ESTABLISHED 79
    FIN_WAIT1 28
    FIN_WAIT2 3
    CLOSING 5
    TIME_WAIT 1669

    状态:描述
    CLOSED:无连接是活动的或正在进行
    LISTEN:服务器在等待进入呼叫
    SYN_RECV:一个连接请求已经到达,等待确认
    SYN_SENT:应用已经开始,打开一个连接
    ESTABLISHED:正常数据传输状态
    FIN_WAIT1:应用说它已经完成
    FIN_WAIT2:另一边已同意释放
    ITMED_WAIT:等待所有分组死掉
    CLOSING:两边同时尝试关闭
    TIME_WAIT:另一边已初始化一个释放
    LAST_ACK:等待所有分组死掉

    也就是说,这条命令可以把当前系统的网络连接状态分类汇总。

    下面解释一下为啥要这样写:

    一个简单的管道符连接了netstat和awk命令。

    ------------------------------------------------------------------

    每个TCP报文在网络内的最长时间,就称为MSL(Maximum Segment Lifetime),它的作用和IP数据包的TTL类似。

    RFC793指出,MSL的值是2分钟,但是在实际的实现中,常用的值有以下三种:30秒,1分钟,2分钟。

    注意一个问题,进入TIME_WAIT状态的一般情况下是客户端,大多数服务器端一般执行被动关闭,不会进入TIME_WAIT状态,当在服务

    器端关闭某个服务再重新启动时,它是会进入TIME_WAIT状态的。

    举例:
    1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的

    80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。
    2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连

    接还处于TIME_WAIT状态。


    检查net.ipv4.tcp_tw当前值,将当前的值更改为1分钟:
    [root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
    net.ipv4.tcp_tw_reuse = 0
    net.ipv4.tcp_tw_recycle = 0
    [root@aaa1 ~]#

    vi /etc/sysctl
    增加或修改net.ipv4.tcp_tw值:
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1

    使内核参数生效:
    [root@aaa1 ~]# sysctl -p

    [root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1

    用netstat再观察正常


    这里解决问题的关键是如何能够重复利用time_wait的值,我们可以设置时检查一下time和wait的值
    #sysctl -a | grep time | grep wait
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120

    问一下TIME_WAIT有什么问题,是闲置而且内存不回收吗?

    是的,这样的现象实际是正常的,有时和访问量大有关,设置这两个参数: reuse是表示是否允许重新应用处于TIME-WAIT状态的

    socket用于新的TCP连接; recyse是加速TIME-WAIT sockets回收

    Q: 我正在写一个unix server程序,不是daemon,经常需要在命令行上重启它,绝大
    多数时候工作正常,但是某些时候会报告"bind: address in use",于是重启失
    败。

    A: Andrew Gierth
    server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。至于
    TIME_WAIT状态,你无法避免,那是TCP协议的一部分。

    Q: 如何避免等待60秒之后才能重启服务

    A: Erik Max Francis

    使用setsockopt,比如

    --------------------------------------------------------------------------
    int ption = 1;

    if ( setsockopt ( masterSocket, SOL_SOCKET, SO_REUSEADDR, &option,
    sizeof( option ) ) < 0 )
    {
    die( "setsockopt" );
    }
    --------------------------------------------------------------------------

    Q: 编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?

    A: 这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用
    端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,
    指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧
    使用同一端口,此时 SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期
    望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不
    可能。

    一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端
    口。SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组
    还是唯一确定的。所以,重启后的服务程序有可能收到非期望数据。必须慎重使
    用 SO_REUSEADDR 选项。

    Q: 在客户机/服务器编程中(TCP/SOCK_STREAM),如何理解TCP自动机 TIME_WAIT 状
    态?

    A: W. Richard Stevens <1999年逝世,享年49岁>

    下面我来解释一下 TIME_WAIT 状态,这些在<>
    中2.6节解释很清楚了。

    MSL(最大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现
    都必须选择一个确定的MSL值。RFC 1122建议是2分钟,但BSD传统实现采用了30秒。

    TIME_WAIT 状态最大保持时间是2 * MSL,也就是1-4分钟。

    IP头部有一个TTL,最大值255。尽管TTL的单位不是秒(根本和时间无关),我们仍需
    假设,TTL为255的TCP报文在Internet上生存时间不能超过MSL。

    TCP报文在传送过程中可能因为路由故障被迫缓冲延迟、选择非最优路径等等,结果
    发送方TCP机制开始超时重传。前一个TCP报文可以称为"漫游TCP重复报文",后一个
    TCP报文可以称为"超时重传TCP重复报文",作为面向连接的可靠协议,TCP实现必须
    正确处理这种重复报文,因为二者可能最终都到达。

    一个通常的TCP连接终止可以用图描述如下:

    client server
    FIN M
    close -----------------> (被动关闭)
    ACK M+1
    <-----------------
    FIN N
    <----------------- close
    ACK N+1
    ----------------->

    为什么需要 TIME_WAIT 状态?

    假设最终的ACK丢失,server将重发FIN,client必须维护TCP状态信息以便可以重发
    最终的ACK,否则会发送RST,结果server认为发生错误。TCP实现必须可靠地终止连
    接的两个方向(全双工关闭),client必须进入 TIME_WAIT 状态,因为client可能面
    临重发最终ACK的情形。

    {
    scz 2001-08-31 13:28

    先调用close()的一方会进入TIME_WAIT状态
    }

    此外,考虑一种情况,TCP实现可能面临先后两个同样的相关五元组。如果前一个连
    接处在 TIME_WAIT 状态,而允许另一个拥有相同相关五元组的连接出现,可能处理
    TCP报文时,两个连接互相干扰。使用 SO_REUSEADDR 选项就需要考虑这种情况。

    为什么 TIME_WAIT 状态需要保持 2MSL 这么长的时间?

    如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。
    第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二
    个连接。TCP实现必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT
    状态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被
    丢弃。建立第二个连接的时候,不会混淆。

    A: 小四

    在Solaris 7下有内核参数对应 TIME_WAIT 状态保持时间

    # ndd -get /dev/tcp tcp_time_wait_interval
    240000
    # ndd -set /dev/tcp tcp_time_wait_interval 1000

    缺省设置是240000ms,也就是4分钟。如果用ndd修改这个值,最小只能设置到1000ms,
    也就是1秒。显然内核做了限制,需要Kernel Hacking。

    # echo "tcp_param_arr/W 0t0" | adb -kw /dev/ksyms /dev/mem
    physmem 3b72
    tcp_param_arr: 0x3e8 = 0x0
    # ndd -set /dev/tcp tcp_time_wait_interval 0

    我不知道这样做有什么灾难性后果,参看<>的声明。

    Q: TIME_WAIT 状态保持时间为0会有什么灾难性后果?在普遍的现实应用中,好象也
    就是服务器不稳定点,不见得有什么灾难性后果吧?

    D: rain@bbs.whnet.edu.cn

    Linux 内核源码 /usr/src/linux/include/net/tcp.h 中

    #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
    * close the socket, about 60 seconds */

    最好不要改为0,改成1。端口分配是从上一次分配的端口号+1开始分配的,所以一般
    不会有什么问题。端口分配算法在tcp_ipv4.c中tcp_v4_get_port中。


    转自:http://blog.csdn.net/ajian005/article/details/6724814



  • 有关nginx的worker_processes参数

    2011-11-23 15:23:58

    有关nginx的worker_processes参数


    分享一:

    搜索到原作者的话:

    As a general rule you need the only worker with large number of
    worker_connections, say 10,000 or 20,000.

    However, if nginx does CPU-intensive work as SSL or gzipping and
    you have 2 or more CPU, then you may set worker_processes to be equal
    to CPU number.

    Besides, if you serve many static files and the total size of the files
    is bigger than memory, then you may increase worker_processes to
    utilize a full disk bandwidth.

    Igor Sysoev

    一般一个进程足够了,你可以把连接数设得很大。如果有SSL、gzip这些比较消耗CPU的工作,而且是多核CPU的话,可以设为和CPU的数量一样。或 者要处理很多很多的小文件,而且文件总大小比内存大很多的时候,也可以把进程数增加,以充分利用IO带宽(主要似乎是IO操作有block)。

    根据我配置实践,服务器是“多个CPU+gzip+网站总文件大小大于内存”的环境,worker_processes设置为CPU个数的两倍比较好。



    分享二:

    最近PPC经常出现502错误,网页经常无法打开,所以本人决定对Nginx进行深入折腾!

    Nginx本身没有挂掉,否则不会出现502的错误信息,所以原因一定在Nginx的设置上。

    经过我查阅资料和测试,发现有可能是worker_processes的参数设置不当引起的。

    worker_processes默认情况下为1,一般情况下不用修改,但考虑到实际情况,可以修改这个数值,以提高性能,官方的建议是修改成CPU的内核数,这里引用一段翻译过的文章: 
    worker_processes指明了nginx要开启的进程数,据官方说法,一般开一个就够了,多开几个,可以减少机器io带来的影响。据实践表明,nginx的这个参数在一般情况下开4个或8个就可以了,再往上开的话优化不太大。据另一种说法是,nginx开启太多的进程,会影响主进程调度,所以占用的cpu会增高。
    经过我测试发现,这个数字是不能乱设置的,如果网站没有出现io性能问题,最好不要修改,采用默认的1即可,如果非要设置,必须要和CPU的内核数匹配,否则要么就假死(主要是Windows),要么就出现502的错误(主要是Linux)。

    我的电脑是双核的,按理说应该是2,但是实际上应该是4,因为是双线程的。测试结果如下: 
    1、worker_processes为1,线程打开2个,有一个是主线程,运行很稳定。
    2、worker_processes为2,线程打开3个,有一个是主线程,1分钟左右挂掉(假死,无法打开网页,浏览器一直处于载入中)。
    3、worker_processes为4,线程打开5个,有一个是主线程,运行很稳定。

    4、worker_processes为8,线程打开9个,有一个是主线程,和2一样,1分钟左右挂掉。


    配置参考

    配置1:4 CPU (4 Core) + 4 worker_processes (每个worker_processes 使用1个CPU)

    [reistlin@reistlin.com ~]$ cat /proc/cpuinfo | grep processor
    processor       : 0
    processor       : 1
    processor       : 2
    processor       : 3
    worker_processes 4;
    worker_cpu_affinity 0001 0010 0100 1000;

    配置2:8 CPU (8 Core) + 8 worker_processes (每个worker_processes 使用1个CPU)

    [reistlin@reistlin.com ~]$ cat /proc/cpuinfo | grep processor
    processor       : 0
    processor       : 1
    processor       : 2
    processor       : 3
    processor       : 4
    processor       : 5
    processor       : 6
    processor       : 7
    worker_processes 8;
    worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

    配置3:16 CPU (16 Core) + 16 worker_processes (每个worker_processes 使用1个CPU)

    [reistlin@reistlin.com ~]$ cat /proc/cpuinfo | grep processor
    processor       : 0
    processor       : 1
    processor       : 2
    processor       : 3
    processor       : 4
    processor       : 5
    processor       : 6
    processor       : 7
    processor       : 8
    processor       : 9
    processor       : 10
    processor       : 11
    processor       : 12
    processor       : 13
    processor       : 14
    processor       : 15
    worker_processes 16;
    worker_cpu_affinity 0000000000000001 0000000000000010 0000000000000100 0000000000001000 0000000000010000 0000000000100000 0000000001000000 0000000010000000 0000000100000000 0000001000000000 0000010000000000 0000100000000000 0001000000000000 0010000000000000 0100000000000000 1000000000000000;

    标签: linuxnginx

    Nginx worker_cpu_affinity 设置

    根据 Nginx Wiki 上的资料显示:

    worker_cpu_affinity

    Syntax: worker_cpu_affinity cpumask [cpumask...]

    Default: none

    Linux only.

    With this option you can bind the worker process to a CPU, it calls sched_setaffinity().

    For example,

    worker_processes     4;
    worker_cpu_affinity 0001 0010 0100 1000;

    Bind each worker process to one CPU only.

    worker_processes     2;
    worker_cpu_affinity 0101 1010;

    Bind the first worker to CPU0/CPU2, bind the second worker to CPU1/CPU3. This is suitable for HTT.

    worker_cpu_affinity 默认是没有开启的,根据例子我们可以看得出,0001 0010 0100 1000 分别代表第1、2、3、4个逻辑CPU,所以我们可以设置0010 0100 1000来将3个进程分别绑定到第2、3、4个逻辑CPU上:
    worker_processes 3;
    worker_cpu_affinity 0010 0100 1000;

    同时根据例子我们也可以看出,worker_cpu_affinity 可以将同1个进程绑定在2个逻辑CPU上:
    worker_processes 2;
    worker_cpu_affinity 0101 1010;

    0101也就是第1、3个逻辑CPU上,1010就是第2、4个逻辑CPU上。 

     

     

    分享三:

    worker_processes指明了nginx要开启的进程数,据官方说法,一般开一个就够了,多开几个,可以减少机器io带来的影响。


    据实践表明,nginx的这个参数在一般情况下开4个或8个就可以了,再往上开的话优化不太大。据另一种说法是,nginx开启太多的进程,会影响主进程调度,所以占用的cpu会增高,这个说法我个人没有证实,估计他们是开了一两百个进程来对比的吧。

    worker_processes配置的一些注意事项:

    1、worker_cpu_affinity配置最好是能写上

    我这里服务器多数是双核超线程,相当于4cpu,我一般开8进程,所以这个配置就是这样:

    worker_cpu_affinity 0001 0100 1000 0010 0001 0100 1000 0010;

    另,worker_cpu_affinity不是什么时候都能用的,我没有认真研究并罗列所有情况,只知道2.4内核的机器用不了,如果用不了的话,那么最好是加大worker_processes进程数,这样分配cpu就会平均一点啦,如果不平均只好多重启几下。

    2、worker_rlimit_nofile配置要和系统的单进程打开文件数一致,千万不要再画蛇添足地除以worker_processes。

    我现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。

    这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。



    转自:
    http://note.sdo.com/u/1188867330/n/6TaQ2~jwaIr0LX00c000-r

    来源: http://bbs.linuxtone.org/thread-1062-1-1.html

  • nginx1.0安装配置详解

    2011-11-23 15:19:38

    nginx1.0安装配置详解

    本文转自:twenty_four的博文,自己稍作精简修改。
    http://twentyfour.blog.51cto.com/945260/568906


    1、选择Nginx的理由
    1.1 支持高并发连接
    通过top命令可以查看系统负载和CPU使用率
    由于apache采用的是select网络I/O模型,处理大量连续的读写很低效
    1.2 内存消耗少
    在服务器3W并发连接下,开启10个Nginx进程消耗150MB内存(15MB*10),开启64个php-cgi进程消耗128MB内存(20MB*64),共消耗不到2GB内存,可以使用webbench做压力测试,运行依旧很快。
    1.3 成本低廉
    购买F5 BIG-IP、NetScaler等负载均衡交换机需要几十万RMB,而开源Nginx替代这些商业设备。
    1.4 其他理由
    网络配置简单,对比apache就知道了
    支持rewrite重写规则,能够根据域名、URL的不同、将HTTP请求分到不同的后端服务器群组
    内置的健康检查功能
    节省带宽,支持GZIP压缩,可以添加浏览器本地缓存的Header头
    支持热部署,能够在不间断服务的情况下、对软件版本进行升级

    结论:Nginx在反向代理、rewrite规则、稳定性、静态文件处理、内存消耗等方面都表现出很强的优势。

    二、Nginx安装与启用
    Nginx服务器的安装与配置
    http://www.nginx.net/
    最新稳定版nginx-1.0.0

    首先linux系统得安装有GCC编译器,再者还有autoconf和automake工具用于自动创建功能完善的makefile,因为Nginx也是用这一工具生成makefile的。
    用yum命令安装GCC和autoconf和automake工具:
    yum install gcc gcc-c++ autoconf automake -y

    Nginx的一些模块需要其他第三方库的支持,例如gzip模块需要zlib库、rewrite模块需要pcre库 、ssl功能需要openssl库等。同样可以使用Yum安装这些模块依赖的库:
    yum install zlib zlib-devel openssl openssl-devel pcre pcre-devel
    (当然最好使用最新版本源码包安装,像系统ISO文件里头自带的pcre库就相对旧些)

    1、安装Nginx
    1.1 安装Nginx所需要的pcre库、才得以支持rewrite
      tar zxvf pcre-8.02.tar.gz
      cd pcre-8.02
      ./configure
      make && make install
    1.2 安装Nginx
      tar zxvf nginx-1.0.0.tar.gz
      cd nginx-1.0.0
      ./configure --prefix=/usr/local/nginx --with-http_ssl_module
      make && make install
    --->
    Configuration summary
      + using system PCRE library
      + using system OpenSSL library
      + md5: using OpenSSL library
      + using system zlib library


    2、启动Nginx
    # /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
    查看进程:
    # ps -ef |grep  nginx
    root     11659     1  0 14:13 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
    nobody   11660 11659  0 14:13 ?        00:00:00 nginx: worker process
    查看端口号:            
    # netstat -antup |grep nginx
    tcp     0    0 0.0.0.0:80      0.0.0.0:*    LISTEN      11659/nginx.conf
    从上面可以看到Nginx启用一个主进程和一个子进程,我们可以修改nginx.conf里头的
    worker_processes使得运行多个子进程。

    3、停止Nginx
    当Nginx服务启动起来后,就会在原本空目录/usr/local/nginx/logs/下自动生成3个文件:
    access.log  error.log  nginx.pid
    这里包含nginx的主进程号:nginx.pid ,我们可以通过如上的ps命令查看、也可以直接cat出来
    3.1 从容停止Nginx
    kill -QUIT Nginx主进程号
    # kill -QUIT `cat /usr/local/nginx/logs/nginx.pid`
    3.2 快速停止Nginx
    kill -TERM Nginx主进程号
    # kill -TERM `cat /usr/local/nginx/logs/nginx.pid`

    4、重启Nginx
    如果改变了Nginx的主配置文件,想重启Nginx,可以先检查Nginx的配置文件是否正确后才发送系统信号给Nginx主进程的方式进行,检查方法如下:
    # /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
    nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
    只有出现如上OK信息才会加载新的配置文件。
    4.1 平滑重启Nginx
    kill -HUP Nginx主进程号
    # kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
    如果Nginx本身都还没启动,平滑重启可是会报错的。

    5、Nginx的信号控制
    TERM,INT  快速关闭
    QUIT       从容关闭
    HUP        平滑重启
    USR1       重新打开日志文件、在切割日志时用途大
    USR2       平滑升级可执行程序
    WINCH      从容关闭工作进程

    三、Nginx的基本配置与优化

    首先看Nginx的主配置文件,可以发现原本的配置文件非常简练

    # grep -v "#" nginx.conf  worker_processes  1;  events {      worker_connections  1024;  }  http {      include       mime.types;      default_type  application/octet-stream;      sendfile        on;      keepalive_timeout  65;      server {          listen       80;          server_name  localhost;          location / {              root   html;              index  index.html index.htm;          }          error_page   500 502 503 504  /50x.html;          location = /50x.html {              root   html;          }      }  }
    1、配置虚拟主机
    1.1、配置基于IP的虚拟主机
    首先添加虚拟网卡:

      ifconfig eth0:1 110.65.99.209 broadcast 110.65.99.255 netmask 255.255.252.0 up
      route add -host 110.65.99.209 dev eth0:1
      ifconfig eth0:2 110.65.99.210 broadcast 110.65.99.255 netmask 255.255.252.0 up
      route add -host 110.65.99.210 dev eth0:2
    如上命令最好写进/etc/rc.local中使得系统开机自动创建。
    或者直接cp ifcfg-eth0 ifcfg-eth0:1

    修改Nginx的主配置文件: /usr/local/nginx/conf/nginx.conf
    在原本定义的一个server之后添加如下两个虚拟主机


    ###############server2################################          server {          listen  110.65.99.209:80;          server_name     server2;          access_log      logs/server2.access.log combined;          location / {          index   index.html index.htm;          root    /usr/local/nginx/server2;                    }          }  ###############server3################################          server {          listen  110.65.99.210:80;          server_name     server3;          access_log      logs/server3.access.log combined;          location / {          index   index.html index.htm;          root    /usr/local/nginx/server3;                    }          }
    然后创建目录server2和server3,并且在各自目录下创建index.html测试文件
    检查配置文件是否写正确,然后才平滑重启Nginx
    # /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
    # kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
    测试:
    #  links http://110.65.99.209
    #  links http://110.65.99.210
    测试后在/usr/local/nginx/logs目录下会自动创建Log日志文件
    server2.access.log  server3.access.log
    # cat server2.access.log
    110.65.99.209 - - [21/Apr/2011:22:34:11 +0800] "GET / HTTP/1.1" 200 8 "-" "ELinks/0.11.1 (textmode; Linux; 142x38-2)"
    # cat server3.access.log
    110.65.99.210 - - [21/Apr/2011:22:34:24 +0800] "GET / HTTP/1.1" 200 8 "-" "ELinks/0.11.1 (textmode; Linux; 142x38-2)"


    1.2、配置基于域名的虚拟主机
    接着如上的配置在server3下面添加如下两个虚拟主机


    ###############server4################################          server {          listen  80;          server_name     server4.com;          access_log      logs/server4.access.log combined;          location / {          index   index.html index.htm;          root    /usr/local/nginx/server4;                    }          }  ###############server5################################          server {          listen  80;          server_name     server5.com;          access_log      logs/server5.access.log combined;          location / {          index   index.html index.htm;          root    /usr/local/nginx/server5;                    }          }
    然后创建目录server4和server5,并且在各自目录下创建index.html测试文件
    检查配置文件是否写正确,然后才平滑重启Nginx
    # /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
    # kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
    为了让系统直接缓存域名解析,在/etc/hosts后面追加如下内容(110.65.99.208是eth0-IP):
    110.65.99.208   server5.com
    110.65.99.208   server4.com
    测试:
    # links http://server4.com
    # links http://server5.com
    测试后在/usr/local/nginx/logs目录下会自动创建Log日志文件
    # cat server4.access.log
    110.65.99.208 - - [21/Apr/2011:22:41:46 +0800] "GET / HTTP/1.1" 200 8 "-" "ELinks/0.11.1 (textmode; Linux; 142x38-2)"
    # cat server5.access.log
    110.65.99.208 - - [21/Apr/2011:22:40:56 +0800] "GET / HTTP/1.1" 200 8 "-" "ELinks/0.11.1 (textmode; Linux; 142x38-2)"

     

    2、Nginx的日志文件配置与切割
    如上的日志文件内容是有一定的指令定义的,在Nginx的主配置文件中是通过
    log_format指令来设置日志格式:

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

    如上指令的解析:
    $remote_addr用户获取客户端的IP地址,但如果前端使用了反向代理,则获取到的是反向代理服务器的IP地址
    $http_x_forwarded_for"则可以使得反向代理服务器转发请求的HTTP头信息来记录客户端IP
    $request用于记录请求的URL和HTTP协议
    $time_local用于记录访问时间与时区
    $status用于记录请求状态,成功时状态为200,页面找到时状态为404
    $body_bytes_sent用于记录发送给客户端的文件主体内容大小
    $http_user_agent用于记录客户端浏览器的相关信息
    $http_referer用于记录是从哪个页面链接访问过来的

    上面指定好了日志格式后就要定义日志存放的路径了,access_log指令用于指定日志存放的路径
    如果说不想记录日志,则直接
    access_log off;
    如果使用如下定义的日志格式存储日志,则可以通过
    access_log  logs/access.log main;
    表示采用main的日志格式,记录在/usr/local/nginx/logs/access.log文件中
    (如果把日志存储路径定义在其他地方,要确保Nginx进程设置的用户和组对该目录有读写权限,否则该日志文件就无法生成了)

    对于生产系统下的server,由于巨大的访问量会导致日志文件的增加非常快,日志太大会影响server的效率,同时为了方便对日志进行分析计算,所以需要对日志文件做定时切割,这里使用按天计算切割。
    先前的文档提及过kill -USR1的作用时重新打开日志文件,这样我们就可以先对旧的日志文件重命名,通过kill -USR1重新生成access.log文件。最后借助crontab进行按天切割的计划任务。
    如下通过一个shell脚本进行日志切割:


    #!/bin/bash  logs_path1="/usr/local/nginx/oldlog" logs_path2="/usr/local/nginx/logs" mkdir -p $logs_path1  time=`date +%Y%m%d`  mv ${logs_path2}/access.log ${logs_path1}/$time.access.log  kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`  通过crontab计划任务实现每天凌晨3点做一次日志切割  # chmod +x /usr/local/nginx/log.sh  # crontab -l  * 3 * * * /usr/local/nginx/log.sh

    3、Nginx的压缩输出配置与自动列目录配置
    3.1、Nginx的压缩输出配置
    gzip(GNU- ZIP)是一种压缩技术,通过gzip压缩后的页面可以变为原来的30%,使得用户浏览页面的时候速度会快很多,gzip的压缩需要browser和 server都支持。其过程是server端进行gzip压缩,browser端解压并解析。目前大多数browser都支持gzip过的页面,如IE、 firefox、chrome。
    Nginx的压缩输出由一组gzip指令来实现,默认的Nginx配置文件仅仅为
    gzip  on;
    这么个简单的指令,所以我们需要参考gzip模块相关介绍,实现gzip的具体压缩功能
    如下:
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 2;
    gzip_vary on;
    3.2、 Nginx的自动列目录配置
    当指定目录下不存在index指令设置的默认首页文件,当访问该页面的时候会出现403 Forbidden
    的信息,所以可以通过在Nginx的主配置文件中的location / {......}目录控制中配置自动列目录,如下代码:
    location / {
     autoindex on;
    }
    这样就可以访问页面显示出该目录下的文件或目录,而不是403 Forbidden信息。
    3.3、 Nginx的浏览器本地缓存设置
    browser caching是为了加速浏览,在用户磁盘上对最近请求过的文档进行存储。当访问者再次请求这个页面的时候,browser就可以直接从本地磁盘显示文档,从而加速页面的阅览,最终到达节约网络资源。
    browser caching通过expires指令输出header头来实现,该指令语法如下:
    语法:expires [time|epoch|max|off]
    默认值: expires off
    作用域: http ,server ,location
    假设一个html页面会引用到一些javascript文件、图片文件,而这些格式的文件很少会被修改,则可以通过expires设置browser caching
    eg:对常见格式的图片、flash文件在浏览器本地缓存30天,对Js、css文件在本地缓存1个小时:
    location ~ .*/.(gif|jpg|jpeg|png|bmp|swf)$
    {
     expires 30d;
    }
    location ~ .*/.(js|css)?$
    {
     expires 1h;
    }

    四、Nginx与PHP(FastCGI)的安装、配置与优化

    CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。
    FastCGI 是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解释器的反复加载是 CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等。

    FastCGI的工作原理(摘自百度百科)
    1、web server(Nginx)启动时载入FastCGI进程管理器
    2、FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自web server的连接
    3、当客户端请求到达web server时,FastCGI进程管理器选择并连接到一个CGI解释器。web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi
    4、FastCGI子进程完成处理后将标准输出和错误信息从同一个连接返回web server,当FastCGI子进程关闭连接时,请求便高处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器的下一个连接。

    所以,如果是使用CGI技术的话,每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。然而不足之处在于FastCGI比CGI消耗更多的系统内存,因为FastCGI是多进程的,CGI是多线程的。

    1、安装PHP所需库(FastCGI模式)
    1.1、 编译安装PHP所需的支持库

    1>libiconv
    GNU的libiconv是为nicode和其他的传统编码两种应用设计的编码转换库
    http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz
      tar zxvf libiconv-1.13.1.tar.gz
      cd libiconv-1.13.1
      ./configure --prefix=/usr/local/
      make && make install

    2>libmcrypt
    Libmcrypt is a library which provides a uniform. interface to several symmetric encryption algorithms. It is intended to have a simple interface to access encryption algorithms in ofb, cbc, cfb, and ecb modes. The algorithms it supports are DES, 3DES, RIJNDAEL, Twofish, IDEA, GOST, CAST-256, ARCFOUR, SERPENT, SAFER+, and more. The algorithms and modes are also modular so you can add and remove them on the fly without recompiling the library.
    主要功能用于加密解密
    http://down1.chinaunix.net/distfiles/libmcrypt-2.5.7.tar.gz
      tar zxvf libmcrypt-2.5.7.tar.gz
      cd libmcrypt-2.5.7
      ./configure
      make && make install
      /sbin/ldconfig     #ldconfig通常在系统启动时运行,当用户安装了一个新的动态链接库时,就需要手工运行这个命令
      cd libltdl/
      ./configure --enable-ltdl-install
      make && make install

    3>mhash
    mhash是哈希函数库,比如用来计算消息的校验码之类的
    http://sourceforge.net/projects/mhash/files/mhash/0.9.9/mhash-0.9.9.tar.gz/download
      tar jxvf mhash-0.9.9.9.tar.bz2
      cd mhash-0.9.9.9
      ./configure
      make && make install

    4>mcrypt
    Mcrypt扩展库可以对数据进行加密和解密
    http://code.google.com/p/lcmp/downloads/detail?name=mcrypt-2.6.8.tar.gz
      tar zxvf mcrypt-2.6.8.tar.gz.gz
      cd mcrypt-2.6.8
      /sbin/ldconfig
      ./configure
      make && make install

    这里我出现了个小报错:configure: error: *** libmcrypt was not found

    是因为环境变量的问题,gcc编译的时候根据自身定义的变量寻找相关函数库等文件,libmcrypt也是刚安装的,在变量中没有定义出来,所以手动添加:

    #export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH


     

     

    5>建立软连接
      ln -s /usr/local/lib/libmcrypt.la /usr/lib/libmcrypt.la
      ln -s /usr/local/lib/libmcrypt.so /usr/lib/libmcrypt.so
      ln -s /usr/local/lib/libmcrypt.so.4 /usr/lib/libmcrypt.so.4
      ln -s /usr/local/lib/libmcrypt.so.4.4.7 /usr/lib/libmcrypt.so.4.4.7
      ln -s /usr/local/lib/libmhash.* /usr/lib/

     

    2、安装mysql
    http://www.mysql.com/downloads/mysql/5.1.html#downloads
    选择下拉“source code”最后一个
    官网要注册才能下载的,去台湾一个网站可以直接下载:
    http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.57.tar.gz/from/http://mysql.cs.pu.edu.tw/

    或者:
    http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.57.tar.gz/from/http://mysql.ntu.edu.tw/

    rpm版mysql需要安装三个包:

    MySQL-server-community-5.1.57-1.rhel5.x86_64.rpm
    MySQL-client-community-5.1.57-1.rhel5.x86_64.rpm
    MySQL-devel-community-5.1.57-1.rhel5.x86_64.rpm


    http://dev.mysql.com/get/Downloads/MySQL-5.1/MySQL-server-community-5.1.57-1.rhel5.x86_64.rpm/from/http://mysql.ntu.edu.tw/

    http://dev.mysql.com/get/Downloads/MySQL-5.1/MySQL-client-community-5.1.57-1.rhel5.x86_64.rpm/from/http://mysql.cs.pu.edu.tw/


    http://dev.mysql.com/get/Downloads/MySQL-5.1/MySQL-devel-community-5.1.57-1.rhel5.x86_64.rpm/from/http://mysql.cs.pu.edu.tw/

     

    useradd mysql
      tar zxvf mysql-5.1.56.tar.gz
      cd mysql-5.1.56
      ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile --with-plugins=innobase
      make && make install
      cp support-files/my-medium.cnf /etc/my.cnf
      cd /usr/local/mysql/
      bin/mysql_install_db --user=mysql
      chown -R root .
      chown -R mysql var/
      chgrp -R mysql .
      bin/mysqld_safe --user=mysql &
      ln -s /usr/local/mysql/bin/* /usr/bin/
      mysqladmin -uroot password 123456
      mysql -uroot -p123456
    mysql> GRANT ALL PRIVILEGES ON *.* TO
    'admin'@'localhost' IDENTIFIED BY '123456';


    3、安装PHP
    1、编译安装PHP(FastCGI模式)
      tar zxvf php-5.2.17.tar.gz
      gzip -cd php-5.2.17-fpm-0.5.14.diff.gz | patch -d php-5.2.17 -p1 //打补丁
      cd php-5.2.17
      ./configure --prefix=/usr/local/php --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr/ --enable-xml --disable-rpath --enable-discard-path --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-fastcgi --enable-fpm --enable-force-cgi-redirect --enable-mbstring --with-mcrypt --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-ldap --with-ldap-sasl --with-xmlrpc --enable-zip --enable-soap --without-pear --with-mysql=/usr/local/mysql/

    注意:如果是RPM版MYSQL可能会出现报错
    configure: error: Cannot find libmysqlclient under /usr.
    解决方法是将 /usr/lib64/mysql/libmysqlclient.a libmysqlclient.la 拷贝到/usr/lib/下,另外编译参数 --with-mysql=/usr/local/mysql/
    需改为:--with-mysql=/usr

    make ZEND_EXTRA_LTBS='-liconv'
      make install
      cp php.ini-dist /usr/local/php/etc/php.ini
      cp php.ini-dist /usr/local/lib/php.ini


    4、编译安装php5扩展模块
    1>memcache
    Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。
    它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
    php中的所讲的memcache是PHP的一个扩展,是一个客户端,用于连接memcached。
    http://pecl.php.net/get/memcache-2.2.6.tgz
      tar zxvf memcache-2.2.6.tgz
      cd memcache-2.2.6
      /usr/local/php/bin/phpize
      ./configure --with-php-config=/usr/local/php/bin/php-config
      make && make install

    2>eaccelerator
    eAccelerator是一个自由开放源码php加速器,优化和动态内容缓存,提高了php脚本的缓存性能,使得PHP脚本在编译的状态下,对服务器的开销几乎完全消除。 它还有对脚本起优化作用,以加快其执行效率。使PHP程序代码执效率能提高1-10倍;
    http://bart.eaccelerator.net/source/0.9.6.1/eaccelerator-0.9.6.1.tar.bz2
      tar jxvf eaccelerator-0.9.6.1.tar.bz2
      cd eaccelerator-0.9.6.1
      /usr/local/php/bin/phpize
      ./configure --enable-eaccelerator=shared --with-php-config=/usr/local/php/bin/php-config
      make && make install

    3>PDO_MYSQL
    PDO_MYSQL is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to MySQL 3.x, 4.x and 5.x databases.
    http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz
      tar zxvf PDO_MYSQL-1.0.2.tgz
      cd PDO_MYSQL-1.0.2
      /usr/local/php/bin/phpize
      ./configure --with-php-config=/usr/local/php/bin/php-config --with-pdo-mysql=/usr/local/mysql/
      make && make install

    4>ImageMagick
    ImageMagick 是一套功能强大、稳定而且免费的工具集和开发包,可以用来读、写和处理超过89种基本格式的图片文件,包括流行的TIFF, JPEG, GIF, PNG, PDF以及PhotoCD等格式。利用ImageMagick,你可以根据web应用程序的需要动态生成图片, 还可以对一个(或一组)图片进行改变大小、旋转、锐化、减色或增加特效等操作,并将操作的结果以相同格式或其它格式保存。
    ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz
      tar zxvf ImageMagick-6.6.5-10.tar.gz
      cd ImageMagick-6.6.5-10
      ./configure
      make && make install

    5>imagick
    imagick 是PHP的一个扩展程序,它是默认的GD图象函数库的绝佳替代方案。面向对象的PHP编程使用非常方便。
    imagick 默认并没有在PHP的安装包里,需要去PHP网站上下载,并在PHP.INI中打开此扩展。
    http://pecl.php.net/get/imagick-3.0.1.tgz 或者
    http://pecl.php.net/get/imagick-3.0.0.tgz
      tar zxvf imagick-3.0.0.tgz
      cd imagick-3.0.0
      /usr/local/php/bin/phpize
      ./configure --with-php-config=/usr/local/php/bin/php-config
      make && make install

    6>修改php.ini文件,配置eaccelerator加速PHP
    1、查找/usr/local/php/etc/php.ini中的extension_dir = "./"
    修改extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/"
    并在此行后添加如下几行用于调用上面的扩展模块
    extension = "memcache.so"
    extension = "pdo_mysql.so"
    extension = "imagick.so"
    最后查找output_buffering = Off,修改成output_buffering = On
    2、创建目录/usr/local/eaccelerator_cache
    mkdir /usr/local/eaccelerator_cache
    修改/usr/local/php/etc/php.ini在最后添加如下:
    [eaccelerator]
    zend_extension="/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/eaccelerator.so"
    eaccelerator.shm_size="64"
    eaccelerator.cache_dir=/usr/local/eaccelerator_cache
    eaccelerator.enable="1"
    eaccelerator.optimizer="1"
    eaccelerator.check_mtime="1"
    eaccelerator.debug="0"
    eaccelerator.filter=""
    eaccelerator.shm_max="0"
    eaccelerator.shm_ttl="3600"
    eaccelerator.shm_prune_period="3600"
    eaccelerator.shm_only="0"
    eaccelerator.compress="1"
    eaccelerator.compress_level="9"


    5、配置启用php-cgi
    /usr/sbin/groupadd www
    /usr/sbin/useradd -g www www
    修改php-fpm配置文件(php-fpm是为PHP打的一个FastCGI管理补丁),可以实现平滑变更php.ini配置而无需重启php-cgi
    vim /usr/local/php/etc/php-fpm.conf
    把两处nobody修改成www,并且去掉<--!-->这样的注释,表示使用www启用进程php-cgi
    然后通过 /usr/local/php/sbin/php-fpm start 来启用php-cgi。
    ps -ef |grep php-cgi 可以查看php-cgi进程


    6、配置Nginx支持PHP
    修改Nginx的主配置文件/usr/local/nginx/conf/nginx.conf
    去掉下面代码前面的#号:
    location ~ /.php$ {
                root           html;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
                include        fastcgi_params;
            }
    然后在/usr/local/nginx/html目录下创建index.php文件测试即可

    *******************************************

    对于Nginx还有很多东西可以整理出来,后续在跟大伙分享分享。








    转自:http://www.th7.cn/db/mysql/2011/08/17/12403.shtml


    应用服务器Nginx安装及配置.rar(1.5 MB)
Open Toolbar