Nginx

Stone大约 42 分钟

Nginx

注意:

此文档对应的 Nginx 版本为 1.24.0。

概述

Nginxopen in new window 是一个高性能的 HTTP 和反向代理 Web 服务器。

经常用于:

  • 反向代理,将客户端的 HTTP 请求转发到后端服务器进行处理
  • 负载均衡,将客户端的请求分配到多个后端服务器上进行处理
  • Web 服务器,处理静态文件

部署

部署 Nginx 有以下两种方式:

  • YUM 部署:主机可以访问外网
  • 本地部署:主机不能访问外网

下面介绍如何在 CentOS 7open in new window 环境安装 Nginx 1.24.0。

注意:

操作系统建议先关闭防火墙和 SELinux。

YUM 部署

如果主机可以访问外网,直接使用以下命令安装 Nginx:

[root@stone ~]# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
Retrieving http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
warning: /var/tmp/rpm-tmp.yfH9Ko: Header V4 RSA/SHA1 Signature, key ID 7bd9bf62: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:nginx-release-centos-7-0.el7.ngx ################################# [100%]

[root@stone ~]# yum -y install nginx
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: ftp.sjtu.edu.cn
 * updates: ftp.sjtu.edu.cn
base                                                                                                       | 3.6 kB  00:00:00     
extras                                                                                                     | 2.9 kB  00:00:00     
nginx                                                                                                      | 2.9 kB  00:00:00     
updates                                                                                                    | 2.9 kB  00:00:00     
nginx/x86_64/primary_db                                                                                    |  85 kB  00:00:04     
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 1:1.24.0-1.el7.ngx will be installed
--> Processing Dependency: libpcre2-8.so.0()(64bit) for package: 1:nginx-1.24.0-1.el7.ngx.x86_64
--> Running transaction check
---> Package pcre2.x86_64 0:10.23-2.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==================================================================================================================================
 Package                    Arch                        Version                                  Repository                  Size
==================================================================================================================================
Installing:
 nginx                      x86_64                      1:1.24.0-1.el7.ngx                       nginx                      804 k
Installing for dependencies:
 pcre2                      x86_64                      10.23-2.el7                              base                       201 k

Transaction Summary
==================================================================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 1.0 M
Installed size: 3.3 M
Downloading packages:
(1/2): pcre2-10.23-2.el7.x86_64.rpm                                                                        | 201 kB  00:00:01     
(2/2): nginx-1.24.0-1.el7.ngx.x86_64.rpm                                                                   | 804 kB  00:00:09     
----------------------------------------------------------------------------------------------------------------------------------
Total                                                                                             104 kB/s | 1.0 MB  00:00:09     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Warning: RPMDB altered outside of yum.
  Installing : pcre2-10.23-2.el7.x86_64                                                                                       1/2 
  Installing : 1:nginx-1.24.0-1.el7.ngx.x86_64                                                                                2/2 
----------------------------------------------------------------------

Thanks for using nginx!

Please find the official documentation for nginx here:
* https://nginx.org/en/docs/

Please subscribe to nginx-announce mailing list to get
the most important news about nginx:
* https://nginx.org/en/support.html

Commercial subscriptions for nginx are available on:
* https://nginx.com/products/

----------------------------------------------------------------------
  Verifying  : pcre2-10.23-2.el7.x86_64                                                                                       1/2 
  Verifying  : 1:nginx-1.24.0-1.el7.ngx.x86_64                                                                                2/2 

Installed:
  nginx.x86_64 1:1.24.0-1.el7.ngx                                                                                                 

Dependency Installed:
  pcre2.x86_64 0:10.23-2.el7                                                                                                      

Complete!

[root@stone ~]# nginx -v
nginx version: nginx/1.24.0

本地部署

如果主机不能访问外网,需要先在官网open in new window下载 Nginx 安装包,上传到主机后再安装:

[root@stone ~]# ll nginx-1.24.0-1.el7.ngx.x86_64.rpm 
-rw-r--r--. 1 root root 823020 Sep 11 10:48 nginx-1.24.0-1.el7.ngx.x86_64.rpm

[root@stone ~]# yum -y localinstall nginx-1.24.0-1.el7.ngx.x86_64.rpm
Loaded plugins: fastestmirror
Examining nginx-1.24.0-1.el7.ngx.x86_64.rpm: 1:nginx-1.24.0-1.el7.ngx.x86_64
Marking nginx-1.24.0-1.el7.ngx.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 1:1.24.0-1.el7.ngx will be installed
--> Processing Dependency: libpcre2-8.so.0()(64bit) for package: 1:nginx-1.24.0-1.el7.ngx.x86_64
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: ftp.sjtu.edu.cn
 * updates: ftp.sjtu.edu.cn
--> Running transaction check
---> Package pcre2.x86_64 0:10.23-2.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==================================================================================================================================
 Package              Arch                  Version                           Repository                                     Size
==================================================================================================================================
Installing:
 nginx                x86_64                1:1.24.0-1.el7.ngx                /nginx-1.24.0-1.el7.ngx.x86_64                2.8 M
Installing for dependencies:
 pcre2                x86_64                10.23-2.el7                       base                                          201 k

Transaction Summary
==================================================================================================================================
Install  1 Package (+1 Dependent package)

Total size: 3.0 M
Total download size: 201 k
Installed size: 3.3 M
Downloading packages:
pcre2-10.23-2.el7.x86_64.rpm                                                                               | 201 kB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : pcre2-10.23-2.el7.x86_64                                                                                       1/2 
  Installing : 1:nginx-1.24.0-1.el7.ngx.x86_64                                                                                2/2 
----------------------------------------------------------------------

Thanks for using nginx!

Please find the official documentation for nginx here:
* https://nginx.org/en/docs/

Please subscribe to nginx-announce mailing list to get
the most important news about nginx:
* https://nginx.org/en/support.html

Commercial subscriptions for nginx are available on:
* https://nginx.com/products/

----------------------------------------------------------------------
  Verifying  : pcre2-10.23-2.el7.x86_64                                                                                       1/2 
  Verifying  : 1:nginx-1.24.0-1.el7.ngx.x86_64                                                                                2/2 

Installed:
  nginx.x86_64 1:1.24.0-1.el7.ngx                                                                                                 

Dependency Installed:
  pcre2.x86_64 0:10.23-2.el7                                                                                                      

Complete!

[root@stone ~]# nginx -v
nginx version: nginx/1.24.0

管理

可以使用以下命令管理 Nginx:

  • ststemclt
  • nginx

systemctl

部署完成后,Nginx 会注册为服务open in new window,使用 systemctl 命令来进行管理。

启动 Nginx 服务:

[root@stone ~]# systemctl start nginx

配置开机启动 Nginx 服务:

[root@stone ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

查看 Nginx 服务状态:

[root@stone ~]# systemctl status nginx
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2023-09-11 11:04:15 CST; 1min 7s ago
     Docs: http://nginx.org/en/docs/
 Main PID: 2104 (nginx)
   CGroup: /system.slice/nginx.service
           ├─2104 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
           └─2105 nginx: worker process

Sep 11 11:04:15 stone systemd[1]: Starting nginx - high performance web server...
Sep 11 11:04:15 stone systemd[1]: Can't open PID file /var/run/nginx.pid (yet?) after start: No such file or directory
Sep 11 11:04:15 stone systemd[1]: Started nginx - high performance web server.

重载 Nginx 配置文件:

[root@stone ~]# systemctl reload nginx

关闭 Nginx 服务:

[root@stone ~]# systemctl stop nginx

重启 Nginx 服务:

[root@stone ~]# systemctl restart nginx

nginx

除了使用 systemclt 外,还可以使用 nginx 命令进行管理。

[root@stone ~]# nginx -h
nginx version: nginx/1.24.0
Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]
             [-e filename] [-c filename] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /etc/nginx/)
  -e filename   : set error log file (default: /var/log/nginx/error.log)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file

常用选项有:

  • -s signal:发送信号给主进程,包括:

    • stop:发送 SIGTERM 信号,表示快速关闭 Nginx

    • quit:发送 SIGQUIT 信号,表示优雅关闭 Nginx

    • reopen:发送 SIGUSR1 信号,表示重新打开日志文件

    • reload:发送 SIGHUP 信号,表示重载配置文件,使用新配置文件启动新的工作进程,优雅关闭老的工作进程

  • -t:测试配置文件是否正确

  • -c:指定配置文件,默认为 /etc/nginx/nginx.conf

重载配置文件:

[root@stone ~]# nginx -s reload

测试配置文件是否正确:

[root@stone ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

查看配置:

[root@proxy ~]# nginx -V
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

进程

查看 Nginx 对应的进程:

[root@stone ~]# ps -ef | grep nginx | grep -v grep
root       2174      1  0 11:11 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx      2175   2174  0 11:11 ?        00:00:00 nginx: worker process

可以看到 Nginx 的进程包括主进程和工作进程:

  • 主进程(master process):在 Nginx 启动时运行,主要负责读取配置文件并验证其有效性和正确性、建立和关闭 Socket、生成、管理和结束工作进程、接收外界指令,如重启、重载以及退出服务器等指令、实现平滑重启和应用新配置、开启日志文件、获取文件描述符以及编译和处理 Perl 脚本等功能。主进程以 root 用户身份运行。
  • 工作进程(worker process):由主进程生成,数量可以通过 Nginx 配置文件指定,正常情况下生存于主进程的整个生命周期。工作进程主要负责处理用户的请求,进行事件处理和 I/O 操作等。

目录结构

Nginx 的目录结构如下:

[root@stone ~]# rpm -ql nginx
/etc/logrotate.d/nginx
/etc/nginx
/etc/nginx/conf.d
/etc/nginx/conf.d/default.conf
/etc/nginx/fastcgi_params
/etc/nginx/mime.types
/etc/nginx/modules
/etc/nginx/nginx.conf
/etc/nginx/scgi_params
/etc/nginx/uwsgi_params
/usr/lib/systemd/system/nginx-debug.service
/usr/lib/systemd/system/nginx.service
/usr/lib64/nginx
/usr/lib64/nginx/modules
/usr/libexec/initscripts/legacy-actions/nginx
/usr/libexec/initscripts/legacy-actions/nginx/check-reload
/usr/libexec/initscripts/legacy-actions/nginx/upgrade
/usr/sbin/nginx
/usr/sbin/nginx-debug
/usr/share/doc/nginx-1.24.0
/usr/share/doc/nginx-1.24.0/COPYRIGHT
/usr/share/man/man8/nginx.8.gz
/usr/share/nginx
/usr/share/nginx/html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
/var/cache/nginx
/var/log/nginx

其中:

  • /etc/logrotate.d/nginx:日志轮转配置文件
  • /etc/nginx:配置目录,包括:
    • /etc/nginx/nginx.conf:主配置文件,会读取 /etc/nginx/conf.d 目录下的配置文件
    • /etc/nginx/conf.d:子配置目录
    • /etc/nginx/conf.d/default.conf:默认配置
  • /etc/nginx/mime.types:文件类型和文件后缀名的对应关系
  • /usr/lib/systemd/system/nginx.service:Nginx 服务文件
  • /usr/sbin/nginx:Nginx 可执行文件
  • /usr/share/nginx/html:静态页面目录,包括:
    • /usr/share/nginx/html/50x.html:默认错误页
    • /usr/share/nginx/html/index.html:默认首页
  • /var/log/nginx:日志文件所在目录

配置文件

Nginx 的默认配置文件为 /etc/nginx/nginx.conf,包括全局块,events 块及 http 块,内容如下:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


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

    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;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

全局块配置全局指令,包括:

  • user:指定启动工作进程的用户,这里为 nginx,默认为 nobody
  • worker_processes:指定工作进程数量,这里为 auto,表示工作进程数量与 CPU 数量相同
  • error_log:指定错误日志和日志级别,这里为 /var/log/nginx/error.lognotice
  • pid:指定 PID 文件,默认为 /var/run/nginx.pid

events 块配置与网络连接相关指令,包括:

  • worker_connections:指定每个工作进程的最大连接数,这里为 1024,不能超过内核参数 fs.file-max 和资源限制 nofile 的值

http 块配置与网络请求相关指令,包括:

  • include:引入的其他配置文件,这里有:
    • /etc/nginx/mime.types:文件类型和文件后缀名的对应关系
    • /etc/nginx/conf.d/*.conf:在 /etc/nginx/conf.d/ 目录下所有的配置文件,包含多个 server
  • default_type:默认 MIME 类型,这里为 application/octet-stream,表示已二进制流的方式下载文件,要将文件内容显示在浏览器中,可以设置为 text/plain。还可以配置在 server 块和 location 块中
  • log_format:日志格式,这里为 main,其后的变量含义参考 setopen in new window
  • access_log:访问日志及日志格式,这里为 /var/log/nginx/access.logmain
  • sendfile:是否开启高效文件传输模式,这里为 on,用于文件服务器
  • keepalive_timeout:长连接超时时间,这里为 65

http 块中引入的配置文件 /etc/nginx/conf.d/default.conf 包含 server 块及其下的 location 块,内容如下:

server {
    listen       80;
    server_name  localhost;

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

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

server 块配置虚拟主机,可以配置相同监听端口(比如 80)和不同域名的多个虚拟主机。包括:

  • listen:监听端口,后面可以加上 default_server 属性来指定该 server 为默认匹配的虚拟主机,用于处理没有匹配到 server_name:listen 的请求,否则使用第一个 server 作为默认匹配的虚拟主机。例如:

    • listen 80
    • listen 8080 default_server
  • server_name:虚拟主机名。可以是 IP 地址、主机名、域名。可以多个,以空格分隔。可以精确匹配、通配符匹配(*,只能出现在域名首尾,不能出现在域名中间)或者正则表达式匹配(以 ~ 为正则开始标记,后面不能加空格。可以使用括号包裹,后续使用 $1$2 等取值)。匹配顺序为先精确匹配,再前通配符匹配,再后通配符匹配,再正则表达式匹配,最后默认匹配。例如:

    • server_name localhost
    • server_name stonecoding.net minio.stonecoding.net
    • server_name *.stonecoding.net
    • server_name www.stonecoding.*
    • server_name ~^www\.(\w+)\.com$
  • error_page:指定错误页面,可以

    • 指定跳转地址:error_page 404 https://stonecoding.net
    • 指定重定向地址:error_page 500 502 503 504 /50x.html
    • 使用 @ 指定对应的 location 块:error_page 404 @jump_to_error
    • 使用 =[response] 更改响应码:error_page 404 =200 /50x.html

location 块指定与请求资源相匹配的路径,语法为 location [ = | ~ | ~* | ^~ | @ ] uri { ... }

  • location /abc:匹配以 abc 开头的请求,比如 server_name:listen/abc 或者 server_name:listen/abcd
  • location =/abc:精确匹配 abc 请求,不包含正则表达式,比如 server_name:listen/abcserver_name:listen/abc?username=tom
  • location ~^/abc\w$:包含正则表达式,且区分大小写,比如 server_name:listen/abc1
  • location ~*^/abc\w$:包含正则表达式,不区分大小写,比如 server_name:listen/ABc1
  • location ^~/abc:不包含正则表达式,功能和不加符号的一致,唯一不同的是,如果匹配,那么就停止搜索

location 块包括:

  • root:请求资源的根目录,最终请求的路径就是 root + location
  • index:默认首页

注意:

  • 一个 http 块可以包含多个 server 块,一个 server 块可以包含多个 location 块。
  • 对于可以在多个块使用的指令,小范围的指令优先。例如 access_log 指令可以在 http 块,server 块和 location 块使用,如果都有配置,则优先使用的是 location 块。

使用默认的配置文件启动 Nginx,作为一个 Web 服务器,访问上面 server 块中配置的虚拟主机名和端口 ,返回 /usr/share/nginx/html/index.html 文件内容:

[root@stone ~]# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

指令

除了在上面配置文件中默认使用的指令外,Nginx 还有非常多的内置指令,下面介绍一些常用的指令。

网络

使用以下指令来提高网络性能,来自于 ngx_http_core_moduleopen in new window 模块。

tcp_nodeplay on;
tcp_nopush on;
client_max_body_size 10m;

tcp_nodelay

使用 tcp_nodelay 指令提高网络包传输实时性,必须在连接为 keep-alive 状态才能启用。

Syntax:tcp_nodelay on | off;
Default:tcp_nodelay on;
Context:http, server, location

tcp_nopush

使用 tcp_nopush 指令提升网络包传输效率,必须在使用 sendfile 时才会启用。

Syntax:tcp_nopush on | off;
Default:tcp_nopush off;
Context:http, server, location

client_max_body_size

使用 client_max_body_size 指令指定客户端请求体最大值,用于限制上传下载文件的大小。

Syntax:client_max_body_size size;
Default:client_max_body_size 1m;
Context:http, server, location

压缩

使用 ngx_http_gzip_moduleopen in new window 模块下的压缩指令来减少传输的数据量,节约带宽。

gzip on;
gzip_comp_level 6;
gzip_min_length 1k;
gzip_types text/plain text/css application/json application/javascript application/xml;

gzip

使用 gzip 指令开启或者关闭压缩。

Syntax:gzip on | off;
Default:gzip off;
Context:http, server, location, if in location

gzip_buffers

使用 gzip_buffers 指令设置处理压缩的缓冲区数量和大小。使用默认值即可。

Syntax:gzip_buffers number size;
Default:gzip_buffers 32 4k|16 8k;
Context:http, server, location

gzip_comp_level

使用 gzip_comp_level 指令指定压缩级别。范围为 1 到 9,默认为 1,压缩率低,效率高。

Syntax:gzip_comp_level level;
Default:gzip_comp_level 1;
Context:http, server, location

gzip_disable

使用 gzip_disable 指令为指定的客户端请求关闭压缩。

Syntax:gzip_disable regex ...;
Default:
Context:http, server, location

根据请求头 User-Agent 来设置,支持使用正则表达式。

例如为不支持压缩的 IE 6 及以下版本浏览器关闭压缩:

gzip_disable "MSIE [1-6]\.";

gzip_http_version

使用 gzip_http_version 指令指定可以使用压缩的最小 HTTP 版本。使用默认即可。

Syntax:gzip_http_version 1.0 | 1.1;
Default:gzip_http_version 1.1;
Context:http, server, location

gzip_min_length

使用 gzip_min_length 指令指定可以被压缩的响应的最小长度。建议设置为 1K 或以上。

Syntax:gzip_min_length length;
Default:gzip_min_length 20;
Context:http, server, location

根据响应头 Content-Length 来决定。

gzip_proxied

使用 gzip_proxied 指令设置是否对服务端返回的结果进行压缩。

Syntax:gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;
Default:gzip_proxied off;
Context:http, server, location

其中:

  • off:对所有代理请求禁用压缩。
  • expired:如果响应头包含 Expires,则启用压缩
  • no-cache:如果响应头包含 Cache-Control:no-cache,则启用压缩
  • no-store:如果响应头包含 Cache-Control:no-store,则启用压缩
  • private:如果响应头包含 Cache-Control:private,则启用压缩
  • no_last_modified:如果响应头不包含 Last-Modified,则启用压缩
  • no_etag:如果响应头不包含 ETag,则启用压缩
  • auth:如果请求头包含 Authorization,则启用压缩
  • any:对所有代理请求启用压缩。

gzip_types

使用 gzip_types 指令指定除 text/html 外可以被压缩的 MIME 类型。

Syntax:gzip_types mime-type ...;
Default:gzip_types text/html;
Context:http, server, location

使用 * 匹配所有类型,text/html 类型的响应始终被压缩。

gzip_vary

使用 gzip_vary 指令指定在使用 gzipgzip_static 或者 gunzip 时是否增加 Vary: Accept-Encoding 响应头。

Syntax:gzip_vary on | off;
Default:gzip_vary off;
Context:http, server, location

客户端缓存

使用 ngx_http_headers_moduleopen in new window 模块下的指令配置客户端缓存。

expires

使用 expires 指令通过设置响应头的 ExpiresCache-Control 来控制页面缓存过期时间。

Syntax:expires [modified] time; expires epoch | max | off;
Default:expires off;
Context:http, server, location, if in location

其中:

  • time:指定缓存过期时间,默认从当前时间开始计算,如果使用 modified,则从文件修改时间开始计算。如果为负数,则 Cache-Controlno-cache,否则 Cache-Controlmax-age=time 。还可以在前面加上 @ 表示一天的某个时间点。可以使用的时间单位如下:
UnitDescription
msmilliseconds
sseconds
mminutes
hhours
ddays
wweeks
Mmonths, 30 days
yyears, 365 days
  • epoch:设置 ExpiresThu, 01 Jan 1970 00:00:01 GMTCache-Controlno-cache
  • max:设置 ExpiresThu, 31 Dec 2037 23:55:55 GMTCache-Control 为 10 年
  • off:不会设置响应头的 ExpiresCache-Control

例如:

expires    24h;
expires    modified +24h;
expires    @15h30m;
expires    0;
expires    -1;
expires    epoch;
expires    max;

add_header

使用 add_header 指令自定义响应头实现客户端缓存的控制。

Syntax:add_header name value [always];
Default:
Context:http, server, location, if in location

Cache-Control 可以设置为:

选项说明
must-revalidate缓存必须在使用之前验证旧资源的状态
no-cache在缓存前要向服务器确认资源是否被更改
no-store绝对禁止缓存
no-transform代理不得对资源进行转换或转变
public可以被任何对象缓存
private只能被单个用户缓存,不能作为共享缓存
proxy-revalidate要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=<seconds>以秒为单位的缓存时间,会覆盖 Expires
s-maxage=<seconds>以秒为单位的缓存时间,仅适用于共享缓存,会覆盖 Expiresmax-age

例如:

server {
    add_header Cache-Control private;
}

跨域

如果两个网址的协议,域名或者端口不同,则就会出现跨域问题。

使用 add_header 指令添加以下响应头以解决跨域问题:

  • Access-Control-Allow-Origin:允许跨域访问的源地址信息,可以配置多个(用逗号分隔),也可以使用 * 表示所有源。语法为 Access-Control-Allow-Origin: <origin> | *
  • Access-Control-Allow-Methods:允许跨域访问的请求方式,语法为 Access-Control-Allow-Methods: <method>[, <method>]*

例如:

location / {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
}

防盗链

为防止其他网站盗用连接,可以使用 ngx_http_referer_moduleopen in new window 模块下的 valid_referers 指令来防止盗链。

valid_referers

使用 valid_referers 指定设置允许访问的客户端地址。

Syntax:valid_referers none | blocked | server_names | string ...;
Default:
Context:server, location

其中:

  • none:请求头没有 Referer 信息。
  • blocked:请求头中有 Referer,但其值已被防火墙或者代理服务器删除,如不以 http:// 或者 https:// 开头的字符串。
  • server_names:请求头的 Referer 为设置的域名或者 IP 之一。
  • string:支持 * 和正则表达式的域名字符串,* 只能位于首位,正则表达式以 ~ 开头。

如果请求头的 Referervalid_referers 匹配时(不区分大小写),会将 $invalid_referer 变量设置为 0,否则设置为 1。

例如:

location /images {
    valid_referers none blocked www.baidu.com *.example.com example.*  www.example.org/galleries/  ~\.google\.;
    if ($invalid_referer){
        return 403;
    }
    root /usr/share/nginx/html;
}

重写

使用 ngx_http_rewrite_moduleopen in new window 模块下的指令实现 URL 重写。

set

使用 set 指令设置变量及其值。

Syntax:set $variable value;
Default:
Context:server, location, if

其中:

  • $variable:变量名,以 $ 开头,不能与 Nginx 预设的全局变量同名。
  • value:变量值,可以是字符串、其他变量或者它们的组合。

例如:

location / {
    default_type text/plain;
    set $name STONE;
    return 200 $name;
}

常用全局变量有:

变量说明
$args变量中存放了请求 URL 中的参数。比如 http://192.168.200.133:8080?arg1=value1&args2=value2 中的 arg1=value1&arg2=value2,功能和 $query_string 一样
$http_user_agent变量存储的是用户访问服务的代理信息(如果通过浏览器访问,记录的是浏览器的相关版本信息)
$host变量存储的是访问服务器的 IP地址
$document_uri变量存储的是当前访问地址的 URI。比如 http://192.168.200.133/server?id=10&name=zhangsan 中的 /server,功能和 $uri 一样
$document_root变量存储的是当前请求对应 locationroot 值,如果未设置,默认指向 Nginx 自带 html 目录所在位置
$content_length变量存储的是请求头中的 Content-Length 的值
$content_type变量存储的是请求头中的 Content-Type 的值
$http_cookie变量存储的是客户端的 Cookie 信息,可以通过 add_header Set-Cookie 'cookieName=cookieValue' 来添加 Cookie 数据
$limit_rate变量中存储的是 Nginx 服务器对网络连接速率的限制,也就是 Nginx 配置中对 limit_rate 指令设置的值,默认是 0,不限制
$remote_addr变量中存储的是客户端的 IP 地址
$remote_port变量中存储了客户端与服务端建立连接的端口号
$remote_user变量中存储了客户端的用户名,需要有认证模块才能获取
$scheme变量中存储了访问协议
$server_addr变量中存储了服务端的地址
$server_name变量中存储了客户端请求到达的服务器的名称
$server_port变量中存储了客户端请求到达服务器的端口号
$server_protocol变量中存储了客户端请求协议的版本,比如 HTTP/1.1
$request_body_file变量中存储了发给后端服务器的本地文件资源的名称
$request_method变量中存储了客户端的请求方式,比如 GET,POST 等
$request_filename变量中存储了当前请求的资源文件的路径名
$request_uri变量中存储了当前请求的 URI,并且携带请求参数,比如 http://192.168.200.133/server?id=10&name=zhangsan 中的 /server?id=10&name=zhangsan

if

使用 if 指令进行条件判断。

Syntax:if (condition) { ... }
Default:
Context:server, location

condition 为判断条件,可以是:

  • 变量名,如果变量值为空字符串或者 0 则返回 false
if ($param){
    return 200 success;
}
  • 使用 =!= 操作符比较变量和字符串,满足条件返回 true,不满足返回 false,字符串不需要添加引号。
if ($request_method = POST){
	return 405 error;
}
  • 正则表达式匹配,匹配成功返回 true,否则返回 false。正则表达式字符串一般不需要加引号,但是如果字符串中包含 } 或者 ; 时,需要加上单引号或者双引号。包括:

    • ~:匹配正则表达式过程中区分大小写。

    • ~*:匹配正则表达式过程中不区分大小写。

    • !~:反向匹配正则表达式过程中区分大小写。

    • !~*:反向匹配正则表达式过程中不区分大小写。

if ($http_user_agent ~ MSIE){
    return 200 IE
}
  • 使用 -f!-f 操作符判断文件是否存在。
location / {
    root /usr/share/nginx/html;
    default_type text/html;
    if (!-f $request_filename){
        return 200 '<h1>file not find</h1>'
    }
}
  • 使用 -d!-d 操作符判断目录是否存在。

  • 使用 -e!-e 操作符判断文件,目录或者符号链接是否存在。

  • 使用 -x!-x 操作符判断可执行文件。

break

使用 break 指令停止处理当前作用域指令,并将请求的 URI 在本 location 进行重定向访问处理。

Syntax:break;
Default:
Context:server, location, if

例如:

location /testbreak {
    default_type text/plain;
    set $username STONE;
    if ($args){
        set $username TOM;
        break;
        set $username JERRY;
    }
    add_header username $username;
    return 200 $username;
}

这里需要在 root 指定的目录下创建 testbreak 目录,并在 testbreak 目录下创建 index.html 文件。

return

使用 return 指令完成对请求的处理,直接向客户端返回。

Syntax:return code [text];
return code URL;
return URL;
Default:
Context:server, location, if

其中:

  • code:返回给客户端的 HTTP 响应状态码
  • text:返回给客户端的响应体内容,可以是变量
  • URL:返回给客户端的 URL 地址

例如:

location /testreturn/graph. {
    return 404;
}
location /testreturn {
    default_type application/json;
    return 200 '{id:1,name:stone}';
}
location /testreturn {
    #return https://www.baidu.com;
    return 302 https://www.baidu.com;
}

rewrite

使用 rewrite 指令使用正则表达式重写请求 URI。

Syntax:rewrite regex replacement [flag];
Default:
Context:server, location, if

其中:

  • regex:匹配 URI 的正则表达式。
  • replacement:用于替换匹配成功的 URI。如果以 http://https:// 或者 $scheme 开头,则直接返回重写后的 URI 给客户端。
location /rewrite {
    rewrite ^/rewrite/url\w*$ https://www.baidu.com;
    rewrite ^/rewrite/(test)\w*$ $1;
    rewrite ^/rewrite/(demo)\w*$ $1;
}
location /test {
    default_type text/plain;
    return 200 test_success;
}
location /demo {
    default_type text/plain;
    return 200 demo_success;
}
  • flag:处理行为标志,包括:

    • last:重写完成后继续向下匹配新的 location URI 规则。
    location /rewrite {
        rewrite ^/rewrite/(test)\w*$ $1 last;
        rewrite ^/rewrite/(demo)\w*$ $1 last;
    }
    location /test {
        default_type text/plain;
        return 200 test_success;
    }
    location /demo {
        default_type text/plain;
        return 200 demo_success;
    }
    
    • break:重写完成后终止,在当前 location{} 中查找重写后的 URI 。
    location /rewrite {
        root /usr/share/nginx/html;
        #如果访问 URI 为 /rewrite/testabc,则会被重写为 /test,则会查找文件 /usr/share/nginx/html/test/index.html
        rewrite ^/rewrite/(test)\w*$ $1 break;
        rewrite ^/rewrite/(demo)\w*$ $1 break;
    }
    
    • redirect:返回 302 临时重定向,浏览器地址会显示为重定向的地址。用于 replacement 不以 http://https:// 或者 $scheme 开头。
    location /rewrite {
        rewrite ^/rewrite/(test)\w*$ $1 redirect;
        rewrite ^/rewrite/(demo)\w*$ $1 redirect;
    }
    
    • permanent:返回 301 永久重定向,浏览器地址会显示为重定向的地址。用于 replacement 不以 http://https:// 或者 $scheme 开头。默认值。
    location /rewrite {
        rewrite ^/rewrite/(test)\w*$ $1 permanent;
        rewrite ^/rewrite/(demo)\w*$ $1 permanent;
    }
    

对于 breaklast,规则如下:

  • rewritelocation{} 外时,遇到 breaklast 后,其后续的 rewrite 指令不再执行。但如果后续有匹配的 location{} 的话,还会执行 location{} 里面的指令。
  • rewritelocation{} 里时,遇到 break 后,本 location{} 与其他 location{} 的所有 rewrite 指令都不再执行。
  • rewritelocation{} 里时,遇到 last 后,本 location{}rewrite 指令都不再执行,但重写后的 URL 再次从头开始匹配各个 location{} ,哪个匹配执行哪个。
域名跳转

在服务器配置如下域名解析:

[root@stone ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.92.128   stone
192.168.92.128   www.stonecoding.net
192.168.92.128   www.stonecoding.com
192.168.92.128   www.stonecoding.cn
192.168.92.128   www.stonecoding.org

增加配置文件 /etc/nginx/conf.d/stonecoding.conf

server {
    listen 80;
    server_name www.stonecoding.net;
    location / {
        default_type text/plain;
        return 200 'Welcome to stonecoding';
    }
}

检测配置文件并重载配置文件:

[root@stone ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@stone ~]# nginx -s reload

访问测试:

[root@stone ~]# curl www.stonecoding.net
Welcome to stonecoding

使用 rewrite 将访问 www.stonecoding.comopen in new window 请求跳转到 https://stonecoding.netopen in new window

server {
	listen 80;
	server_name www.stonecoding.com;
	rewrite ^/ https://stonecoding.net;
}

访问测试:

[root@stone ~]# curl -L www.stonecoding.com
Welcome to stonecoding

使用 rewrite 多个域名跳转,并在跳转时携带请求的 URI

server{
	listen 80;
	server_name www.stonecoding.cn www.stonecoding.org;
	rewrite ^(.*) https://stonecoding.net$1;
}

访问测试:

[root@stone ~]# curl -L www.stonecoding.cn
Welcome to stonecoding
[root@stone ~]# curl -L www.stonecoding.org
Welcome to stonecoding
[root@stone ~]# curl -L www.stonecoding.org/abc
Welcome to stonecoding

如果使用服务器上的浏览器访问,则会发现地址发生了改变。

域名镜像

使用 rewrite 为子目录下的资源进行域名跳转。

server {
	listen 80;
	server_name www.stonecoding.cn www.stonecoding.org;
	location /user {
		rewrite ^/user(.*)$ http://www.stonecoding.net$1;
	}
}

访问测试:

[root@stone ~]# curl -L www.stonecoding.org/user/abc
Welcome to stonecoding
独立域名

一个完整的项目包含多个模块,比如购物网站有搜索模块、详情模块、购物车模块等,可以为每一个模块设置独立的域名。

需求:

http://search.stonecoding.net:81  访问商品搜索模块
http://item.stonecoding.net:82	  访问商品详情模块
http://cart.stonecoding.net:83	  访问商品购物车模块
server{
	listen 81;
	server_name search.stonecoding.net;
	rewrite ^(.*) http://www.stonecoding.net/search$1;
}
server{
	listen 82;
	server_name item.stonecoding.net;
	rewrite ^(.*) http://www.stonecoding.net/item$1;
}
server{
	listen 83;
	server_name cart.stonecoding.net;
	rewrite ^(.*) http://www.stonecoding.net/cart$1;
}
合并目录

假设网站中有一个资源文件的访问路径为 /server/11/22/33/44/20.html,也就是说文件存在于第 5 级目录下,如果想要访问该资源文件,客户端的URL地址就要写成 http://www.web.name/server/11/22/33/44/20.html,

server {
	listen 80;
	server_name www.web.name;
	location /server{
		root html;
	}
}

这样的地址是非常不利于 SEO 搜索引擎优化的,同时客户端也不好记。使用 rewrite 进行如下配置:

server {
	listen 80;
	server_name www.web.name;
	location /server{
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /server/$1/$2/$3/$4/$5.html last;
	}
}

此时客户端只需要输入 http://www.web.name/server-11-22-33-44-20.html 就可以访问到页面了。

防盗链

使用 rewrite 可以将盗链请求转发到自定义的一张图片和页面,给用户比较好的提示信息。

根据文件类型实现防盗链:

server{
	listen 80;
	server_name www.web.com;
	locatin ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)${
		valid_referers none blocked server_names *.web.com;
		if ($invalid_referer){
			rewrite ^/ http://www.web.com/images/forbidden.png;
		}
	}
}

根据目录实现防盗链:

server{
	listen 80;
	server_name www.web.com;
	location /file/ {
		root /server/file/;
		valid_referers none blocked server_names *.web.com;
		if ($invalid_referer){
			rewrite ^/ http://www.web.com/images/forbidden.png;
		}
	}
}
跳转首页

使用 rewrite 将 404 跳转到首页。

server {
    listen       80;
    server_name  localhost;
	location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
	
	error_page 404 @jump_to_index;

    location @jump_to_index {
        rewrite ^.*$ / permanent;
    }
}

rewrite_log

使用 rewrite_log 指令指定是否将重写相关日志以 notice 级别写入到 error_log 指定的日志文件中。

Syntax:rewrite_log on | off;
Default:rewrite_log off;
Context:http, server, location, if

如果要在 error_log 指定的日志文件中看到重写日志,确保 error_log 的日志级别为 notice

location /rewrite {
    rewrite_log on;
    error_log /var/log/nginx/error.log notice;
    rewrite ^/rewrite/(test)\w*$ $1 permanent;
    rewrite ^/rewrite/(demo)\w*$ $1 permanent;
}

反向代理

反向代理是指以代理服务器来接受互联网上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给互联网上请求连接的客户端。对于客户端而言,反向代理服务器就相当于目标服务器,即直接访问反向代理服务器就可以获得目标服务器的资源。这种机制使得用户不需要知道目标服务器的地址,也无须在用户端做任何设定。

image-20230918101558657

使用 ngx_http_proxy_moduleopen in new window 模块下的指令实现反向代理。

location / {
    proxy_pass http://app;
    proxy_set_header Host $host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_redirect off;
    proxy_buffering on;
    proxy_buffer_size 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;
}

proxy_pass

使用 proxy_pass 指令指定服务端地址。

Syntax:proxy_pass URL;
Default:
Context:location, if in location, limit_except

安装配置两个虚拟机,分别为代理端和服务端:

No.HostNameIPRole
1proxy192.168.92.128Proxy
2server192.168.92.128Server

在代理端和服务端都安装 Nginx。

修改代理端 /usr/share/nginx/html/index.html 文件:

[root@proxy ~]# mv /usr/share/nginx/html/index.html /usr/share/nginx/html/index.html.bak
[root@proxy ~]# echo "I am proxy" > /usr/share/nginx/html/index.html
[root@proxy ~]# curl 192.168.92.128
I am proxy

修改服务端 /usr/share/nginx/html/index.html 文件:

[root@server ~]# mv /usr/share/nginx/html/index.html /usr/share/nginx/html/index.html.bak
[root@server ~]# echo "I am server" > /usr/share/nginx/html/index.html
[root@server ~]# curl 192.168.92.129
I am server

在代理端增加配置 /etc/nginx/conf.d/proxy.conf

server {
    listen 80;
    server_name proxy;
    location / {
        proxy_pass http://192.168.92.129/;
    }
}

代理端重新加载配置文件:

[root@proxy ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@proxy ~]# nginx -s reload

然后访问代理端:

[root@proxy ~]# curl proxy
I am server

可以看到已经将请求转发给了服务端。

注意

  • 如果 location 指令指定的 URI 为 /,则 proxy_pass 指令指定的 URL 最后加不加 /,效果一样。
  • 如果 location 指令指定的 URI 不为 /,例如 /server
    • proxy_pass 指令指定的 URL 最后不加 /,例如 http://192.168.92.129,则请求将会被转发到 URL/URI,即 http://192.168.92.129/server/index.html
    • proxy_pass 指令指定的 URL 最后加上 /,例如 http://192.168.92.129/,则请求将会被转发到 URL,即 http://192.168.92.129/index.html

proxy_set_header

使用 proxy_set_header 指令在代理端设置请求头信息,再发给服务端。

Syntax:proxy_set_header field value;
Default:proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context:http, server, location

在代理端增加配置 /etc/nginx/conf.d/proxy.conf 并重载配置文件:

server {
    listen 80;
    server_name proxy;
    location / {
        proxy_pass http://192.168.92.129/;
    }    
    location /server {
        proxy_pass http://192.168.92.129:8080/;
        proxy_set_header username STONE;
    }
}
[root@proxy ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@proxy ~]# nginx -s reload

在服务端增加配置 /etc/nginx/conf.d/server.conf 并重载配置文件:

server {
    listen  8080;
    server_name server;
    location / {
        default_type text/plain;
        return 200 $http_username;
    }
}
[root@server ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@server ~]# nginx -s reload

然后访问代理端:

[root@proxy ~]# curl proxy/server
STONE

proxy_redirect

使用 proxy_redirect 指令重置响应头信息中的 LocationRefresh 的值,即对发送给客户端的 URL 进行修改。

Syntax:proxy_redirect default;
proxy_redirect off;
proxy_redirect redirect replacement;
Default:proxy_redirect default;
Context:http, server, location

其中 default 表示将 proxy_pass 变量作为 redirect,将 location 的 URI 作为 replacement。例如以下两个配置等价:

location /one/ {
    proxy_pass     http://upstream:port/two/;
    proxy_redirect default;
}
location /one/ {
    proxy_pass     http://upstream:port/two/;
    proxy_redirect http://upstream:port/two/ /one/;
}

redirectreplacement 可以使用变量。例如:

proxy_redirect http://localhost:8000/ http://$host:$server_port/;
proxy_redirect http://$proxy_host:8000/ /;

redirect 可以使用正则表达式,replacement 可以引用 。例如:

proxy_redirect ~^(http://[^:]+):\d+(/.+)$ $1$2;
proxy_redirect ~*/user/([^/]+)/(.+)$      http://$1.example.com/$2;

proxy_buffering

使用 proxy_buffering 指令开启或关闭代理端缓冲。

Syntax:proxy_buffering on | off;
Default:proxy_buffering on;
Context:http, server, location

开启缓冲后,Nginx 接收服务端响应,并保存到由指令 proxy_buffer_sizeproxy_buffers 设置的缓冲区。

proxy_buffer_size

使用 proxy_buffer_size 指令设置从服务端获取的第一部分响应数据的大小,默认为一个内存页大小。

Syntax:proxy_buffer_size size;
Default:proxy_buffer_size 4k|8k;
Context:http, server, location

proxy_buffers

使用 proxy_buffers 指令指定用于单个连接读取服务端响应的缓存区个数和大小,单个大小默认为一个内存页。

Syntax:proxy_buffers number size;
Default:proxy_buffers 8 4k|8k;
Context:http, server, location

proxy_busy_buffers_size

使用 proxy_busy_buffers_size 指令限制同时处于 BUSY 状态的缓冲总大小。

Syntax:proxy_busy_buffers_size size;
Default:proxy_busy_buffers_size 8k|16k;
Context:http, server, location

proxy_temp_path

使用 proxy_temp_path 指令指定当缓冲区满时,存放临时文件的目录。

Syntax:proxy_temp_path path [level1 [level2 [level3]]];
Default:proxy_temp_path proxy_temp;
Context:http, server, location

proxy_temp_file_write_size

使用 proxy_temp_file_write_size 指令限制一次写入临时文件的数据大小。

Syntax:proxy_temp_file_write_size size;
Default:proxy_temp_file_write_size 8k|16k;
Context:http, server, location

安全

使用 ngx_http_ssl_moduleopen in new window 模块下的指令提供 HTTPS 支持。

server {
    listen              443 ssl;
    keepalive_timeout   70;

    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
    ssl_certificate     /usr/local/nginx/conf/cert.pem;
    ssl_certificate_key /usr/local/nginx/conf/cert.key;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
}

ssl

使用 ssl 指令开启 HTTPS。

Syntax:ssl on | off;
Default:ssl off;
Context:http, server

该指令将在 1.25.1 版本被移除,使用 listen 443 ssl; 替代。

ssl_certificate

使用 ssl_certificate 指令指定 PEM 格式的证书文件。

Syntax:ssl_certificate file;
Default:
Context:http, server

ssl_certificate_key

使用 ssl_certificate_key 指令指定 PEM 格式的密钥文件。

Syntax:ssl_certificate_key file;
Default:
Context:http, server

ssl_session_cache

使用 ssl_session_cache 指令指定用于 SSL 的会话缓存。

Syntax:ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
Default:ssl_session_cache none;
Context:http, server

包括:

  • off:禁用会话缓存,客户端不得重复使用会话。
  • none:禁止使用会话缓存,客户端可以重复使用,但是并没有在缓存中存储会话参数。
  • builtin:内置 OpenSSL 缓存,仅在一个工作进程中使用。如果没有指定 size,则为 20480 个会话,使用该类型会话会导致内存碎片。
  • shared:所有工作进程共享缓存,以字节为单位指定 size,1 MB可以存储 4000 会话。

例如:

ssl_session_cache shared:SSL:10m;

ssl_session_timeout

使用 ssl_session_timeout 指令指定客户端能够重复使用储存在缓存中的会话参数的超时时间。

Syntax:ssl_session_timeout time;
Default:ssl_session_timeout 5m;
Context:http, server

ssl_ciphers

使用 ssl_ciphers 指令指定 OpenSSL 支持的加密算法。

Syntax:ssl_ciphers ciphers;
Default:ssl_ciphers HIGH:!aNULL:!MD5;
Context:http, server

ssl_prefer_server_ciphers

使用 ssl_prefer_server_ciphers 指令指定是否服务器密码优先客户端密码。

Syntax:ssl_prefer_server_ciphers on | off;
Default:ssl_prefer_server_ciphers off;
Context:http, server

OpenSSL

安装 OpenSSL 并生成证书:

[root@proxy ~]# yum install openssl

[root@proxy ~]# openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017

[root@proxy ~]# openssl genrsa -out proxy-privkey.pem 2048
Generating RSA private key, 2048 bit long modulus
.............+++
..........+++
e is 65537 (0x10001)

[root@proxy ~]# openssl req -new -key proxy-privkey.pem -out proxy-cert.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:cq
Locality Name (eg, city) [Default City]:bb
Organization Name (eg, company) [Default Company Ltd]:stone 
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:proxy.stonecoding.net
Email Address []:stone@stonecoding.net

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:stone

[root@proxy ~]# openssl req -new -x509 -key proxy-privkey.pem -out proxy-cacert.pem -days 109500
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:cq
Locality Name (eg, city) [Default City]:bb
Organization Name (eg, company) [Default Company Ltd]:stone
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:proxy.stonecoding.net
Email Address []:stone@stonecoding.net

[root@proxy ~]# ll proxy-*
-rw-r--r-- 1 root root 1383 Sep 18 16:52 proxy-cacert.pem
-rw-r--r-- 1 root root 1094 Sep 18 16:52 proxy-cert.csr
-rw-r--r-- 1 root root 1679 Sep 18 16:51 proxy-privkey.pem
[root@proxy ~]# cp proxy-privkey.pem /etc/nginx/proxy-privkey.pem
[root@proxy ~]# cp proxy-cacert.pem /etc/nginx/proxy-cert.pem

使用生成的证书为配置文件 /etc/nginx/conf.d/proxy.conf 增加 SSL:

server {
    listen 80;
    listen 443 ssl;
    server_name proxy.stonecoding.net;
    ssl_certificate proxy-cert.pem;
    ssl_certificate_key proxy-privkey.pem;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://192.168.92.129/;
    }    
    location /server {
        proxy_pass http://192.168.92.129:8080/;
        proxy_set_header username STONE;
    }
}

重载配置文件:

[root@proxy ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@proxy ~]# nginx -s reload

客户端配置域名解析后使用浏览器访问 HTTPS:

image-20230918170910096

由于是自签发的证书,故地址栏处会有安全警告。可以在阿里云或其他机构申请经过第三方签发证书。

使用 rewrite 将访问 HTTP 的流量重定向到 HTTPS:

server {
    listen 80;
    server_name proxy.stonecoding.net;

    location / {
        rewrite ^(.*) https://proxy.stonecoding.net$1;
    }
}
server {
    listen 443 ssl;
    server_name proxy.stonecoding.net;
    ssl_certificate proxy-cert.pem;
    ssl_certificate_key proxy-privkey.pem;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://192.168.92.129/;
    }
    location /server {
        proxy_pass http://192.168.92.129:8080/;
        proxy_set_header username STONE;
    }
}

重载配置文件:

[root@proxy ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@proxy ~]# nginx -s reload

客户端使用浏览器访问 HTTP 时会自动跳转到 HTTPS。

缓存

使用 ngx_http_proxy_moduleopen in new window 模块下的指令实现 Nginx 缓存。

proxy_cache_path

使用 proxy_cache_path 指令设置缓存目录及其他参数。

Syntax:proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [min_free=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
Default:
Context:http

其中:

  • path:指定缓存目录。例如:/data/nginx/cache
  • levels:指定缓存目录下的目录层级及目录名称长度。例如:levels=1:2,表示目录层级为 2 层,第一层的目录名称为缓存文件名的最后 1 个字符,第二层的目录名称为缓存文件名倒数第 3 和 第 2 个字符,例如:/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
  • keys_zone:指定缓存的名称和大小。例如:keys_zone=stone:200m
  • inactive:指定没有被访问的缓存输出可以被保留的时间。例如:inactive=1d
  • max_size:指定最大缓存大小。例如:max_size=10g

例如:

http {
	proxy_cache_path /data/nginx/cache keys_zone=stone:200m  levels=1:2 inactive=1d max_size=10g;
}

proxy_cache

使用 proxy_cache 指令指定用于缓存的缓冲区。

Syntax:proxy_cache zone | off;
Default:proxy_cache off;
Context:http, server, location

proxy_cache off; 表示禁用缓存。

proxy_cache_key

使用 proxy_cache_key 指令指定缓存的键。

Syntax:proxy_cache_key string;
Default:proxy_cache_key $scheme$proxy_host$request_uri;
Context:http, server, location

proxy_cache_valid

使用 proxy_cache_valid 指令为不同的响应状态码设置缓存时间。

Syntax:proxy_cache_valid [code ...] time;
Default:
Context:http, server, location

例如:

proxy_cache_valid 200 302 10m;
proxy_cache_valid 404      1m;

如果只设置时间参数,例如:

proxy_cache_valid 5m;

则只缓存响应状态码为 200,301 和 302 的响应。

使用 any 参数缓存任意状态码:

proxy_cache_valid 200 302 10m;
proxy_cache_valid 301      1h;
proxy_cache_valid any      1m;

proxy_cache_min_uses

使用 proxy_cache_min_uses 指令设置多少次请求后对应的响应才会被缓存。

Syntax:proxy_cache_min_uses number;
Default:proxy_cache_min_uses 1;
Context:http, server, location

proxy_cache_methods

使用 proxy_cache_methods 指令设置会被缓存的 HTTP 方法。

Syntax:proxy_cache_methods GET | HEAD | POST ...;
Default:proxy_cache_methods GET HEAD;
Context:http, server, location

proxy_no_cache

使用 proxy_no_cache 指令定义不缓存响应数据的条件。

Syntax:proxy_no_cache string ...;
Default:
Context:http, server, location

如果多个 string 参数有一个不为空且不等于 “0” 则不缓存响应数据。

例如:

proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;
proxy_no_cache $http_pragma    $http_authorization;

其中:

  • $cookie_nocache:当前请求的 Cookie 中键的名称为 nocache 对应的值
  • $arg_nocache:当前请求的参数中属性名为 nocache 对应的属性值
  • $arg_comment:当前请求的参数中属性名为 comment 对应的属性值

proxy_cache_bypass

使用 proxy_cache_bypass 指令定义不缓存响应数据的条件。

Syntax:proxy_cache_bypass string ...;
Default:
Context:http, server, location

如果多个 string 参数有一个不为空且不等于 “0” 则不缓存响应数据。

例如:

proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
proxy_cache_bypass $http_pragma    $http_authorization;

其中:

  • $cookie_nocache:当前请求的 Cookie 中键的名称为 nocache 对应的值
  • $arg_nocache:当前请求的参数中属性名为 nocache 对应的属性值
  • $arg_comment:当前请求的参数中属性名为 comment 对应的属性值

示例

缓存配置:

http {
	proxy_cache_path /data/nginx/cache keys_zone=stone:200m  levels=1:2 inactive=1d max_size=10g;
	upstream backend {
		server 192.168.92.129:8080;
	}
	server {
		listen       8080;
        server_name  localhost;
        location / {
        	proxy_cache stone;
            proxy_cache_min_uses 5;
            proxy_cache_valid 200 5d;
            proxy_cache_valid 404 30s;
            proxy_cache_valid any 1m;
            add_header nginx-cache "$upstream_cache_status";
        	proxy_pass http://backend/js/;
        }
	}
}

不缓存配置:

server {
	listen	8080;
	server_name localhost;
	location / {
		if ($request_uri ~ /.*\.js$){
           set $nocache 1;
        }
		proxy_no_cache $nocache $cookie_nocache $arg_nocache $arg_comment;
        proxy_cache_bypass $nocache $cookie_nocache $arg_nocache $arg_comment;
	}
}

下载站点

使用 ngx_http_autoindex_moduleopen in new window 模块下的指令创建下载站点。

autoindex

使用 autoindex 指令启用或禁用目录列表输出。

Syntax:autoindex on | off;
Default:autoindex off;
Context:http, server, location

autoindex_format

使用 autoindex_format 指令设置目录列表格式。

Syntax:autoindex_format html | xml | json | jsonp;
Default:autoindex_format html;
Context:http, server, location

对于下载站点,需要保持为默认值,即:autoindex_format html

autoindex_exact_size

使用 autoindex_exact_size 指令指定是以字节为单位在目录列表显示文件的详细大小,还是以 KB,MB 或者 GB 为单位显示文件大小。用于 autoindex_format html

Syntax:autoindex_exact_size on | off;
Default:autoindex_exact_size on;
Context:http, server, location

autoindex_localtime

使用 autoindex_localtime 指令指定显示的时间格式是本地时区还是 UTC。用于 autoindex_format html

Syntax:autoindex_localtime on | off;
Default:autoindex_localtime off;
Context:http, server, location

示例

location /download {
    root /tmp;
    autoindex on;
}

认证

使用 ngx_http_auth_basic_moduleopen in new window 模块下的指令实现认证。

auth_basic

使用 auth_basic 指令采用 HTTP Basic Authentication 协议启用用户名和密码的验证。

Syntax:auth_basic string | off;
Default:auth_basic off;
Context:http, server, location, limit_except

开启后,服务端会返回 401,指定的字符串会返回到客户端,给用户以提示信息,但是不同的浏览器对内容的展示不一致。

auth_basic_user_file

使用 auth_basic_user_file 指令指定用户名和密码所在文件。

Syntax:auth_basic_user_file file;
Default:
Context:http, server, location, limit_except

安装 httpd-tools 并使用 htpasswd 命令生成密码文件:

[root@proxy ~]# yum -y install httpd-tools
[root@proxy ~]# htpasswd -c /tmp/htpasswd stone
[root@proxy ~]# cat /tmp/htpasswd 
stone:$apr1$RW9BxhaW$nsQY6/M/DfcF1rjRh897U0
[root@proxy ~]# htpasswd -b /tmp/htpasswd tom 123456
Adding password for user tom
[root@proxy ~]# cat /tmp/htpasswd 
stone:$apr1$RW9BxhaW$nsQY6/M/DfcF1rjRh897U0
tom:$apr1$vdJBd3ga$PhBRkHdKLWGge0Qku1Bb50
[root@proxy ~]# htpasswd -D /tmp/htpasswd tom
Deleting password for user tom
[root@proxy ~]# cat /tmp/htpasswd 
stone:$apr1$RW9BxhaW$nsQY6/M/DfcF1rjRh897U0
[root@proxy ~]# htpasswd -v /tmp/htpasswd stone
Enter password: 
Password for user stone correct.

示例

location /download {
    root /tmp;
    autoindex on;
    auth_basic 'please input your username and password';
    auth_basic_user_file /tmp/htpasswd;
}

负载均衡

可以使用 Nginx 配置负载均衡,将客户端请求分摊到多个服务器上。

image-20230919131329504

负载均衡可以分为:

  • 七层负载均衡,工作在应用层,经常用于处理 HTTP 请求。可以使用 Nginx,HAProxy 实现。
  • 四层负载均衡,工作中传输层,是基于 IP 和端口的负载均衡,可以使用 LVS,Nginx 实现。

七层

Nginx 使用 ngx_http_upstream_moduleopen in new window 模块下的指令实现七层负载均衡。

upstream

使用 upstream 指令定义一组后端服务器。

Syntax:upstream name { ... }
Default:
Context:http

server

使用 server 指令在 upstream 中定义后端服务器的地址及其他参数。

Syntax:server address [parameters];
Default:
Context:upstream

parameters 包括:

  • weight=number:后端服务器的权重,默认为 1。
  • max_conns=number:到后端服务器的最大活动连接数,默认为 0,表示无限制。
  • max_fails=number:设置请求失败的次数,默认为 1。
  • fail_timeout=time:失败次数达到 max_fails 后,服务暂停的时间,默认为 10 秒。
  • backup:标记该服务器为备份服务器,在主服务器不可用后启用。
  • down:标记该服务器为不可用。

例如:负载均衡方式为轮询

upstream backend {
	server 192.168.92.131;
	server 192.168.92.132;
	server 192.168.92.133;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

例如:负载均衡方式为加权轮询

upstream backend {
	server 192.168.92.131 weight=5;
	server 192.168.92.132 weight=3;
	server 192.168.92.133 weight=2;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

例如:一个后端服务器不可用,一个后端服务器为备份服务器,一个后端服务器失败次数达到 3 次后,服务暂停的 15 秒

upstream backend {
	server 192.168.92.131 down;
	server 192.168.92.132 backup;
	server 192.168.92.133 max_fails=3 fail_timeout=15;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

random

使用 random 指令指定负载均衡方式,将请求随机传递给随机选择的后端服务器。

Syntax:random [two [method]];
Default:
Context:upstream

例如:负载均衡方式为 random

upstream backend {
	random;
	server 192.168.92.131;
	server 192.168.92.132;
	server 192.168.92.133;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

least_conn

使用 least_conn 指令指定负载均衡方式,将请求传递给最少活动连接数的后端服务器。

Syntax:least_conn;
Default:
Context:upstream

例如:负载均衡方式为 least_conn

upstream backend {
	least_conn;
	server 192.168.92.131;
	server 192.168.92.132;
	server 192.168.92.133;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

ip_hash

使用 ip_hash 指令指定负载均衡方式,将相同 IP 的请求通过哈希算法传递到同一台后端服务器上。

Syntax:ip_hash;
Default:
Context:upstream

例如:负载均衡方式为 ip_hash

upstream backend {
	ip_hash;
	server 192.168.92.131;
	server 192.168.92.132;
	server 192.168.92.133;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

hash

使用 hash 指令指定负载均衡方式,可以将相同 URL 的请求通过哈希算法传递到同一台后端服务器上。

Syntax:hash key [consistent];
Default:
Context:upstream

例如:负载均衡方式为 hash

upstream backend {
	hash &request_uri consistent;
	server 192.168.92.131;
	server 192.168.92.132;
	server 192.168.92.133;
}
server {
	listen 80;
	server_name localhost;
	location / {
		proxy_pass http://backend;
	}
}

示例

对特定资源实现负载均衡:

upstream filebackend {
	server 192.168.92.131;
	server 192.168.92.132;
}
upstream imagebackend {
	server 192.168.92.133;
	server 192.168.92.134;
}
server {
	listen 80;
	server_name localhost;
	location /file/ {
		proxy_pass http://filebackend;
	}
	location /image/ {
		proxy_pass http://imagebackend;
	}
}

对不同域名实现负载均衡:

upstream stonebackend {
	server 192.168.92.131;
	server 192.168.92.132;
}
upstream shibackend {
	server 192.168.92.133;
	server 192.168.92.134;
}
server {
	listen	8080;
	server_name www.stonecoding.net;
	location / {
		proxy_pass http://stonebackend;
	}
}
server {
	listen	8080;
	server_name www.shihanle.com;
	location / {
		proxy_pass http://shibackend;
	}
}

带有 URL 重写的负载均衡:

upstream backend {
	server 192.168.92.131;
	server 192.168.92.132;
	server 192.168.92.133;
}
server {
	listen	80;
	server_name localhost;
	location /file/ {
		rewrite ^(/file/.*) /server/$1 last;
	}
	location / {
		proxy_pass http://backend;
	}
}

四层

Nginx 使用 Stream 模块下的指令实现四层负载均衡,该模块在 Nginx 1.9.0 后可用,用法与 Http 模块类似,允许配置一组 TCP 或者 UDP 等协议的监听,然后通过 proxy_pass 转发请求,通过 upstream 添加多个后端服务,实现负载均衡。

stream

使用 stream 指令指定四层负载均衡的配置。位于 ngx_stream_core_moduleopen in new window 模块。

Syntax:stream { ... }
Default:
Context:main

server

使用 server 指令在 stream 中定义虚拟服务器。位于 ngx_stream_core_moduleopen in new window 模块。

Syntax:server { ... }
Default:
Context:stream

listen

使用 listen 指令在 server 中指定监听的地址和端口。位于 ngx_stream_core_moduleopen in new window 模块。

Syntax:listen address:port [ssl] [udp] [proxy_protocol] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
Default:
Context:server

proxy_pass

使用 proxy_pass 指令在 server 中指定服务端地址。位于 ngx_stream_proxy_moduleopen in new window 模块。

Syntax:proxy_pass address;
Default:
Context:server

upstream

使用 upstream 指令在 stream 中定义一组后端服务器。位于 ngx_stream_upstream_moduleopen in new window 模块。

Syntax:upstream name { ... }
Default:
Context:stream

server

使用 server 指令在 upstream 中定义后端服务器的地址及其他参数。位于 ngx_stream_upstream_moduleopen in new window 模块。

Syntax:server address [parameters];
Default:
Context:upstream

parameters 包括:

  • weight=number:后端服务器的权重,默认为 1。
  • max_conns=number:到后端服务器的最大活动连接数,默认为 0,表示无限制。
  • max_fails=number:设置请求失败的次数,默认为 1。
  • fail_timeout=time:失败次数达到 max_fails 后,服务暂停的时间,默认为 10 秒。
  • backup:标记该服务器为备份服务器,在主服务器不可用后启用。
  • down:标记该服务器为不可用。

示例

使用 Dockeropen in new window 安装 Redis:

[root@server ~]# docker run -itd --name redis1 -p 6378:6379 redis
[root@server ~]# docker run -itd --name redis2 -p 6379:6379 redis
[root@server ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                                       NAMES
528f9acd05e9   redis     "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   redis2
a0b16f5ff613   redis     "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6378->6379/tcp, :::6378->6379/tcp   redis1

配置负载均衡:

stream {
    upstream redisbackend {
        server 192.168.92.129:6378;
        server 192.168.92.129:6379;
    }
    server {
        listen  6379;
        proxy_pass redisbackend;
    }
}
上次编辑于:
贡献者: stonebox,stone