搭建好LNMP环境之后,接着要考虑的就是整个系统的并发能力了。

一、Nginx的配置

Nginx有很好的并发能力。但是要想使它的并发能力能够施展出来,需要在初步安装好的Nginx上做一些配置。主要需要修改的一些配置有:

1.nginx进程数,建议按照cpu数目来指定,一般跟cpu核数相同或为它的倍数。

worker_processes 8;

2.为每个进程分配cpu,将上例中8个进程分配到8个cpu。

worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

3.下面这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是系统的最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。

worker_rlimit_nofile 65535;

这个属性对Nginx的并发影响比较直接,如果值太小,会报错 socket() failed (24: Too many open files) while connecting to upstream 。

Nginx 默认的打开文件的数量可以用 cat /proc/`ps -ef | grep nginx|grep -v grep|head -1|awk '{print $2}'`/limits 这个命令查看。

其中 Max open files,就是一个Nginx进程可以打开的最多文件数,它有两个属性很重要 一个是 Soft Limit(软限制),默认1024;另一个是 Hard Limit(硬限制),默认 4096 。

这两个值会限制并发数。如果用默认值,最大并发只能是 1000 左右。所以如果要进一步提高并发,就要对这两个值做修改。

但是,只是在Nginx的配置文件中添加 worker_rlimit_nofile 65535 ;有时候不起作用。还要对其他两个主要的地方做修改:

3.1.1、修改用户进程可打开文件数限制

在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句

柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:

ulimit -n

如果命令执行之后显示的数值满足项目需求,可以不做修改,直接看3.2 的步骤;

但是,对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。

3.1.2、修改/etc/security/limits.conf文件,在文件中添加如下行,修改Linux系统对用户的关于打开文件数的软限制和硬限制:

* soft nofile 65533
    * hard nofile 65533

其中*号表示修改所有用户的限制;如果要修改指定的某个用户,把*换成具体的用户名就可以了,例如 nginx soft nofile 65533,soft或hard指定要修改软限制还是硬限制;65533则指定了想要修改的新的

限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。

3.1.3、修改/etc/pam.d/login文件,在文件中添加如下行:

session required /lib/security/pam_limits.so
    如果是64bit系统的话,应该为 :
  session required /lib64/security/pam_limits.so

这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会

从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。

3.1.4、查看Linux系统级的最大打开文件数限制,使用如下命令:

cat /proc/sys/fs/file-max

这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)的文件数,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统

硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/sysctl.conf文件,在文件中

添加如下行

fs.file-max = 70001

3.1.5、执行sysctl命令:

sysctl -p

修改到这一步,用命令查看,Nginx的 Max open files,可能值还是没有变化。这就需要我们接着修改 nginx.service

3.2.1、查找nginx.service

rpm -qal |grep nginx.service

3.2.2、修改 nginx.service,在其中添加:

[Service]
   LimitNOFILE=100000

3.2.3、重启服务。

sudo systemctl daemon-reload

修改到这儿,可以看到(grep 'open files' /proc/$( cat /var/run/nginx.pid )/limits)Nginx 的 Soft Limit 和 Hard Limit 都发生了变化,而且配置中的 worker_rlimit_nofile 65535; 也开始起了作用。我们接着配置Nginx其他属性:

4.使用epoll的I/O模型,用这个模型来高效处理异步事件

use epoll;

5.每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为worker_processes*worker_connections。

worker_connections 65535;

6.可以让sendfile()发挥作用。sendfile()可以在磁盘和TCP socket之间互相拷贝数据(或任意两个文件描述符)。Pre-sendfile是传送数据之前在用户空间申请数据缓冲区。之后用read()将数据从文件拷贝到这个缓冲区,write()将缓冲区数据写入网络。sendfile()是立即将数据从磁盘读到OS缓存。因为这种拷贝是在内核完成的,sendfile()要比组合read()和write()以及打开关闭丢弃缓冲更加有效。

sendfile on;

7.告诉Nginx在一个数据包里发送所有头文件,而不一个接一个的发送。就是说数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞。

tcp_nopush on;

8.告诉Nginx不要缓存数据,而是一段一段的发送--当需要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能立即得到返回值。

tcp_nodelay on;

9.由于Nginx对每一个请求都会写log,这样会浪费时间,可以把日志注释

#access_log  /var/log/nginx/access.log  main;
    access_log off;

或者,添加缓存

access_log  /var/log/nginx/access.log  main buffer=32k;

10.接收FastCGI应答的超时时间,这个值是指已经完成两次握手后接收FastCGI应答的超时时间,有时候Nginx的错误日志中会报错 Upstream timed out (110: Connection timed out) while reading response header from upstream ,可以尝试把这个值改大解决。

fastcgi_read_timeout 300;

下面是一个使用的简单的nginx配置文件:

user nginx;
  worker_processes 8;
  worker_rlimit_nofile 10240;
  worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
  error_log /var/log/nginx/error.log;
  pid /run/nginx.pid;

 # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
  include /usr/share/nginx/modules/*.conf;

  events {
      use epoll;
      worker_connections 10240;
    }

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

     access_log  /var/log/nginx/access.log  main buffer=32k;

     sendfile            on;
     tcp_nopush          on;
     tcp_nodelay         on;
     keepalive_timeout   65;
     types_hash_max_size 2048;

     include             /etc/nginx/mime.types;
     default_type        application/octet-stream;

     fastcgi_connect_timeout 300;
     fastcgi_send_timeout 300;
     fastcgi_read_timeout 300;
     fastcgi_buffer_size 128k;
     fastcgi_buffers 4 128k;
     fastcgi_busy_buffers_size 256k;
     fastcgi_temp_file_write_size 256k;             

     # Load modular configuration files from the /etc/nginx/conf.d directory.
     # See http://nginx.org/en/docs/ngx_core_module.html#include
     # for more information.
     include /etc/nginx/conf.d/*.conf;

     
   server {
    listen       80 default backlog=5000;
    server_name  baidu.com;
    root         /usr/share/nginx/html/baidu;
    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;
    client_max_body_size 1024M;
    client_body_buffer_size 200000k;
    location / {
     index index.php;
     if (!-e $request_filename) {
       rewrite  ^(.*)$  /index.php?s=$1  last;
       break;
          }   

    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

 }

重启 nginx:

sudo systemctl restart nginx