Nginx
Nginx
注意:
此文档对应的 Nginx 版本为 1.24.0。
概述
Nginx 是一个高性能的 HTTP 和反向代理 Web 服务器。
经常用于:
- 反向代理,将客户端的 HTTP 请求转发到后端服务器进行处理
- 负载均衡,将客户端的请求分配到多个后端服务器上进行处理
- Web 服务器,处理静态文件
部署
部署 Nginx 有以下两种方式:
- YUM 部署:主机可以访问外网
- 本地部署:主机不能访问外网
下面介绍如何在 CentOS 7 环境安装 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
本地部署
如果主机不能访问外网,需要先在官网下载 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 会注册为服务,使用 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 信号,表示快速关闭 Nginxquit
:发送 SIGQUIT 信号,表示优雅关闭 Nginxreopen
:发送 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.log
和notice
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
,其后的变量含义参考 setaccess_log
:访问日志及日志格式,这里为/var/log/nginx/access.log
和main
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/abc
,server_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_module 模块。
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_module 模块下的压缩指令来减少传输的数据量,节约带宽。
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
指令指定在使用 gzip
,gzip_static
或者 gunzip
时是否增加 Vary: Accept-Encoding
响应头。
Syntax: | gzip_vary on | off; |
---|---|
Default: | gzip_vary off; |
Context: | http , server , location |
客户端缓存
使用 ngx_http_headers_module 模块下的指令配置客户端缓存。
expires
使用 expires
指令通过设置响应头的 Expires
和 Cache-Control
来控制页面缓存过期时间。
Syntax: | expires [modified] time; expires epoch | max | off; |
---|---|
Default: | expires off; |
Context: | http , server , location , if in location |
其中:
time
:指定缓存过期时间,默认从当前时间开始计算,如果使用modified
,则从文件修改时间开始计算。如果为负数,则Cache-Control
为no-cache
,否则Cache-Control
为max-age=time
。还可以在前面加上@
表示一天的某个时间点。可以使用的时间单位如下:
Unit | Description |
---|---|
ms | milliseconds |
s | seconds |
m | minutes |
h | hours |
d | days |
w | weeks |
M | months, 30 days |
y | years, 365 days |
epoch
:设置Expires
为Thu, 01 Jan 1970 00:00:01 GMT
,Cache-Control
为no-cache
max
:设置Expires
为Thu, 31 Dec 2037 23:55:55 GMT
,Cache-Control
为 10 年off
:不会设置响应头的Expires
和Cache-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> | 以秒为单位的缓存时间,仅适用于共享缓存,会覆盖 Expires 和 max-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_module 模块下的 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
:支持*
和正则表达式的域名字符串,*
只能位于首位,正则表达式以~
开头。
如果请求头的 Referer
与 valid_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_module 模块下的指令实现 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 | 变量存储的是当前请求对应 location 的 root 值,如果未设置,默认指向 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; }
对于 break
和 last
,规则如下:
- 当
rewrite
在location{}
外时,遇到break
或last
后,其后续的rewrite
指令不再执行。但如果后续有匹配的location{}
的话,还会执行location{}
里面的指令。 - 当
rewrite
在location{}
里时,遇到break
后,本location{}
与其他location{}
的所有rewrite
指令都不再执行。 - 当
rewrite
在location{}
里时,遇到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.com 请求跳转到 https://stonecoding.net
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;
}
反向代理
反向代理是指以代理服务器来接受互联网上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给互联网上请求连接的客户端。对于客户端而言,反向代理服务器就相当于目标服务器,即直接访问反向代理服务器就可以获得目标服务器的资源。这种机制使得用户不需要知道目标服务器的地址,也无须在用户端做任何设定。
使用 ngx_http_proxy_module 模块下的指令实现反向代理。
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. | HostName | IP | Role |
---|---|---|---|
1 | proxy | 192.168.92.128 | Proxy |
2 | server | 192.168.92.128 | Server |
在代理端和服务端都安装 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
指令重置响应头信息中的 Location
和 Refresh
的值,即对发送给客户端的 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/;
}
redirect
和 replacement
可以使用变量。例如:
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_size
和 proxy_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_module 模块下的指令提供 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:
由于是自签发的证书,故地址栏处会有安全警告。可以在阿里云或其他机构申请经过第三方签发证书。
使用 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_module 模块下的指令实现 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_module 模块下的指令创建下载站点。
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_module 模块下的指令实现认证。
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 配置负载均衡,将客户端请求分摊到多个服务器上。
负载均衡可以分为:
- 七层负载均衡,工作在应用层,经常用于处理 HTTP 请求。可以使用 Nginx,HAProxy 实现。
- 四层负载均衡,工作中传输层,是基于 IP 和端口的负载均衡,可以使用 LVS,Nginx 实现。
七层
Nginx 使用 ngx_http_upstream_module 模块下的指令实现七层负载均衡。
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_module 模块。
Syntax: | stream { ... } |
---|---|
Default: | — |
Context: | main |
server
使用 server
指令在 stream
中定义虚拟服务器。位于 ngx_stream_core_module 模块。
Syntax: | server { ... } |
---|---|
Default: | — |
Context: | stream |
listen
使用 listen
指令在 server
中指定监听的地址和端口。位于 ngx_stream_core_module 模块。
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_module 模块。
Syntax: | proxy_pass address; |
---|---|
Default: | — |
Context: | server |
upstream
使用 upstream
指令在 stream
中定义一组后端服务器。位于 ngx_stream_upstream_module 模块。
Syntax: | upstream name { ... } |
---|---|
Default: | — |
Context: | stream |
server
使用 server
指令在 upstream
中定义后端服务器的地址及其他参数。位于 ngx_stream_upstream_module 模块。
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
:标记该服务器为不可用。
示例
使用 Docker 安装 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;
}
}