Nginx常用命令

  1. 验证nginx配置文件是否正确

    1. nginx -t
  2. 重新加载配置|重启|停止|退出

    1. nginx -s reload|reopen|stop|quit
  3. 查看版本号

    1. nginx -v #查看版本
    2. nginx -V #查看版本,以及配置文件地址
  4. 指定加载配置文件

    1. nginx c filename

    例:nginx ‐c /usr/local/etc/nginx/nginx.conf //启动时加载指定nginx.conf文件

  5. 查看帮助

    1. nginx -h

    Nginx的高并发原理

    Nginx 采用的是多进程(单线程) & 多路IO复用模型。使用了 I/O 多路复用技术的 Nginx,就成了”并发事件驱动“的服务器。其实现了异步,非阻塞,使用了epoll 和大量的底层代码优化。
    如果一个server采用一个进程负责一个request的方式,那么进程数就是并发数。正常情况下,会有很多进程一直在等待中。
    而nginx采用一个master进程,多个woker进程的模式。

  • master进程主要负责收集、分发请求。每当一个请求过来时,master就拉起一个worker进程负责处理这个请求。
  • 同时master进程也负责监控woker的状态,保证高可靠性
  • woker进程一般设置为跟cpu核心数一致。nginx的woker进程在同一时间可以处理的请求数只受内存限制,可以处理多个请求。
  • Nginx 的异步非阻塞工作方式正把当中的等待时间利用起来了。在需要等待的时候,这些进程就空闲出来待命了,因此表现为少数几个进程就解决了大量的并发问题。

image.png
每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向上游(后端)服务器转发request,并等待请求返回。那么,这个处理的worker很聪明,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。此时,如果再有request 进来,他就可以很快再按这种方式处理。而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。

为什么Nginx不使用多线程?

Apache: 创建多个进程或线程,而每个进程或线程都会为其分配 cpu 和内存(线程要比进程小的多,所以worker支持比perfork高的并发),并发过大会耗光服务器资源。

Nginx: 采用单线程来异步非阻塞处理请求(管理员可以配置Nginx主进程的工作进程的数量)(epoll),不会为每个请求分配cpu和内存资源,节省了大量资源,同时也减少了大量的CPU的上下文切换。所以才使得Nginx支持更高的并发。

Nginx配置调优策略

  1. 调整worker_processes指定Nginx需要创建的worker进程数量,worker进程数一般设置为和CPU核心数一致。

查看系统中的CPU核心数命令:

  1. 逻辑CPU个数:
  2. grep processor /proc/cpuinfo | wc -l
  3. 物理CPU个数:
  4. grep "physical id" /proc/cpuinfo | sort | uniq | wc -l
  5. 每个物理CPUCore的个数:
  6. grep "cpu cores" /proc/cpuinfo | wc -l
  1. 调整worker_connections设置Nginx最多可以同时服务的客户端数,结合worker_processes配置可以获得每秒可以服务的最大客户端数,配置一个worker进程能并发处理(发起)的最大连接数(包含所有连接数),不能超过最大文件打开数。在linux终端中输入ulimit -n查看一个进程能打开的最大文件数

最大客户端连接数计算公式:
max_clients = worker_processes * worker_connections
nginx即可以作为服务器使用,又可以作为反向代理使用,nginx能处理客户端最大连接数的计算公式如下:
nginx作为http服务器的时候:
max_clients = worker_processes * worker_connections/2
nginx作为反向代理服务器的时候:
max_clients = worker_processes * worker_connections/4

  1. 启动gzip压缩,网页在服务器端经过了gzip或者其他格式的压缩后的输出明显减少了content-length字节,当访问过百万时,这些减少的字节就会变为客观的流量给节约下来;从而减轻服务器的压力以及大幅度提升网页的访问速度。

原理
客户端在向服务端发送http请求时,在请求头中有一个Accept-Encoding的头信息,该头信息告知服务器端本客服端能接收什么样的压缩文件,如果服务器端配置了压缩的需求,就会返回相应的压缩文件,然后浏览器再解码呈现出来;我们在做采集时,需要采集的是未压缩的文件,所以在http请求头上不要包含Accept-Encoding的键。
配置说明

  1. gzip on|off; #是否开启gzip
  2. gzip_buffers 32 4K| 16 8K #缓冲(压缩在内存中缓冲几块? 每块多大?)
  3. gzip_comp_level [1-9] #推荐6 压缩级别(级别越高,压的越小,越浪费CPU计算资源)
  4. gzip_disable #正则匹配UA 什么样的Uri不进行gzip
  5. gzip_min_length 1k # 开始压缩的最小长度(再小就不要压缩了,意义不在)
  6. gzip_http_version 1.0|1.1 # 开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议)
  7. gzip_proxied # 设置请求者代理服务器,该如何缓存内容
  8. gzip_types text/plain application/xml # 对哪些类型的文件用压缩 如txt,xml,html ,css
  9. gzip_vary on|off # 是否传输gzip压缩标志

示例配置

  1. gzip on; #开启或关闭gzip on off
  2. gzip_static on; #是否开启gzip静态资源
  3. gzip_buffers 4 16k;#缓冲(压缩在内存中缓冲几块? 每块多大?)
  4. gzip_min_length 1k; #gzip压缩最小文件大小,超出进行压缩(自行调节)
  5. gzip_comp_level 6; #压缩级别:1-10,数字越大压缩的越好,时间也越长
  6. gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;# 压缩文件类型
  7. gzip_vary on; #跟Squid等缓存服务有关,on的话会在Header里增加 "Vary: Accept-Encoding"
  8. gzip_proxied expired no-cache no-store private auth;
  9. gzip_disable "MSIE [1-6]\."; #不进行gzipd的规则

画外音

  • 图片/mp3这样的二进制文件,不必压缩,因为压缩率比较小, 比如100->80字节,而且压缩也是耗费CPU资源的。
  • 比较小的文件不必压缩,意义不存在。
    1. 为静态文件启用缓存,如果请求静态资源,启用缓存是可以大幅度提升性能的.

原理
这里的缓存控制主要是针对图片,css,js等变化周期较短的静态文件;以图片为例,当我们第一次访问这张图片时,服务器返回的是200,同时在响应头返回了两个键,Etag:即该文件的’指纹’(唯一标识)以及Last-Modified:’文件的修改时间’;此时浏览器,以及其他的缓存服务器就会把这张图片给缓存起来;再次请求这张图片时,请求头增加了两个键值,If-Modified-Since:上次发生改变的时间;If-None-Match:上次文件本身的Etag值,服务器根据这两个键值判断其Etag和Last-Modified,如果都没发生改变就不返回这张图片,只返回一个304的状态码,服务器接收到这个304的状态码就会自己去从缓存里面找这个被缓存的图片,这样就减少了服务器的带宽压力以及提升了网站访问速度。
示例配置

  1. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  2. {
  3. expires 30d;
  4. }
  5. location ~ .*\.(js|css)?$
  6. {
  7. expires 12h;
  8. }
  1. 调整timeouts,单位默认S

keepalive连接减少了打开和关闭连接所需的CPU和网络开销,获得最佳性能需要调整的变量:

  1. client_body_timeout 12;
  2. client_header_timeout 12;
  3. keepalive_timeout 15;
  4. send_timeout 10;
  1. 禁用access_log

访问日志记录,它记录每个nginx请求,因此消耗了大量CPU资源,从而降低了nginx性能。

  1. access\_log off;

如果必须具有访问日志记录,则启用访问日志缓冲:

  1. access\_log /var/log/nginx/access.log主缓冲区= 16k
  1. FastCGI调优

    Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。

    1. fastcgi_connect_timeout 600;
    2. fastcgi_send_timeout 600;
    3. fastcgi_read_timeout 600;
    4. fastcgi_buffer_size 64k;
    5. fastcgi_buffers 4 64k;
    6. fastcgi_busy_buffers_size 128k;
    7. fastcgi_temp_file_write_size 128k;
    8. fastcgi_temp_path/usr/local/nginx1.10/nginx_tmp;
    9. fastcgi_intercept_errors on;
    10. fastcgi_cache_path/usr/local/nginx1.10/fastcgi_cache levels=1:2 keys_zone=cache_fastcgi:128minactive=1d max_size=10g;

    fastcgi_connect_timeout指定连接到后端FastCGI的超时时间。
    fastcgi_send_timeout指定向FastCGI传送请求的超时时间,这个值是已经完成两次握手后向FastCGI传送请求的超时时间。
    fastcgi_read_timeout指定接收FastCGI应答的超时时间,这个值是已经完成两次握手后接收FastCGI应答的超时时间。
    fastcgi_buffer_size用于指定读取FastCGI应答第一部分需要用多大的缓冲区,这个值表示将使用1个64KB的缓冲区读取应答的第一部分(应答头),可以设置为fastcgi_buffers选项指定的缓冲区大小。
    fastcgi_buffers指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求。如果一个PHP脚本所产生的页面大小为256KB,那么会为其分配4个64KB的缓冲区来缓存;如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于硬盘。一般这个值应该为站点中PHP脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“16 16k”、“4 64k”等。
    fastcgi_busy_buffers_size的默认值是fastcgi_buffers的两倍。
    fastcgi_temp_file_write_size表示在写入缓存文件时使用多大的数据块,默认值是fastcgi_buffers的两倍。
    fastcgi_cache表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502错误的发生,但是开启缓存也会引起很多问题,要视具体情况而定。
    fastcgi_cache_valid、fastcgi用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存一个小时,将301应答缓存1天,其他应答均缓存1分钟。

    Nginx常用配置

    根据文件类型设置过期时间

    ``` location ~.*.css$ { expires 1d; break; }

location ~.*.js$ { expires 1d; break; }

location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ { access_log off; expires 15d; #保存15天 break; }

  1. <a name="dfrYX"></a>
  2. #### 静态资源访问

http {

  1. # 这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,
  2. # 建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
  3. open_file_cache max=204800 inactive=20s;
  4. # open_file_cache 指令中的inactive 参数时间内文件的最少使用次数,
  5. # 如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个
  6. # 文件在inactive 时间内一次没被使用,它将被移除。
  7. open_file_cache_min_uses 1;
  8. # 这个是指多长时间检查一次缓存的有效信息
  9. open_file_cache_valid 30s;
  10. # 默认情况下,Nginx的gzip压缩是关闭的, gzip压缩功能就是可以让你节省不
  11. # 少带宽,但是会增加服务器CPU的开销哦,Nginx默认只对text/html进行压缩 ,
  12. # 如果要对html之外的内容进行压缩传输,我们需要手动来设置。
  13. gzip on;
  14. gzip_min_length 1k;
  15. gzip_buffers 4 16k;
  16. gzip_http_version 1.0;
  17. gzip_comp_level 2;
  18. gzip_types text/plain application/x-javascript text/css application/xml;
  19. server {
  20. listen 80;
  21. server_name www.test.com;
  22. charset utf-8;
  23. root /data/www.test.com;
  24. index index.html index.htm;
  25. }

}

  1. <a name="dfOji"></a>
  2. #### access_log 访问日志

http { log_format access ‘$remote_addr - $remote_user [$time_local] $host “$request” ‘ ‘$status $body_bytes_sent “$http_referer” ‘ ‘“$http_user_agent” “$http_x_forwarded_for” “$clientip”‘; access_log /srv/log/nginx/talk-fun.access.log access; }

  1. <a name="nBgwh"></a>
  2. #### error_log 日志

error_log /srv/log/nginx/nginx_error.log error;

error_log /dev/null; # 真正的关闭错误日志

http {

  1. # ...

}

  1. <a name="j8yQY"></a>
  2. #### 日志切割

和apache不同的是,nginx没有apache一样的工具做切割,需要编写脚本实现。# 在/usr/local/sbin下写脚本

!/bin/bash

dd=$(date -d ‘-1 day’ +%F)[ -d /tmp/nginx_log ] || mkdir /tmp/nginx_log mv /tmp/nginx_access.log /tmp/nginx_log/$dd.log /etc/init.d/nginx reload > /dev/null

  1. <a name="V8SyV"></a>
  2. #### 反向代理<br />

http { include mime.types; server_tokens off;

  1. ## 配置反向代理的参数
  2. server {
  3. listen 8080;
  4. ## 1. 用户访问 http://ip:port,则反向代理到 https://github.com
  5. location / {
  6. proxy_pass https://github.com;
  7. proxy_redirect off;
  8. proxy_set_header Host $host;
  9. proxy_set_header X-Real-IP $remote_addr;
  10. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  11. }
  12. ## 2.用户访问 http://ip:port/README.md,则反向代理到
  13. ## https://github.com/zibinli/blog/blob/master/README.md
  14. location /README.md {
  15. proxy_set_header X-Real-IP $remote_addr;
  16. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  17. proxy_pass https://github.com/zibinli/blog/blob/master/README.md;
  18. }
  19. }

}

  1. <a name="CpxoF"></a>
  2. #### 禁止指定user_agent

禁止useragent为baidu、360和sohu,~*表示不区分大小写匹配

if ($http_user_agent ~* ‘baidu|360|sohu’) { return 403; }

  1. <a name="DpUYI"></a>
  2. #### nginx访问控制

可以设置一些配置禁止一些ip的访问

deny 127.0.0.1; #全局定义限制,location里的是局部定义的。如果两者冲突,以location这种精确地优先,

location ~ .*admin.php$ {

  1. #auth_basic "cct auth";
  2. #auth_basic_user_file /usr/local/nginx/conf/.htpasswd;
  3. allow 127.0.0.1; 只允许127.0.0.1的访问,其他均拒绝
  4. deny all;
  5. include fastcgi_params;
  6. fastcgi_pass unix:/tmp/www.sock;
  7. fastcgi_index index.php;
  8. fastcgi_param SCRIPT_FILENAME /data/www$fastcgi_script_name;

}

  1. <a name="si4LD"></a>
  2. #### 负载均衡

http { upstream test.net { ip_hash; server 192.168.10.13:80; server 192.168.10.14:80 down; server 192.168.10.15:8009 max_fails=3 fail_timeout=20s; server 192.168.10.16:8080; } server { location / { proxy_pass http://test.net; } } }

  1. <a name="TbZNH"></a>
  2. #### 防盗链

location ~* .(gif|jpg|png)$ {

  1. # 只允许 192.168.0.1 请求资源
  2. valid_referers none blocked 192.168.0.1;
  3. if ($invalid_referer) {
  4. rewrite ^/ http://$host/logo.png;
  5. }

}

  1. <a name="lZanh"></a>
  2. #### 禁止文件缓存

location ~* .(js|css|png|jpg|gif)$ { add_header Cache-Control no-store; }

  1. <a name="m229l"></a>
  2. #### 指定错误页面

根据状态码,返回对于的错误页面

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

  1. <a name="CbOwx"></a>
  2. #### 跨域问题
  3. > <a name="vf6v3"></a>
  4. #### 跨域的定义
  5. > 同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。通常不允许不同源间的读操作。
  6. > <a name="ESF82"></a>
  7. #### 同源的定义
  8. > 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
  9. **nginx解决跨域的原理**<br />例如:
  10. - 前端server域名为:http://xx_domain
  11. - 后端server域名为:https://github.com
  12. 现在http://xx_domain对https://github.com发起请求一定会出现跨域。<br />不过只需要启动一个nginx服务器,将server_name设置为xx_domain,然后设置相应的location以拦截前端需要跨域的请求,最后将请求代理回github.com。如下面的配置:

配置反向代理的参数

server { listen 8080; server_name xx_domain

  1. ## 1. 用户访问 http://xx_domain,则反向代理到 https://github.com
  2. location / {
  3. proxy_pass https://github.com;
  4. proxy_redirect off;
  5. proxy_set_header Host $host; # 传递域名
  6. proxy_set_header X-Real-IP $remote_addr; # 传递ip
  7. proxy_set_header X-Scheme $scheme; # 传递协议
  8. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9. }

}

  1. 这样可以完美绕过浏览器的同源策略:github.com访问nginxgithub.com属于同源访问,而nginx对服务端转发的请求不会触发浏览器的同源策略。
  2. <a name="CDtnp"></a>
  3. #### 乱码处理

server { listen 80; server_name example.com; root /var/www/example;

location / { charset utf‐8; #一般是在个别的location中加入此项,具体情况具体对待 rewrite .* /index.html break; } }

  1. <a name="e2pXj"></a>
  2. #### 开启目录浏览功能
  3. Nginx默认是不允许列出整个目录的。如需此功能,打开nginx.conf文件,在location server 或 http段中加入

autoindex on;

  1. 另外还有两个参数最好也加上去

autoindex_exact_size off;

  1. 默认为on,显示出文件的确切大小,单位是bytes。<br />改为off后,显示出文件的大概大小,单位是kB或者MB或者GB

autoindex_localtime on;

  1. 默认为off,显示的文件时间为GMT时间。<br />改为on后,显示的文件时间为文件的服务器时间
  2. <a name="CRqTB"></a>
  3. #### 常见错误码和解决方案
  4. 400 bad request错误的原因和解决办法 配置nginx.conf相关设置如下.

client_header_buffer_size 16k; large_client_header_buffers 4 64k;

  1. 根据具体情况调整,一般适当调整值就可以。<br />Nginx 502 Bad Gateway错误

proxy_next_upstream error timeout invalid_header http_500 http_503;

  1. 或者尝试设置:

large_client_header_buffers 4 32k;

  1. Nginx出现的413 Request Entity Too Large错误<br />这个错误一般在上传文件的时候会出现,<br />编辑Nginx主配置文件Nginx.conf,找到http{}段,添加

client_max_body_size 10m; //设置多大根据自己的需求作调整.

  1. 如果运行php的话这个大小client_max_body_size要和php.ini中的如下值的最大值一致或<br />者稍大,这样就不会因为提交数据大小不一致出现的错误。

post_max_size = 10M upload_max_filesize = 2M

  1. 解决504 Gateway Time-out(nginx)<br />遇到这个问题是在升级discuz论坛的时候遇到的<br />一般看来, 这种情况可能是由于nginx默认的fastcgi进程响应的缓冲区太小造成的, 这将导致<br />fastcgi进程被挂起, 如果你的fastcgi服务对这个挂起处理的不好, 那么最后就极有可能导致<br />504 Gateway Time-out<br />现在的网站, 尤其某些论坛有大量的回复和很多内容的, 一个页面甚至有几百K。<br />默认的fastcgi进程响应的缓冲区是8K, 我们可以设置大点<br />在nginx.conf里, 加入:

fastcgi_buffers 8 128k

  1. 这表示设置fastcgi缓冲区为8×128k<br />当然如果您在进行某一项即时的操作, 可能需要nginx的超时参数调大点,例如设置成60<br />秒:

send_timeout 60;

``` 只是调整了这两个参数, 结果就是没有再显示那个超时, 可以说效果不错, 但是也可能是由于
其他的原因, 目前关于nginx的资料不是很多, 很多事情都需要长期的经验累计才有结果。

https://segmentfault.com/a/1190000039873208/