Nginx使用经验总结,好记性不比烂笔头(键盘)

基础知识

  1.  配置文件中以#开始的行,或者是前面有若干空格或者 TAB,然后再跟#的行,都被认为是注释
  2. 在 nginx.conf 中,包含若干配置项。每个配置项由配置指令和指令参数 2 个部分构成。指令参数也就是配置指令对应的配置值。
    •  配置指令是一个字符串,可以用单引号或者双引号括起来,也可以不括。但是如果配置指令包含空格,一定要引起来。
    • 指令的参数使用一个或者多个空格或者 TAB 字符与指令分开。指令的参数有一个或者多个 TOKEN 串组成。TOKEN 串之间由空格或者 TAB 键分隔。
    • 这个是一个简单配置项:error_page 500 502 503 504 /50x.html;
  3. 使用if指令时,if和{}中间需要一个空格;

Server语句

每个虚拟主机一个对应的 server 配置项,配置项里面包含该虚拟主机相关的配置。在提供 mail 服务的代理时,也可以建立若干 server,每个 server 通过监听的地址来区分。

  • listen,用于指定虚拟机的监听端口(listen 80;)
  • index,用于指定是首页文件(index index.html index.htm index.php;)
  • root,用于指定虚拟机目录(root /data/www/w3cschool;)
  • location,用于对收到的不同的链接的请求进行不同的处理,如下是设定指定类型的链接的请求的过期时间为1小时...
    #JS和CSS缓存时间设置
    location ~ .*.(js|css)?$
    {
        expires 1h;
    }
    #定义访问php脚本时,将会执行本location{}部分指令
    location ~ .php$ {
        proxy_pass   http://127.0.0.1;  //proxy_pass后面指定要访问的url链接,用proxy_pass实现代理。
    }
    
  • access_log,指定网站访问日志的存储路径,log_format 指令用于设置日志的记录格式,值为Off则关闭。
  • error_page,当出现指定状态码是时,返回指定页面(error_page 500 502 503 504 /50x.html; //当状态码为500、502、503、504时,则访问50x.html

SSL相关配置

### 以下为ssl相关配置
ssl_certificate      cert.pem;    //指定pem文件路径
ssl_certificate_key  cert.key;  //指定key文件路径
ssl_session_cache    shared:SSL:1m;  //指定session cache大小
ssl_session_timeout  5m;  //指定session超时时间
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   //指定ssl协议
ssl_ciphers  HIGH:!aNULL:!MD5;  //指定ssl算法
ssl_prefer_server_ciphers  on;  //优先采取服务器算法s

全局变量

  1. $args,$query_string  请求中的参数,如www.123.com/1.php?a=1&b=2的$args就是a=1&b=2
  2. $content_length  http请求信息里面的“Content-Length”
  3. $conten_type  http请求信息里面的“Content-Type”
  4. $document_root  nginx虚拟主机配置文件中的root参数对应的值
  5. $document_uri  当前请求中不包含指令的URI,如www.123.com/1.php?a=1&b=2的$document_uri就是1.php,不包含后面的参数。
  6. $host  主机头,也就是域名。
  7. $http_user_agent  客户端的详细信息,也就是浏览器的标识。
  8. $http_cookie  客户端的cookie信息
  9. $limit_rate  如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置,则显示为0.
  10. $remote_addr  客户端的公网ip
  11. $remote_port  客户端的port
  12. $remote_user  如果nginx有配置认证,该变量代表客户端认证的用户名
  13. $request_body_file  做反向代理时发给后端服务器的本地资源的名称
  14. $request_uri  请求的连接,包括$document_uri和$args
  15. $request_method 请求的方法,GET、POST等
  16. $scheme  请求的协议,如ftp,http,https
  17. $server_protocol  客户端请求资源用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0
  18. $server_addr  服务器ip地址
  19. $server_name  服务器的主机名
  20. $server_port  服务器的端口号
  21. $uri  和$document_uri相同
  22. $http_referer  客户端请求时的referer,通俗讲就是该请求时通过哪个连接跳进来的,也就是我们在百度搜一个关键字,然后可以点击条目跳进一个网站,点击的那个链接就是你的referer,用curl -e可以指定。

IF语句

提示
可以使用 =、!= 比较字符串是否相等,进行比较时字符串不需要加引号,IF跟括号之间必须有一个空格。

在server和location两种配置块内可以使用nginx的IF条件判断,当条件成立时执行指定的指令,条件可以为以下几种:

1.正则表达式

# ~ 为区分大小写匹配;
# ~* 为不区分大小写匹配;
# !~ 不匹配某个区分大小写的正则;
# !~* 不匹配某个不区分大小写的正则;
#下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下: 
if ($http_user_agent ~ MSIE) { 
     rewrite ^(.*)$ /nginx-ie/$1 break;
 }

整个正则表达式字符串一般不需要加引号但如果含有右花括号}或者分号;字符时必须要给整个正则表达式添加引号

2.文件目录匹配

#-f和!-f判断是否存在文件
# -d和!-d判断是否存在目录
#-e和!-e判断是否存在文件或目录
#-x和!-x判断文件是否可执行
#设定nginx在文件和目录不存在的时候重定向:
if (!-e $request_filename) {
  proxy_pass http://127.0.0.1/;
}

Return语句

该指令一般用于对请求的客户端直接返回响应状态码。在该作用域内return后面的所有nginx配置都是无效的。 可以使用在server、location以及if配置中。 除了支持跟状态码,还可以跟字符串或者url链接,该语句只会影响当前所在的代码块。

#301重定向,直接带server块内使用,后面的所有指令都不会执行
return 301 https://nicen.cn$request_uri;
#输出HTML也行
return 200 "<html><script>window.location.href='//$host$request_uri';</script></html>";

Deny语句

Deny用于拒绝访问,可在sever和location中使用

deny all; #拒绝访问
allow 208.97.167.194; #允许指定IP访问

Rewrite 命令

  1. 它可以用在server, location 和IF条件判断块中,格式为:rewrite 正则表达式 替换目标 flag标记
  2. flag标记可以用以下几种格式
    last – 停止当前这个请求,并根据rewrite匹配的规则重新发起一个请求。新请求又从第一阶段开始执行…
    break – 中止Rewirte,不在继续匹配,相对last,break并不会重新发起一个请求,只是跳过当前的rewrite阶段,并执行本请求后续的执行阶段…
    redirect – 重定向到指定的链接,返回临时重定向的HTTP状态302
    permanent – 重定向到指定的链接,返回永久重定向的HTTP状态301

Set语句

set 指令是用于定义一个变量,并且赋值,可在server、location、if代码块中使用。

Nginx配置文件中文详解:https://www.w3cschool.cn/nginx/nginx-d1aw28wa.html

try_files命令

try_files是nginx中http_core核心模块所带的指令,主要是能替代一些rewrite的指令,提高解析效率。

  1. 它可以用在server, location 和IF条件判断块中,格式为:rewrite 正则表达式 替换目标 flag标记
  2. 按指定的file顺序查找存在的文件,并使用第一个找到的文件进行请求处理,如果给出的file都没有匹配到,则重新请求最后一个参数给定的uri,就是新的location匹配;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ .*.(php|php5)?$
    {
        fastcgi_pass  127.0.0.1:9000;
         fastcgi_index index.php;
    }
    

    当用户请求 http://localhost/example 时,这里的 $uri 就是 /example。

    try_files 会到硬盘里尝试找这个文件。如果存在名为 /root/example(其中root 是项目代码安装目录)的文件,就直接把这个文件的内容发送给用户。

    显然,目录中没有叫 example 的文件。然后就看 uri/,增加了一个 /,也就是看有没有名为 /root/example/ 的目录。

    又找不到,就会 fall back 到 try_files 的最后一个选项 /index.php,发起一个内部 “子请求”,也就是相当于 nginx 发起一个 HTTP 请求到 http://localhost/index.php

    这个请求会被 location ~ .*.(php|php5)?$ { ... } catch 住,也就是进入 FastCGI 的处理程序。而具体的 URI 及参数是在 REQUEST_URI 中传递给 FastCGI 和 PHP 程序的,因此不受 URI 变化的影响。

break命令

该指令用于中断当前相同作用域中的其他 Nginx 配置

与该指令处于同一作用域的 Nginx 配置中位于它前面的指令配置生效位于后面的指令配置无效

Nginx 服务器在根据配置处理请求的过程中遇到该指令时回到上一层作用域继续向下读取配置该指令可以在 server 块和 location 块以及 if 块中使用其语法结构为:break;

问题总结

  1. location的匹配存在优先级的问题,前面比后面先匹配;绝对比正则先匹配。往往重写不生效时就是没有匹配到指定的块。(例如重写一个PHP文件的请求时,在PHP-CGI块的后面,所以一直返回404)。
  2. 修改配置文件后,一定要重启NGINX。

正向代理和反向代理

在Nginx的环境下,通过不同协议访问时可代理http、https等不同的协议。

正向代理:局域网的主机访问互联网的资源;(proxy_pass指令,目标为外网地址)

反向代理:互联网主机访问局域网内某台主机的资源(proxy_pass指令,目标为局域网地址)。

反向代理websocket时,默认情况下,如果代理服务器在 60 秒内没有传输任何数据,连接将被关闭。

1.proxy_hide_header field  指令

其中,field为需要隐藏的头域。该指令可以在 http 块、server 块或者 location 块中进行配置。

2.proxy_pass_header field 指令

默认情况下,Nginx 服务器在发送响应报文时,报文头中不包含「Date」、「Server」、「X-Accel」等来自被代理服务器的头域信息。该指令可以设置这些头域信息以被发送,其语法结构为:

3.proxy_pass_request_body 指令

该指令用于配置是否将客户端请求的请求体发送给代理服务器,其语法结构为: proxy_pass_request_body on|off;默认设置为开启(on),开关可以在 http 块、server 块或者 location 块中进行配置。

4.proxy_pass_request_headers on|off

该指令用于配置是否将客户端请求的请求头发送给代理服务器,其语法结构为:

5.proxy_set_header  field value 指令

该指令可以更改 Nginx 服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给被代理的服务器,field为指定的字段,value为字段值。

6.proxy_set_body value

该指令可以更改 Nginx 服务器接收到的客户端请求的请求体信息,然后将新的请求体发送给被代理的服务器;

7.proxy_bind address

官方文档中对该指令的解释是,强制将与代理主机的连接绑定到指定的 IP 地址,通俗来讲就是,在配置了多个基于名称或者基于 IP 的主机的情况下,如果我们希望代理连接由指定的主机处理,就可以使用该指令进行配置,address为指定的IP;

8.proxy_connect_timeout time

指令,该指令配置 Nginx 服务器与后端被代理服务器尝试建立连接的超时时间。默认为60s;

9.proxy_read_timeout time

该指令配置 Nginx 服务器向后端被代理服务器组发出 read 请求后等待响应的超时时间,time默认为60s;

10.proxy_send_timeout time

该指令配置 Nginx 服务器向后端被代理服务器组发出 write 请求后等待响应的超时时间,time默认为60s;

11.proxy_http_version version

该指令用于设置用于 Nginx 服务器提供代理服务的 HTTP 协议版本,默认设置为 1.0 版本,1.1 版本支持 upsteam 服务器组设置中的 keepalive 指令;

12.proxy_method method

该指令用于设置 Nginx 服务器请求被代理服务器时使用的请求方法,一般为 POST 或者 GET。设置了该指令,客户端的请求方法将被忽略。

13.proxy_ignore_client_abort on | off

该指令用于设置在客户端中断网络请求时,Nginx 服务器是否中断对被代理服务器的请求,默认设置为 off,当客户端中断网络请求时,Nginx 服务器中断对被代理服务器的请求。

14.proxy_ignore_headers field ...

该指令用于设置一些 HTTP 响应头中的头域,Nginx 服务器接收到被代理服务器的响应数据后,不会处理被设置的头域。其中,field为要设置的 HTTP 响应头的头域,例如「X-Accel-Redirect」、「X-Accel-Expires」、「Expires」、「Cache-Control」或「Set-Cookie」等。

15.proxy_redirect 指令

该指令用于修改被代理服务器返回的响应头中的 Location 头域和「Refresh」头域,与 proxy_pass 指令配合使用。比如,Nginx 服务器通过 proxy_pass 指令将客户端的请求地址重写为被代理服务器的地址,那么 Nginx 服务器返回给客户端的响应头中「Location」头域显示的地址就应该和客户端发起请求的地址相对应,而不是代理服务器直接返回的地址信息,否则就会出问题。该指令解决了这个问题,可以把代理服务器返回的地址信息更改为需要的地址信息。其语法结构为:

proxy_redirect redirect replacement; 
proxy_redirect default; 
proxy_redirect off;

redirect,匹配「Location」头域值的字符串,支持变量的使用和正则表达式。
replacement,用于替换redirect变量内容的字符串,支持变量的使用。

对于第 1 个结构,>假设被代理服务器返回的响应头中「Location」头域为:

Location: http://localhost:8081/proxy/some/uri/

该指令设置为:

proxy_redirect  http://localhost:8081/proxy/  http://myweb/frontend/;

Nginx 服务器会将「Location」头域的信息更改为:

Location: http://myweb/frontend//some/uri/

这样,客户端收到的响应信息头部中的「Location」头域也就被更改了。

结构 2 使用 default,代表使用 location 块的uri变量作为replacement,并使用 proxy_pass 变量作为redirect。请看下面两段配置,它们的配置效果是等同的。

location /server/
{
    proxy_pass http://proxyserver/source/;
    proxy_redirect default;
}
location /server/
{
    proxy_pass http://proxyserver/source/;
    proxy_redirect http://proxyserver/source/ /server/;
}

使用结构 3 可以将当前作用域下所有的 proxy_redirect 指令配置全部设置为无效。

17.proxy_intercept_errors on | off;

该指令用于配置一个状态是开启还是关闭。在开启该状态时,如果被代理的服务器返回的 HTTP 状态代码为 400 或者大于 400,则 Nginx 服务器使用自己定义的错误页(使用 error_page 指令);如果是关闭该状态,Nginx 服务器直接将被代理服务器返回的 HTTP 状态返回给客户端。

18.proxy_headers_hash_ max _size size

该指令用于配置存放 HTTP 报文头的哈希表的容量,size 为 HTTP 报文头哈希表的容量上限,默认为 512 个字符,即:proxy_headers_hash_ max _size 512;Nginx 服务器为了能够快速检索 HTTP 报文头中的各项信息,比如服务器名称、MIME 类型、请求头名称等,使用哈希表存储这些信息。Nginx 服务器在申请存放 HTTP 报文头的空间时,通常以固定大小为单位申请,该大小由 proxy_headers_hash_bucket_size 指令配置。在 Nginx 配置中,不仅能够配置整个哈希表的大小上限,对大部分的内容项,也可以配置其大小上限,比如 server_names_hash_max_size 指令和 server_names_hash_bucket_size 指令用来设置服务器名称的字符数长度。

19.proxy_headers_hash_bucket_size size;

该指令用于设置 Nginx 服务器申请存放 HTTP 报文头的哈希表容量的单位大小。该指令的具体作用在上面 proxy_headers_hash_max_size 指令的使用中已经说明。size 为设置的容量,默认为 64 个字符。

20.proxy_next_upstream status …;

在配置 Nginx 服务器反向代理功能时,如果使用 upstream 指令配置了一组服务器作为被代理服务器,服务器组中各服务器的访问规则遵循 upstream 指令配置的轮询规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交由下一个组内服务器处理。status为设置的服务器返回状态,可以是一个或者多个。这些状态包括error,在建立连接、向被代理的服务器发送请求或者读取响应头时服务器发生连接错误。
timeout,在建立连接、向被代理的服务器发送请求或者读取响应头时服务器发生连接超时。
invalid_header,被代理的服务器返回的响应头为空或者无效。
http_500 | http_502 | http_503 | http_504 | http_404,被代理的服务器返回 500、502、503、504 或者 404 状态代码。
off,无法将请求发送给被代理的服务器。与被代理的服务器进行数据传输的过程中发送错误的请求,不包含在该指令支持的状态之内。

21.proxy_ssl_session_reuse on | off

该指令用于配置是否使用基于 SSL 安全协议的会话连接(“https://”)被代理的服务器,默认设置为开启(on)状态。如果我们在错误日志中发现「SSL3_GET_FINISHED:digest check failed」的情况,可以将该指令配置为关闭(off)状态。

问题总结

  1. 使用腾讯云CDN时,进行websokect反向代理时,由于cdn链接最多保持10s,将会导致websokect中断。