Nginx 全实践(超长文预警)
实验环境四台 VMWare Workstation 虚拟机:node105:作为测试访问的客户端,以及进行 Tengine 相关实验;node106:Nginx实验,并作为七层反向代理及四层负载均衡;node107和node108:作为后端服务器,安装web应用(httpd/nginx和php-fpm)、MySQL和Redis;[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(
实验环境
四台 VMWare Workstation 虚拟机:
- node105:作为测试访问的客户端,以及进行 Tengine 相关实验;
- node106:Nginx实验,并作为七层反向代理及四层负载均衡;
- node107和node108:作为后端服务器,安装web应用(httpd/nginx和php-fpm)、MySQL和Redis;
一:Nginx 安装
1.1:Nginx yum 安装
1.1.1:安装 epel 源
- 安装 epel 源:
[root@node105 ~]# yum install epel-release -y
- 查看 epel 仓库中的 Nginx 版本:
[root@node105 ~]# yum info nginx
Available Packages
Name : nginx
Arch : x86_64
Epoch : 1
Version : 1.16.1
Release : 3.el7
Size : 563 k
Repo : epel/x86_64
Summary : A high performance web server and reverse proxy server
URL : http://nginx.org/
License : BSD
Description : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
: IMAP protocols, with a strong focus on high concurrency, performance and low
: memory usage.
1.1.2:安装 Nginx
- 安装:
[root@node105 ~]# yum install nginx -y
1.1.3:验证安装
- 查看生成文件:
[root@node105 ~]# rpm -ql nginx
/etc/logrotate.d/nginx
/etc/nginx/fastcgi.conf
/etc/nginx/fastcgi.conf.default
/etc/nginx/fastcgi_params
/etc/nginx/fastcgi_params.default
/etc/nginx/koi-utf
/etc/nginx/koi-win
/etc/nginx/mime.types
/etc/nginx/mime.types.default
/etc/nginx/nginx.conf
/etc/nginx/nginx.conf.default
/etc/nginx/scgi_params
/etc/nginx/scgi_params.default
/etc/nginx/uwsgi_params
/etc/nginx/uwsgi_params.default
/etc/nginx/win-utf
/usr/bin/nginx-upgrade
/usr/lib/systemd/system/nginx.service
/usr/lib64/nginx/modules
/usr/sbin/nginx
/usr/share/doc/nginx-1.16.1
/usr/share/doc/nginx-1.16.1/CHANGES
/usr/share/doc/nginx-1.16.1/README
/usr/share/doc/nginx-1.16.1/README.dynamic
/usr/share/doc/nginx-1.16.1/UPGRADE-NOTES-1.6-to-1.10
/usr/share/licenses/nginx-1.16.1
/usr/share/licenses/nginx-1.16.1/LICENSE
/usr/share/man/man3/nginx.3pm.gz
/usr/share/man/man8/nginx-upgrade.8.gz
/usr/share/man/man8/nginx.8.gz
/usr/share/nginx/html/404.html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/en-US
/usr/share/nginx/html/icons
/usr/share/nginx/html/icons/poweredby.png
/usr/share/nginx/html/img
/usr/share/nginx/html/index.html
/usr/share/nginx/html/nginx-logo.png
/usr/share/nginx/html/poweredby.png
/usr/share/vim/vimfiles/ftdetect/nginx.vim
/usr/share/vim/vimfiles/ftplugin/nginx.vim
/usr/share/vim/vimfiles/indent/nginx.vim
/usr/share/vim/vimfiles/syntax/nginx.vim
/var/lib/nginx
/var/lib/nginx/tmp
/var/log/nginx
- 查看 nginx 命令帮助:
[root@node105 ~]# nginx -h
nginx version: nginx/1.16.1
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-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: /usr/share/nginx/)
-c filename : set configuration file (default: /etc/nginx/nginx.conf)
-g directives : set global directives out of configuration file
- 验证 nginx 配置文件:
[root@node105 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
- 查看 nginx 版本及配置信息:
[root@node105 ~]# nginx -V
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1c FIPS 28 May 2019 (running with OpenSSL 1.1.1g FIPS 21 Apr 2020)
TLS SNI support enabled
configure arguments: --prefix=/usr/share/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 --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
- 查看 nginx 启动脚本:
[root@node105 ~]# cat /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
1.1.4:Nginx 默认配置
[root@node105 ~]# grep -v "#" /etc/nginx/nginx.conf | grep -v "^$"
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
1.1.5:启动 Nginx
- 设置开机启动:
[root@node105 ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
- 启动 Nginx:
[root@node105 ~]# systemctl start nginx
- 查看 nginx 运行状态:
[root@node105 ~]# systemctl status nginx
nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2020-12-02 03:53:55 CST; 7s ago
Process: 3014 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Process: 3010 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 3009 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Main PID: 3016 (nginx)
CGroup: /system.slice/nginx.service
├─3016 nginx: master process /usr/sbin/nginx
└─3017 nginx: worker process
Dec 02 03:53:55 node105.yqc.com systemd[1]: Starting The nginx HTTP and reverse proxy server...
Dec 02 03:53:55 node105.yqc.com nginx[3010]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Dec 02 03:53:55 node105.yqc.com nginx[3010]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Dec 02 03:53:55 node105.yqc.com systemd[1]: Failed to parse PID from file /run/nginx.pid: Invalid argument
Dec 02 03:53:55 node105.yqc.com systemd[1]: Started The nginx HTTP and reverse proxy server.
- 查看 Nginx 进程:
[root@node105 ~]# ps -ef | grep nginx | grep -v grep
root 3016 1 0 03:53 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 3017 3016 0 03:53 ? 00:00:00 nginx: worker process
1.1.6:访问 Nginx
1.2:Nginx 编译安装
1.2.1:准备编译环境
- 安装编译基础环境以及常用工具:
yum install -y vim lrzsz tree screen psmisc lsof tcpdump wget ntpdate gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools iotop bc zip unzip zlib-devel bash-completion nfs-utils automake libxml2 libxml2-devel libxslt libxslt-devel perl perl-ExtUtils-Embed
1.2.2:下载 Nginx 源码包
Nginx 官方下载地址:https://nginx.org/en/download.html
[root@node106 ~]# cd /usr/local/src/
[root@node106 src]# ll
total 1016
-rw-r--r-- 1 root root 1039530 Oct 19 17:33 nginx-1.18.0.tar.gz
1.2.3:解压 Nginx 源码包
[root@node106 src]# tar zxvf nginx-1.18.0.tar.gz
[root@node106 src]# ll nginx-1.18.0
total 768
drwxr-xr-x 6 1001 1001 4096 Dec 2 03:58 auto
-rw-r--r-- 1 1001 1001 302863 Apr 21 2020 CHANGES
-rw-r--r-- 1 1001 1001 462213 Apr 21 2020 CHANGES.ru
drwxr-xr-x 2 1001 1001 4096 Dec 2 03:58 conf
-rwxr-xr-x 1 1001 1001 2502 Apr 21 2020 configure
drwxr-xr-x 4 1001 1001 68 Dec 2 03:58 contrib
drwxr-xr-x 2 1001 1001 38 Dec 2 03:58 html
-rw-r--r-- 1 1001 1001 1397 Apr 21 2020 LICENSE
drwxr-xr-x 2 1001 1001 20 Dec 2 03:58 man
-rw-r--r-- 1 1001 1001 49 Apr 21 2020 README
drwxr-xr-x 9 1001 1001 84 Dec 2 03:58 src
1.2.4:生成 Makefile
- 这一步是检查系统环境是否符合编译安装的要求,是否支持编译参数中的模块,并根据指定的编译参数生成 Makefile 文件,为接下来的编译安装作好准备:
./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
1.2.5:编译并安装
- 编译是根据 Makefile 生成安装所需的相应模块文件:
[root@node106 nginx-1.18.0]# make
- 安装是创建相应目录,并将编译过程生成的模块和文件复制到相应目录:
[root@node106 nginx-1.18.0]# make install
1.2.6:创建 Nginx 用户
- 创建 Nginx 用户,指定 UID 为 2000,shell 为 nologin:
[root@node106 ~]# useradd -u 2000 -s /sbin/nologin nginx
- 验证 Nginx 用户:
[root@node106 ~]# id nginx
uid=2000(nginx) gid=2000(nginx) groups=2000(nginx)
1.2.7:创建额外的配置文件目录
[root@node106 ~]# mkdir /apps/nginx/conf.d
[root@node106 ~]# chown nginx:nginx -R /apps/nginx/conf.d/
1.2.8:创建 nginx 软链接
[root@node106 ~]# ln -sv /apps/nginx/sbin/nginx /usr/bin/nginx
‘/usr/bin/nginx’ -> ‘/apps/nginx/sbin/nginx’
1.2.9:验证编译安装
- 查看安装生成的文件目录:
[root@node106 ~]# ll /apps/nginx/
total 4
drwxr-xr-x 2 root root 4096 Dec 2 04:18 conf
drwxr-xr-x 2 root root 38 Dec 2 04:18 html
drwxr-xr-x 2 root root 6 Dec 2 04:18 logs
drwxr-xr-x 2 root root 18 Dec 2 04:18 sbin
- 查看 Nginx 版本及编译配置参数:
[root@node106 ~]# /apps/nginx/sbin/nginx -V
nginx version: nginx/1.18.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=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
1.2.10:Nginx 默认配置
[root@node106 ~]# grep -v "#" /apps/nginx/conf/nginx.conf | grep -v "^$"
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
1.2.11:创建 Nginx 启动脚本
- 编辑启动脚本:
[root@node106 ~]# vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /apps/nginx/logs/nginx.pid
ExecStartPre=/apps/nginx/sbin/nginx -t
ExecStart=/apps/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
- 重载 systemd:
[root@node106 ~]# systemctl daemon-reload
1.2.12:启动 Nginx
- 设置开机启动:
[root@node106 ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
- 启动 Nginx:
[root@node106 ~]# systemctl start nginx
- 查看 Nginx 运行状态:
[root@node106 ~]# ssytemctl status nginx
-bash: ssytemctl: command not found
[root@node106 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2020-12-02 04:27:38 CST; 12s ago
Process: 6208 ExecStart=/apps/nginx/sbin/nginx (code=exited, status=0/SUCCESS)
Process: 6206 ExecStartPre=/apps/nginx/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 6205 ExecStartPre=/usr/bin/rm -f /apps/nginx/logs/nginx.pid (code=exited, status=0/SUCCESS)
Main PID: 6210 (nginx)
CGroup: /system.slice/nginx.service
├─6210 nginx: master process /apps/nginx/sbin/nginx
└─6211 nginx: worker process
Dec 02 04:27:38 node106.yqc.com systemd[1]: Starting The nginx HTTP and reverse proxy server...
Dec 02 04:27:38 node106.yqc.com nginx[6206]: nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
Dec 02 04:27:38 node106.yqc.com nginx[6206]: nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
Dec 02 04:27:38 node106.yqc.com systemd[1]: Failed to parse PID from file /apps/nginx/logs/nginx.pid: Invalid argument
Dec 02 04:27:38 node106.yqc.com systemd[1]: Started The nginx HTTP and reverse proxy server.
- 查看 Nginx 进程:
[root@node106 ~]# ps -ef | grep nginx | grep -v grep
root 6210 1 0 20:27 ? 00:00:00 nginx: master process /apps/nginx/sbin/nginx
nginx 6211 6210 0 20:27 ? 00:00:00 nginx: worker process
1.2.13:访问 Nginx
1.3:Tengine 编译安装
以下内容摘自 Tengine 官方:
Tengine是由淘宝网发起的Web服务器项目。
它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。
Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。
它的最终目标是打造一个高效、稳定、安全、易用的Web平台。
特性
- 继承Nginx-1.17.3的所有特性,兼容Nginx的配置;
- 支持HTTP的CONNECT方法,可用于正向代理场景;
- 支持异步OpenSSL,可使用硬件如:QAT进行HTTPS的加速与卸载;
- 增强相关运维、监控能力,比如异步打印日志及回滚,本地DNS缓存,内存监控等;
- Stream模块支持server_name指令;
- 更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线,以及动态解析upstream中出现的域名;
- 输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便;
- 支持设置proxy、memcached、fastcgi、scgi、uwsgi在后端失败时的重试次数
- 动态脚本语言Lua支持。扩展功能非常高效简单;
- 支持按指定关键字(域名,url等)收集Tengine运行状态;
- 组合多个CSS、JavaScript文件的访问请求变成一个请求;
- 自动去除空白字符和注释从而减小页面的体积
- 自动根据CPU数目设置进程个数和绑定CPU亲缘性;
- 监控系统的负载和资源占用从而对系统进行保护;
- 显示对运维人员更友好的出错信息,便于定位出错机器;
- 更强大的防攻击(访问速度限制)模块;
- 更方便的命令行参数,如列出编译的模块列表、支持的指令等;
- 可以根据访问文件类型设置过期时间;
- ……
1.3.1:下载 Tengine 源码包
Tengine 官网:http://tengine.taobao.org/
本次实验采用 Tengine-2.1.2:http://tengine.taobao.org/download/tengine-2.1.2.tar.gz
[root@node105 ~]# wget -O /usr/local/src/tengine-2.1.2.tar.gz http://tengine.taobao.org/download/tengine-2.1.2.tar.gz
1.3.2:解压 Tengine 源码包
[root@node105 ~]# cd /usr/local/src/
[root@node105 src]# tar zxvf tengine-2.1.2.tar.gz
[root@node105 src]# ll tengine-2.1.2
total 664
-rw-r--r-- 1 50469 users 889 Dec 31 2015 AUTHORS.te
drwxr-xr-x 6 50469 users 4096 Dec 31 2015 auto
-rw-r--r-- 1 50469 users 236013 Dec 31 2015 CHANGES
-rw-r--r-- 1 50469 users 18359 Dec 31 2015 CHANGES.cn
-rw-r--r-- 1 50469 users 359556 Dec 31 2015 CHANGES.ru
-rw-r--r-- 1 50469 users 23875 Dec 31 2015 CHANGES.te
drwxr-xr-x 2 50469 users 4096 Dec 31 2015 conf
-rwxr-xr-x 1 50469 users 2435 Dec 31 2015 configure
drwxr-xr-x 4 50469 users 103 Dec 31 2015 contrib
drwxr-xr-x 3 50469 users 20 Dec 31 2015 docs
-rw-r--r-- 1 50469 users 441 Dec 31 2015 good_configure
drwxr-xr-x 2 50469 users 38 Dec 31 2015 html
-rw-r--r-- 1 50469 users 1676 Dec 31 2015 LICENSE
drwxr-xr-x 2 50469 users 20 Dec 31 2015 man
drwxr-xr-x 4 50469 users 53 Dec 31 2015 modules
drwxr-xr-x 3 50469 users 19 Dec 31 2015 packages
-rw-r--r-- 1 50469 users 3223 Dec 31 2015 README
-rw-r--r-- 1 50469 users 3775 Dec 31 2015 README.markdown
drwxr-xr-x 9 50469 users 82 Dec 31 2015 src
drwxr-xr-x 4 50469 users 41 Dec 31 2015 tests
-rw-r--r-- 1 50469 users 43 Dec 31 2015 THANKS.te
[root@node105 src]# cd tengine-2.1.2
1.3.3:生成 Makefile
Tengine 的编译参数和 Nginx 基本相同,以下为 Tengine 特有的编译参数:
--dso-path
Set the installation directory for the DSO modules.
--dso-tool-path
Set the installation path for the dso_tool script.
--without-dso
Disable the DSO (Dynamic Shared Object) feature.
--with-jemalloc
Enable Tengine to link the jemalloc library for memory management.
--with-jemalloc=path
Set the path to the source code of the jemalloc library.
P.S.
Tengine-2.1.2 中不支持 --with-stram* 的编译参数,想必 stream 相关的功能已默认加载;
./configure --prefix=/apps/tengine \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-file-aio \
--with-ipv6
1.3.4:编译并安装
[root@node105 tengine-2.1.2]# make && make install
1.3.5:创建 nginx 软链接
Tengine 也是采用 nginx 命令,这里为了方便区分,建立的是 tengine 软链接;
[root@node105 ~]# ln -sv /apps/tengine/sbin/nginx /usr/bin/nginx
‘/usr/bin/nginx’ -> ‘/apps/tengine/sbin/nginx’
1.3.6:验证编译安装
- 查看 tengine 编译安装生成的文件目录:
[root@node105 ~]# ll /apps/tengine/
total 8
drwxr-xr-x 2 root root 4096 Dec 5 16:52 conf
drwxr-xr-x 2 root root 38 Dec 5 16:52 html
drwxr-xr-x 2 root root 4096 Dec 5 16:52 include
drwxr-xr-x 2 root root 22 Dec 5 16:55 logs
drwxr-xr-x 2 root root 6 Dec 5 16:52 modules
drwxr-xr-x 2 root root 33 Dec 5 16:52 sbin
- 查看 tengine 版本及编译参数:
[root@node105 ~]# nginx -V
Tengine version: Tengine/2.1.2 (nginx/1.6.2)
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
TLS SNI support enabled
configure arguments: --prefix=/apps/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-file-aio
nginx: [emerg] invalid port in resolver "fe80::1%eth0" in /apps/tengine/conf/nginx.conf:123
Tengine 有一个自动解析/etc/resolve.conf文件构造resolver的功能,但这个功能还不支持IPv6,所以解析报错:
nginx: [emerg] invalid port in resolver “fe80::1%eth0” in /apps/tengine/conf/nginx.conf:123可以通过删除 /etc/resolv.conf 中的
nameserver fe80::1%eth0
这条 ipv6 解析条目来临时解决(重启网络后会失效):[root@node105 ~]# vim /etc/resolv.conf # Generated by NetworkManager nameserver 192.168.1.1 nameserver fe80::1%eth0 [root@node105 ~]# cat /etc/resolv.conf # Generated by NetworkManager nameserver 192.168.1.1
- 接下来 tengine 的编译参数就可以完整加载了(后续的启动也不会再报相同的错误):
[root@node105 ~]# tengine -V
Tengine version: Tengine/2.1.2 (nginx/1.6.2)
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
TLS SNI support enabled
configure arguments: --prefix=/apps/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-file-aio --with-ipv6
loaded modules:
ngx_core_module (static)
ngx_errlog_module (static)
ngx_conf_module (static)
ngx_dso_module (static)
ngx_syslog_module (static)
ngx_events_module (static)
ngx_event_core_module (static)
ngx_epoll_module (static)
ngx_procs_module (static)
ngx_proc_core_module (static)
ngx_openssl_module (static)
ngx_regex_module (static)
ngx_http_module (static)
ngx_http_core_module (static)
ngx_http_log_module (static)
ngx_http_upstream_module (static)
ngx_http_v2_module (static)
ngx_http_static_module (static)
ngx_http_gzip_static_module (static)
ngx_http_autoindex_module (static)
ngx_http_index_module (static)
ngx_http_auth_basic_module (static)
ngx_http_access_module (static)
ngx_http_limit_conn_module (static)
ngx_http_limit_req_module (static)
ngx_http_realip_module (static)
ngx_http_geo_module (static)
ngx_http_map_module (static)
ngx_http_split_clients_module (static)
ngx_http_referer_module (static)
ngx_http_rewrite_module (static)
ngx_http_ssl_module (static)
ngx_http_proxy_module (static)
ngx_http_fastcgi_module (static)
ngx_http_uwsgi_module (static)
ngx_http_scgi_module (static)
ngx_http_memcached_module (static)
ngx_http_empty_gif_module (static)
ngx_http_browser_module (static)
ngx_http_user_agent_module (static)
ngx_http_upstream_ip_hash_module (static)
ngx_http_upstream_consistent_hash_module (static)
ngx_http_upstream_check_module (static)
ngx_http_upstream_least_conn_module (static)
ngx_http_upstream_keepalive_module (static)
ngx_http_upstream_dynamic_module (static)
ngx_http_stub_status_module (static)
ngx_http_write_filter_module (static)
ngx_http_header_filter_module (static)
ngx_http_chunked_filter_module (static)
ngx_http_v2_filter_module (static)
ngx_http_range_header_filter_module (static)
ngx_http_gzip_filter_module (static)
ngx_http_postpone_filter_module (static)
ngx_http_ssi_filter_module (static)
ngx_http_charset_filter_module (static)
ngx_http_userid_filter_module (static)
ngx_http_footer_filter_module (static)
ngx_http_trim_filter_module (static)
ngx_http_headers_filter_module (static)
ngx_http_upstream_session_sticky_module (static)
ngx_http_reqstat_module (static)
ngx_http_copy_filter_module (static)
ngx_http_range_body_filter_module (static)
ngx_http_not_modified_filter_module (static)
1.3.7:Tengine 默认配置
[root@node105 ~]# grep -v "#" /apps/tengine/conf/nginx.conf | grep -v "^$"
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
1.3.8:创建 Tengine 启动脚本
- 编辑启动脚本:
[root@node105 ~]# vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/apps/tengine/logs/nginx.pid
ExecStartPre=/usr/bin/rm -f /apps/tengine/logs/nginx.pid
ExecStartPre=/apps/tengine/sbin/nginx -t
ExecStart=/apps/tengine/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
- 重载 systemd:
[root@node105 ~]# systemctl daemon-reload
1.3.9:启动 Tengine
[root@node105 ~]# systemctl start nginx
[root@node105 ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
1.3.10:访问 Tengine
二:Nginx 基础配置实践
2.1:server_name 配置
2.1.1:http 配置段导入 conf.d 下的配置文件
- 删除默认 server 配置,并为 http 配置段导入 conf.d 下的配置文件:
[root@node106 ~]# vim /apps/nginx/conf/nginx.conf
http {
……
include /apps/nginx/conf.d/*.conf;
……
}
- 重载 nginx:
[root@node106 ~]# systemctl reload nginx
2.1.2:新建一个 PC 端站点
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
location / {
root /data/nginx/yqc/www;
}
}
- 检查配置文件:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
- 重载nginx:
[root@node106 ~]# systemctl reload nginx
- 准备 PC 端测试页面:
[root@node106 ~]# mkdir /data/nginx/yqc/www -pv
mkdir: created directory ‘/data’
mkdir: created directory ‘/data/nginx’
mkdir: created directory ‘/data/nginx/yqc’
mkdir: created directory ‘/data/nginx/yqc/www’
[root@node106 ~]# vim /data/nginx/yqc/www/index.html
PC site
- 访问测试
2.1.3:新建一个移动端站点
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
location / {
root /data/nginx/yqc/wap;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备移动端测试页:
[root@node106 ~]# mkdir /data/nginx/yqc/wap
[root@node106 ~]# vim /data/nginx/yqc/wap/index.html
wap site
- 访问测试
2.2:location 匹配
2.2.1:不指定匹配方式
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location /images {
root /data/nginx/yqc/www;
}
location /text {
root /data/nginx/yqc;
}
}
访问以 /images 开始的 URI,root 为 /data/nginx/yqc/www;
访问以 /text 开始的 URI, root 为 root /data/nginx/yqc;
- 准备测试页面:
[root@node106 ~]# mkdir /data/nginx/yqc/text
[root@node106 ~]# vim /data/nginx/yqc/text/test.txt
test text
-
访问测试
http://www.yqc.com/images/ironman.jpg
http://www.yqc.com/text/test.txt
2.2.2:精确匹配
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /ironman.jpg {
root /data/nginx/yqc/www/images;
}
}
访问 http://www.yqc.com/ironman.jpg 时,root 为 /data/nginx/yqc/www/images;
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# !sys
systemctl reload nginx
- 验证访问
http://www.yqc.com/ironman.jpg
2.2.3:正则表达式匹配 - 区分大小写
- 编辑配置文件:
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
# location / {
# root /data/nginx/yqc/www;
# index index.html;
# }
location ~ /images/.*\.JPG {
root /data/nginx/yqc/www;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# !sys
systemctl reload nginx
- 准备测试文件:
[root@node106 ~]# ll /data/nginx/yqc/www/images/
total 1340
-rw-r--r-- 1 root root 1113986 Dec 2 12:37 batman.JPG
-rw-r--r-- 1 root root 254358 Dec 2 09:53 ironman.jpg
- 访问测试:
仅能访问大写的 JPG,而不能识别 jpg 结尾的 URI;
2.2.4:正则表达式匹配 - 不区分大小写
- 将上述配置改为
~*
:
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
# location / {
# root /data/nginx/yqc/www;
# index index.html;
# }
location ~* /images/.*\.JPG {
root /data/nginx/yqc/www;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# !sys
systemctl reload nginx
- 访问测试
可以访问 jpg 结尾的图片;
2.2.5:正则表达式匹配 - 匹配 URI 起始
验证:
^~
比~
的匹配优先级高;
- 编辑配置文件:
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
# location / {
# root /data/nginx/yqc/www;
# index index.html;
# }
location ~ /images/.*\.jpg {
root /data/nginx/yqc/www;
}
location ^~ /images {
root /data/nginx/yqc;
}
}
- 准备测试图片:
[root@node106 ~]# mkdir /data/nginx/yqc/images
[root@node106 ~]# cp ironman.jpg /data/nginx/yqc/images/ironman111.jpg
- 访问测试:
可以访问http://www.yqc.com/images/ironman111.jpg;
但不能访问http://www.yqc.com/images/ironman.jpg;
因为优先匹配location ^~ /images
,而根据其中指定的 root,存在/data/nginx/yqc/images/ironman111.jpg
,但不存在/data/nginx/yqc/images/ironman111.jpg
;
2.3:Nginx 安全
2.3.1:allow/deny 访问控制
通过匹配请求的源 IP 地址,对访问进行控制;
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
location / {
root /data/nginx/yqc/www;
index index.html;
allow 192.168.1.66;
deny all;
}
}
~
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 192.168.1.66 访问:
- 192.168.1.9 访问:
2.3.2:basic 用户认证
- 安装 httpd-tools,以使用 htpasswd 命令:
[root@node106 ~]# yum install httpd-tools -y
- 创建用户认证文件,并添加第一个认证用户:
[root@node106 ~]# htpasswd -cbm /apps/nginx/conf/.htpasswd user1 123456
Adding password for user user1
- 添加第二个用户:
[root@node106 ~]# htpasswd -bm /apps/nginx/conf/.htpasswd user2 123456
Adding password for user user2
- 查看用户认证文件:
[root@node106 ~]# cat /apps/nginx/conf/.htpasswd
user1:$apr1$D9a1alP8$/PI5dWmw.puO6OBGcpL/F1
user2:$apr1$CLtPB5Sc$YFk83BEiQO2hLEGPyxic90
- 编辑 nginx 配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
location / {
root /data/nginx/yqc/www;
index index.html;
auth_basic "username/password";
auth_basic_user_file /apps/nginx/conf/.htpasswd;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试:
2.3.3:limit_except
- 编辑配置文件
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
error_log /data/nginx/logs/www-yqc-com_error.log;
client_max_body_size 10m;
client_body_buffer_size 16k;
client_body_temp_path /data/nginx/temp 1 2 2;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location /upload {
root /data/nginx/yqc/www;
index index.html;
limit_except GET {
allow 192.168.1.105;
deny all;
}
}
}
配置:
- 仅允许 192.168.1.105 执行除 GET 之外的其它操作;
- 其他 IP 仅允许 GET(允许GET的同时意味着也允许HEAD);
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 创建目录:
[root@node106 ~]# mkdir /data/nginx/yqc/www/upload
[root@node106 ~]# chown -R nginx:nginx /data/nginx
- 使用192.168.1.105 上传文件:
[root@node105 ~]# curl -XPUT /etc/issue http://www.yqc.com/upload
curl: (3) <url> malformed
<html>
<head><title>405 Not Allowed</title></head>
<body>
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
405 表示Nginx已经允许 PUT 操作,但程序不支持上传功能;
- 使用192.168.1.111 上传文件:
root@ubuntu:~# curl -XPUT /etc/issue http://www.yqc.com/upload
curl: (3) <url> malformed
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
403 表示 PUT 被 Nginx 拒绝;
2.3.4:隐藏 Nginx 版本
- 更改 Nginx 源码信息:
[root@node106 ~]# vim /usr/local/src/nginx-1.18.0/src/http/ngx_http_header_filter_module.c
static u_char ngx_http_server_string[] = "Server: yqc" CRLF;
- 重新编译安装nginx:
[root@node106 ~]# systemctl stop nginx
[root@node106 ~]# cd /usr/local/src/nginx-1.18.0/
[root@node106 nginx-1.18.0]# ./configure \
--prefix=/apps/nginx \
--user=nginx --group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--add-module=/usr/local/src/echo-nginx-module
[root@node106 nginx-1.18.0]# make && make install
[root@node106 nginx-1.18.0]# systemctl start nginx
- 访问验证响应报文头部
没改过来,不深究了;
2.3.5:编译升级 OpenSSL
升级 openssl 主要是为了解决 heartbleed 安全漏洞;
heartbleed 漏洞存在于 OpenSSL 的 1.0.1 至 1.0.1f(含)版本中,较新版本及先前版本均不受影响;
[root@node106 ~]# yum info openssl Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com Installed Packages Name : openssl Arch : x86_64 Epoch : 1 Version : 1.0.2k Release : 19.el7 Size : 814 k Repo : installed From repo : base Summary : Utilities from the general purpose cryptography library with TLS implementation URL : http://www.openssl.org/ License : OpenSSL Description : The OpenSSL toolkit provides support for secure communications between : machines. OpenSSL includes a certificate management tool and shared : libraries which provide various cryptographic algorithms and : protocols.
此次系统上的 OpenSSL 版本为 1.0.2k,已不存在此安全漏洞,仅为了测试升级步骤;
-
查看当前 openssl 版本:
当前为 1.0.2k;
[root@node106 ~]# nginx -V
nginx version: nginx/1.18.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=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
- 下载并解压 openssl 源码包:
openssl 官网:https://www.openssl.org
本次下载的为 openssl-1.1.1h,下载地址为:https://www.openssl.org/source/openssl-1.1.1h.tar.gz
[root@node106 ~]# cd /usr/local/src/
[root@node106 src]# tar zxvf openssl-1.1.1h.tar.gz
- 重新编译安装 nginx:
[root@node106 ~]# systemctl stop nginx
[root@node106 ~]# cd /usr/local/src/nginx-1.18.0/
[root@node106 nginx-1.18.0]# ./configure \
--prefix=/apps/nginx \
--user=nginx --group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--add-module=/usr/local/src/echo-nginx-module \
--with-openssl=/usr/local/src/openssl-1.1.1h
[root@node106 nginx-1.18.0]# make && make install
-
验证 openssl 版本:
版本升级为 1.1.1h
[root@node106 ~]# nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1h 22 Sep 2020
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/echo-nginx-module --with-openssl=/usr/local/src/openssl-1.1.1h
2.4:Nginx 日志
2.4.1:access_log 访问日志
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
}
- 创建相应日志目录:
[root@node106 ~]# mkdir /data/nginx/logs
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看日志:
[root@node106 ~]# tail -f /data/nginx/logs/www-yqc-com_access.log
192.168.1.9 - user1 [02/Dec/2020:13:45:31 +0800] "GET /tom.jpg HTTP/1.1" 404 6 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36"
192.168.1.9 - user1 [02/Dec/2020:13:45:37 +0800] "GET /tom.jpg HTTP/1.1" 404 6 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36"
192.168.1.9 - user1 [02/Dec/2020:13:45:50 +0800] "GET /images/batman.JPG HTTP/1.1" 200 1113986 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36"
192.168.1.66 - - [02/Dec/2020:13:46:14 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0"
2.4.2:error_log 错误日志
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
error_log /data/nginx/logs/www-yqc-com_error.log;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看日志:
[root@node106 ~]# tail -f /data/nginx/logs/www-yqc-com_error.log
2020/12/02 13:53:10 [error] 5113#0: *65 open() "/data/nginx/yqc/www/images/tom.jpg" failed (2: No such file or directory), client: 192.168.1.9, server: www.yqc.com, request: "GET /images/tom.jpg HTTP/1.1", host: "www.yqc.com"
2.5:Nginx 应用
2.5.1:root 与 alias
root 与 alias 的区别:
-
在 location 中指定 root 时,location 指定的 URI 的文件系统路径为:root + URI;
比如:location /images { root /data/nginx/yqc/www; }
如果要访问的是 http://www.yqc.com/images/1.jpg,那么文件的路径为:
/data/nginx/yqc/www/images/1.jpg
; -
在 location 中指定 alias 时,location 指定的 URI 的文件系统路径为:alias;
比如:
location /images {
alias /data/nginx/yqc/www;
}
如果要访问的是 http://www.yqc.com/images/1.jpg,那么文件的路径为:/data/nginx/yqc/www/1.jpg
;
指定 root 与 alias
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location /images {
root /data/nginx/yqc/www;
}
location /images-alias {
alias /data/nginx/yqc/www;
}
}
- 重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备 root 测试图片:
[root@node106 ~]# mkdir /data/nginx/yqc/www/images
[root@node106 ~]# cp ironman.jpg /data/nginx/yqc/www/images/
- 准备 alias 测试图片:
[root@node106 ~]# cp batman.jpg /data/nginx/yqc/www/
访问指定了 root 的 URI
- 浏览器访问 http://www.yqc.com/images/ironman.jpg
访问指定了 alias 的 URI
- 浏览器访问 http://www.yqc.com/images-alias/batman.jpg
2.5.2:error_page 错误页面
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备错误页面:
[root@node106 ~]# mkdir /data/nginx/yqc/redirect
[root@node106 ~]# vim /data/nginx/yqc/redirect/error.html
sorry
- 访问测试:
2.5.3:try_files
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
error_log /data/nginx/logs/www-yqc-com_error.log;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location ^~ /images {
root /data/nginx/yqc/www;
try_files $uri $uri.jpg /images/default.jpg;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备测试图片:
[root@node106 ~]# ll /data/nginx/yqc/www/images/
total 1372
-rw-r--r-- 1 root root 1113986 Dec 2 12:37 batman.JPG
-rw-r--r-- 1 root root 31912 Dec 2 14:20 default.jpg
-rw-r--r-- 1 root root 254358 Dec 2 09:53 ironman.jpg
- 访问不存在的文件,显示default.jpg:
- 访问不加jpg后缀的图片:
2.5.4:auto_index 显示列表
可以使用该选项配置下载服务器;
- 编辑配置文件:
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
error_log /data/nginx/logs/www-yqc-com_error.log;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location /download {
root /data/nginx/yqc/www;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
autoindex_format html;
limit_rate 1k;
}
}
配置为:
- 开启自动索引;
- 不显示文件精确大小(即以 K、M等单位显示);
- 显示为当前系统时间;
- 显示格式为 html;
- 设置每个连接的速率限制为 1KB/s;(这个限制是针对单个连接的,如果一个客户端同时开了多个连接,则总的速率限制为 limit_rate 乘以连接数)
- 准备下载目录及文件:
[root@node106 ~]# mkdir /data/nginx/yqc/www/download
[root@node106 ~]# cp /usr/local/src/nginx-1.18.0/* /data/nginx/yqc/www/download -R
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问及下载测试:
- 下载速度为 1KB/s 左右:
2.5.5:stub_status 状态页
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
error_log /data/nginx/logs/www-yqc-com_error.log;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
}
配置:
- 仅允许192.168.1.0/24 和 本地访问状态页;
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问状态页:
2.5.6:favicon.ico 网站图标
浏览器发送请求时,会自动请求获取页面的图标文件;
如果图标文件不存在,会产生 404 错误;
设置不记录错误日志
- 查看修改前的错误日志:
2020/12/03 11:31:23 [error] 4460#0: *28 open() "/data/nginx/yqc/www/favicon.ico" failed (2: No such file or directory), client: 192.168.1.9, server: www.yqc.com, request: "GET /favicon.ico HTTP/1.1", host: "www.yqc.com", referrer: "https://www.yqc.com/"
- 修改配置文件:
[root@node106 ~]# cat /apps/nginx/conf.d/www.yqc.com.conf
server {
……
location = /favicon.ico {
log_not_found off;
access_log off;
}
}
配置 URI 为 /favicon.ico 时:
- 不记录“文件未找到”的错误日志;
- 不记录访问日志;
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看是否有新的错误日志
设置网站图标
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
……
location = /favicon.ico {
root /data/nginx/yqc/www/images;
#log_not_found off;
access_log off;
expires 90d;
}
}
- 准备图标文件:
[root@node106 ~]# mv buding.jpg /data/nginx/yqc/www/images/favicon.ico
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试:
三:Nginx 高级配置实践
3.1:Nginx 编译安装第三方模块
第三模块是对nginx 的功能扩展;
第三⽅模块需要在编译安装Nginx 的时候使⽤参数–add-module=PATH指定路径添加;
nginx⽀持第三⽅模块需要从源码重新编译⽀持;
有的模块是由公司的开发⼈员针对业务需求定制开发的,有的模块是开源爱好者开发好之后上传到github进⾏开源的模块;
3.1.1:echo 模块
https://github.com/openresty/echo-nginx-module
克隆
- 安装 git:
[root@node106 ~]# yum install git -y
- 从 github 克隆echo模块:
[root@node106 ~]# cd /usr/local/src
[root@node106 src]# git clone https://github.com/openresty/echo-nginx-module.git
[root@node106 src]# ll echo-nginx-module/
total 76
-rw-r--r-- 1 root root 3184 Dec 2 16:33 config
-rw-r--r-- 1 root root 1345 Dec 2 16:33 LICENSE
-rw-r--r-- 1 root root 54502 Dec 2 16:33 README.markdown
drwxr-xr-x 2 root root 4096 Dec 2 16:33 src
drwxr-xr-x 2 root root 4096 Dec 2 16:33 t
drwxr-xr-x 2 root root 52 Dec 2 16:33 util
-rw-r--r-- 1 root root 986 Dec 2 16:33 valgrind.suppress
重新编译安装 Nginx
- 查看 nginx 之前的编译参数:
[root@node106 ~]# nginx -V
nginx version: nginx/1.18.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=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
[root@node106 ~]#
- 添加 echo 模块,重新生成 Makefile:
[root@node106 ~]# cd /usr/local/src/nginx-1.18.0/
[root@node106 nginx-1.18.0]# ./configure \
--prefix=/apps/nginx \
--user=nginx --group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--add-module=/usr/local/src/echo-nginx-module
- 重新编译安装 nginx:
[root@node106 nginx-1.18.0]# make && make install
测试 echo 模块
- 编译配置文件:
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log;
error_log /data/nginx/logs/www-yqc-com_error.log;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
location /main {
index index.html;
default_type text/html;
echo "hello world,main-->";
echo_reset_timer;
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 1;
echo sub1;
}
location /sub2 {
echo_sleep 1;
echo sub2;
}
}
- 检查配置文件并重启nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl restart nginx
新装模块需要重启生效;
- 访问测试:
[root@node105 ~]# curl http://www.yqc.com/main
hello world,main-->
sub1
sub2
took 2.003 sec for total.
3.1.2:concat 模块(Tengine)
⽹站中的css、js等⽂件都是⼩⽂件,单个⽂件⼤⼩⼏k甚⾄⼏个字节,所以⽂件的特点是⼩⽽多,会造成⽹站加载时http请求较多,且⽹络传输时间⽐较短,甚⾄有时候请求时间⽐传输时间还长;
当公司⽹站中的这类⼩⽂件很多时,⼤量的http请求就会造成传输效率低,影响⽹站的访问速度和客⼾端体验,这时合并http请求就⾮常有必要了;
concat模块就提供了合并⽂件http请求的功能,这个模块由淘宝开发,功能和apache的mod_concat模块类似。
编译 concat 动态模块
- 安装 lua 和 lua-devel:
[root@node105 ~]# yum install lua lua-devel
- 查看之前的 tengine 编译参数
[root@node105 ~]# nginx -V
Tengine version: Tengine/2.1.2 (nginx/1.6.2)
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
TLS SNI support enabled
configure arguments: --prefix=/apps/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-file-aio --with-ipv6
loaded modules:
ngx_core_module (static)
ngx_errlog_module (static)
……
- 重新编译 tengine,将concat和lua编译为动态模块:
[root@node105 ~]# cd /usr/local/src/tengine-2.1.2/
[root@node105 tengine-2.1.2]# ./configure --prefix=/apps/tengine \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-file-aio \
--with-ipv6 \
--with-http_lua_module=shared \
--with-http_concat_module=shared
[root@node105 tengine-2.1.2]# make
- 安装动态模块:
[root@node105 tengine-2.1.2]# make dso_install
关于 make dso_install
的官方说明:
它将会复制动态库文件到你的动态模块目录,或者你也可以手工拷贝动态模块文件(文件是在objs/modules)到你想要加载的目录.
你能够使用dso_tool(在Nginx安装目录的sbin下)这个工具来编译第三方模块.
示例
./dso_tool --add-module=/home/dso/lua-nginx-module
将会编译ngx_lua模块为动态库,然后安装到默认的模块路径.如果你想要安装到指定位置,那么需要指定–dst选项(更多的选项请使用dso_tool -h查看).
加载 concat 动态模块
- 查看模块文件:
[root@node105 ~]# ll /apps/tengine/modules/
total 2784
-rwxr-xr-x 1 root root 93937 Dec 5 18:04 ngx_http_concat_module.so
-rwxr-xr-x 1 root root 2755475 Dec 5 18:04 ngx_http_lua_module.so
- 编辑配置文件,加载 concat 动态模块:
dso {
load ngx_http_concat_module.so;
load ngx_http_lua_module.so;
}
- 检查配置文件并重载 tengine:
[root@node105 ~]# nginx -t
the configuration file /apps/tengine/conf/nginx.conf syntax is ok
configuration file /apps/tengine/conf/nginx.conf test is successful
[root@node105 ~]# systemctl reload nginx
验证 concat 模块
- 编辑配置文件,加入 concat 模块参数:
location / {
root html;
index index.html index.htm;
concat on;
}
- 检查配置文件并重载 tengine:
[root@node105 ~]# nginx -t
the configuration file /apps/tengine/conf/nginx.conf syntax is ok
configuration file /apps/tengine/conf/nginx.conf test is successful
[root@node105 ~]# systemctl reload nginx
未报错,表示已支持 concat 功能;
3.2:Nginx 自定义访问日志
3.2.1:Nginx 内置变量
-
$remote_addr
客户端地址(公网IP,有可能是代理服务器的 IP); -
$args
URL 中的指令参数; -
$document_root
所请求的资源对应的 root 路径; -
d o c u m e n t u r i U R L 中 的 U R I ( 不 包 含 指 令 参 数 ) ; 即 s e r v e r n a m e 、 document_uri URL中的URI(不包含指令参数); 即server_name、 documenturiURL中的URI(不包含指令参数);即servername、document_uri 和 $args 组成完整的 URL;
-
$host
请求的Host; -
$http_user_agent
客户端的浏览器信息; -
$http_cookie
客户端的cookie信息; -
$limit_rate
limit_rate的值(未设置则显示默认值0); -
$remote_port
客户端的请求端口; -
$remote_user
通过basic验证的用户名; -
$request_body_file
nginx作为反向代理时,请求的后端服务器上的本地资源名称; -
$request_method
请求资源所用的method(GET、HEAD、PUT等); -
$request_filename
请求资源在文件系统上的绝对路径; -
$request_uri
请求的完整URI;
$document_uri 和 $args 组成 $request_uri; -
$scheme
请求的协议,如http、https、ftp等; -
$server_protocol
请求资源所用的协议(包括版本),如HTTP/1,0、HTTP/1,1、HTTP/2.0等; -
$server_addr
服务器的IP地址; -
$server_name
server_name指定的虚拟服务器名称; -
$server_port
服务端的监听端口; -
$upstream_cache_status
缓存状态;·MISS 未命中,请求被传送到后端 ·HIT 缓存命中 ·EXPIRED 缓存已经过期请求被传送到后端 ·UPDATING 正在更新缓存,将使用旧的应答 ·STALE 后端将得到过期的应答
-
$proxy_add_x_forwarded_for
KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for变量…remote_addr用逗号分开:
- X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息。
X-Forwarded-For 的记录格式:client1, proxy1, proxy2
X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个。
在默认情况下,Nginx并不会对X-Forwarded-For头做任何的处理,除非用户使用proxy_set_header 参数设置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
如果没有"X-Forwarded-For" 请求头,则KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for等于remote_addr($remote_addr变量的值是客户端的IP);
当Nginx设置X-Forwarded-For于$proxy_add_x_forwarded_for后会有两种情况发生:
1、如果从CDN过来的请求没有设置X-Forwarded-For头(通常这种事情不会发生),而到了我们这里Nginx设置将其设置为$proxy_add_x_forwarded_for的话,X-Forwarded-For的信息应该为CDN的IP,因为相对于Nginx负载均衡来说客户端即为CDN,这样的话,后端的web程序时死活也获得不了真实用户的IP的。
2、CDN设置了X-Forwarded-For,我们这里又设置了一次,且值为$proxy_add_x_forwarded_for的话,那么X-Forwarded-For的内容变成 ”客户端IP,Nginx负载均衡服务器IP“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的第一项即可。
- X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息。
-
$http_x_forwarded_for
Nginx中还有一个$http_x_forwarded_for变量,这个变量中保存的内容就是请求中的X-Forwarded-For信息。如果后端获得X-Forwarded-For信息的程序兼容性不好的话(没有考虑到X-Forwarded-For含有多个IP的情况),最好就不要将X-Forwarded-For设置为 KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for。应…http_x_forwarded_for或者干脆不设置。
-
$fastcgi_script_name
此变量保存的是请求的 URI,或者是以 / 结尾的 URI(即访问的是默认主页);比如在
location ~ \.php$
中配置root /data/nginx/yqc/www;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name
;
当访问的 URI 为/appv1/test.php
时,
$document_root 指向 /data/nginx/yqc/www,
$fastcgi_script_name 指向 /appv1/test.php,
最终 SCRIPT_FILENAME 的值,即请求的 URI 指向的文件系统路径为:/data/nginx/yqc/www/appv1/test.php;$fastcgi_script_name
request URI or, if a URI ends with a slash, request URI with an index file name configured by the fastcgi_index directive appended to it. This variable can be used to set the
SCRIPT_FILENAME
andPATH_TRANSLATED
parameters that determine the script name in PHP. For example, for the “/info/
” request with the following directivesfastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
the
SCRIPT_FILENAME
parameter will be equal to “/home/www/scripts/php/info/index.php
”.When using the fastcgi_split_path_info directive, the
$fastcgi_script_name
variable equals the value of the first capture set by the directive.
3.2.2:Nginx 自定义变量
Syntax: set $variable value;
Default: —
Context: server, location, if
示例:
set $name magedu;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port";
3.2.3:自定义默认格式的访问日志
- 定义日志格式:
[root@node106 ~]# vim /apps/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format format1 '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
include /apps/nginx/conf.d/*.conf;
}
- 调用日志格式:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log format1;
error_log /data/nginx/logs/www-yqc-com_error.log;
limit_rate 1024;
location / {
root /data/nginx/yqc/www;
index index.html;
limit_rate 1024;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看日志:
[root@node106 ~]# !tail
tail -f /data/nginx/logs/www-yqc-com_access.log
192.168.1.9 - user1 [02/Dec/2020:18:12:31 +0800] "GET / HTTP/1.1"200 8 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" "-"www.yqc.com:80
3.2.4:自定义 json 格式的访问日志
定义为 json 格式的访问日志,方便后期配合 ELK 对日志进行收集、统计和分析;
- 定义 json 日志格式:
[root@node106 ~]# vim /apps/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format format1 '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
log_format format2 '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
include /apps/nginx/conf.d/*.conf;
}
- 调动 json 日志格式:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access.log format2;
error_log /data/nginx/logs/www-yqc-com_error.log;
limit_rate 1024;
location / {
root /data/nginx/yqc/www;
index index.html;
limit_rate 1024;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看日志:
[root@node106 ~]# tail -f /data/nginx/logs/www-yqc-com_access.log
{"@timestamp":"2020-12-02T20:45:10+08:00","host":"192.168.1.106","clientip":"192.168.1.9","size":0,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.yqc.com","uri":"/index.html","domain":"www.yqc.com","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36","status":"304"}
3.3:Nginx 压缩
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name www.yqc.com;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access_json.log format2;
error_log /data/nginx/logs/www-yqc-com_error.log;
gzip on;
gzip_comp_level 3;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
}
配置:
- 开启 gzip;
- 压缩级别为 3;
- 启用压缩的最小文件大小为 1k;
- 定义压缩文件媒体类型;
- 启用 gzip_vary,在响应头部中显示“Vary: Accept-Encoding” ;
- 检查配置文件并重置nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备测试文件:
[root@node106 ~]# ll -h /var/log/messages
-rw-------. 1 root root 457K Dec 2 22:27 /var/log/messages
[root@node106 ~]# cp /var/log/messages /data/nginx/yqc/www/messages.html
- 验证压缩:
[root@node105 ~]# curl --head --compressed http://www.yqc.com/messages.html
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Wed, 02 Dec 2020 14:37:13 GMT
Content-Type: text/html
Last-Modified: Wed, 02 Dec 2020 14:28:38 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/"5fc7a496-721cf"
Content-Encoding: gzip
- 验证小于1k的文件不执行压缩:
[root@node106 ~]# ll /data/nginx/yqc/www/index.html -h
-rw-r--r-- 1 nginx nginx 8 Dec 2 09:33 /data/nginx/yqc/www/index.html
[root@node105 ~]# curl --head --compressed http://www.yqc.com/index.html
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Wed, 02 Dec 2020 14:37:58 GMT
Content-Type: text/html
Content-Length: 8
Last-Modified: Wed, 02 Dec 2020 01:33:03 GMT
Connection: keep-alive
ETag: "5fc6eecf-8"
Accept-Ranges: bytes
3.4:Nginx 实现 https
3.4.1:构建私有 CA
证书颁发机构(CA, Certificate Authority);
这里生成一个私钥 Key 和 自签名的 crt 证书,将自己作为一个私有 CA,后续为自己颁发 CA 证书;
- 生成私有 CA 的私钥和自签名证书:
umask 077:设置创建文件或目录时的 umask 为 077,即创建的文件权限为 600,目录权限为 700;
[root@node106 ~]# (umask 077; openssl req -newkey rsa:4096 -nodes -sha256 -keyout /etc/pki/CA/private/ca.key -x509 -days 3650 -out /etc/pki/CA/ca.crt)
Generating a 4096 bit RSA private key
...............................++
...........................................................................................................................................++
writing new private key to '/etc/pki/CA/private/ca.key'
-----
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) []:Shanxi
Locality Name (eg, city) [Default City]:Taiyuan
Organization Name (eg, company) [Default Company Ltd]:yqc
Organizational Unit Name (eg, section) []:Ops
Common Name (eg, your name or your server's hostname) []:yqc.ca
Email Address []:20251839@qq.com
- 查看私钥和自签名 CA 证书:
[root@node106 ~]# ll /etc/pki/CA/private/ca.key
-rw------- 1 root root 3272 Dec 3 10:12 /etc/pki/CA/private/ca.key
[root@node106 ~]# ll /etc/pki/CA/ca.crt
-rw------- 1 root root 2074 Dec 3 10:12 /etc/pki/CA/ca.crt
3.4.2:生成私钥和证书签署请求
csr 表示 Certificate Signature Request,证书签署请求;
- 创建ssl目录(用于存放私钥和证书):
[root@node106 ~]# mkdir /apps/nginx/ssl
- 生成私钥和csr:
[root@node106 ~]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout /apps/nginx/ssl/www.yqc.com.key -out /apps/nginx/ssl/www.yqc.com.csr
Generating a 4096 bit RSA private key
...................++
..........................++
writing new private key to '/apps/nginx/ssl/www.yqc.com.key'
-----
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) []:Shanxi
Locality Name (eg, city) [Default City]:Taiyuan
Organization Name (eg, company) [Default Company Ltd]:yqc.com
Organizational Unit Name (eg, section) []:Ops
Common Name (eg, your name or your server's hostname) []:www.yqc.com
Email Address []:20251839@qq.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
- 查看生成的文件:
[root@node106 ~]# ll /apps/nginx/ssl/
total 8
-rw------- 1 root root 1740 Dec 3 10:27 www.yqc.com.csr
-rw------- 1 root root 3272 Dec 3 10:27 www.yqc.com.key
3.4.3:签发证书
- 使用私有 CA 签发证书:
[root@node106 ~]# openssl x509 -req -days 3650 -in /apps/nginx/ssl/www.yqc.com.csr -CA /etc/pki/CA/ca.crt -CAkey /etc/pki/CA/private/ca.key -CAcreateserial -out /apps/nginx/ssl/www.yqc.com.crt
Signature ok
subject=/C=CN/ST=Shanxi/L=Taiyuan/O=yqc.com/OU=Ops/CN=www.yqc.com/emailAddress=20251839@qq.com
Getting CA Private Key
- 验证证书序列号和登记内容:
[root@node106 ssl]# openssl x509 -in /apps/nginx/ssl/www.yqc.com.crt -noout -serial -subject
serial=FA5590CFB34CBE92
subject= /C=CN/ST=Shanxi/L=Taiyuan/O=yqc.com/OU=Ops/CN=www.yqc.com/emailAddress=20251839@qq.com
[root@node106 ssl]# cat /etc/pki/CA/ca.srl
FA5590CFB34CBE92
3.4.4:www.yqc.com 的 https 访问
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/www.yqc.com.conf
server {
# listen 192.168.1.106:80;
listen 192.168.1.106:443;
server_name www.yqc.com;
ssl_certificate /apps/nginx/ssl/www.yqc.com.crt;
ssl_certificate_key /apps/nginx/ssl/www.yqc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access_json.log format2;
error_log /data/nginx/logs/www-yqc-com_error.log;
gzip on;
gzip_comp_level 3;
gzip_min_length 1k;
gzip_types text/plain text/html application/javascript application/x-javascript text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 测试访问:
- 继续访问:
- 查看证书信息:
3.4.5:wap.yqc.com 的 https 访问
- 生成私钥和证书签署申请:
[root@node106 ~]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout /apps/nginx/ssl/wap.yqc.com.key -out /apps/nginx/ssl/wap.yqc.com.csr
Generating a 4096 bit RSA private key
..........................................................................................................................++
..................................................................................++
writing new private key to '/apps/nginx/ssl/wap.yqc.com.key'
-----
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) []:Shanxi
Locality Name (eg, city) [Default City]:Taiyuan
Organization Name (eg, company) [Default Company Ltd]:yqc
Organizational Unit Name (eg, section) []:Ops
Common Name (eg, your name or your server's hostname) []:wap.yqc.com
Email Address []:20251839@qq.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
- 签发证书:
[root@node106 ~]# openssl x509 -req -days 3650 -in /apps/nginx/ssl/wap.yqc.com.csr -CA /etc/pki/CA/ca.crt -CAkey /etc/pki/CA/private/ca.key -CAcreateserial -out /apps/nginx/ssl/wap.yqc.com.crt
Signature ok
subject=/C=CN/ST=Shanxi/L=Taiyuan/O=yqc/OU=Ops/CN=wap.yqc.com/emailAddress=20251839@qq.com
Getting CA Private Key
- 配置 nginx:
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
# listen 192.168.1.106:80;
listen 192.168.1.106:443 ssl;
server_name wap.yqc.com;
ssl_certificate /apps/nginx/ssl/wap.yqc.com.crt;
ssl_certificate_key /apps/nginx/ssl/wap.yqc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
root /data/nginx/yqc/wap;
}
}
- 检查配置文件并重置 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 验证访问:
3.5:Nginx 防盗链
盗链的定义:
如果别⼈只链接了⾃⼰网站的某个单独资源,⽽不是打开了⽹站的整个页⾯,就是盗链;$http_referer 变量中记录的就是链接自己站点的网站域名;
通过定义 valid_referer 的值,来定义有效的 referer;
valid_referer 的值包括以下几种类型:
- none:请求报⽂⾸部没有referer⾸部,⽐如⽤⼾直接在浏览器输⼊域名访问web⽹站,就没有referer信息。
- blocked:请求报⽂有referer⾸部,但⽆有效值,⽐如为空。
- server_names:referer⾸部中包含本主机名及即nginx 监听的server_name。
- arbitrary_string:⾃定义指定字符串,可使⽤*作通配符。
- regular expression:被指定的正则表达式模式匹配到的字符串,要使⽤
~
开头。相关内置变量:
- $invalid_referer,如果访问资源命中 valid_refer 所记录的 referer 类型,则为空;否则为 1;
3.5.1:盗链演示
模拟场景:
wap.yqc.com 盗取 www.yqc.com 下的 /images/ironman.jpg;
- 编辑盗链页面:
[root@node106 ~]# vim /data/nginx/yqc/wap/test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>盗链页面</title>
</head>
<body>
<a href="http://www.yqc.com">测试盗链</a>
<img src="http://www.yqc.com/images/ironman.jpg">
</body>
</html>
- 访问测试:
http://wap.yqc.com/test.html
-
查看www.yqc.com访问日志:
“referer”:“http://wap.yqc.com/”
{"@timestamp":"2020-12-04T11:08:14+08:00","host":"192.168.1.106","clientip":"192.168.1.9","size":249006,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.yqc.com","uri":"/images/ironman.jpg","domain":"www.yqc.com","xff":"-","referer":"http://wap.yqc.com/","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36","status":"200"}
3.5.2:防盗链配置
- 在 www.yqc.com 的 location /images配置中定义防盗链配置:
location /images {
root /data/nginx/yqc/www;
index index.html;
valid_referers none blocked server_names ~\.google\. ~\.baidu\.;
if ( $invalid_referer = 1 ) {
return 403;
}
}
- 检查配置文件并重置 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问盗链测试页面:
- 查看日志:
{"@timestamp":"2020-12-04T11:37:50+08:00","host":"192.168.1.106","clientip":"192.168.1.9","size":555,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.yqc.com","uri":"/images/ironman.jpg","domain":"www.yqc.com","xff":"-","referer":"http://wap.yqc.com/","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36","status":"403"}
3.6:Nginx 转发 FastCGI 请求
CGI 和 FastCGI:
CGI,Common Gateway Interface,通用网关接口,Nginx 基于 CGI 协议转发客户端的动态资源请求至 PHP 程序,由这些程序处理完请求后,返回结果给 Nginx,再由 Nginx 返回客户端相应的数据;
早期的 CGI 协议,对于每一个请求都会创建一个 CGI 进程,解析并处理完毕后再关闭进程,效率很低;
FastCGI 处理完请求后,不会立即关闭进程,而是保留并继续处理新的请求,使得不用反复创建新的进程,提升了处理效率;
php-fpm:
FPM,FastCGI Process Manager,FastCGI 进程管理器,提供 FastCGI 进程启动和管理的功能;
FastCGI 的进程运行模式为 master-worker 模式:
- 一个 master 进程,负责监听并接收来自 web 服务转发的客户端请求;
- 多个 worker 进程,每个 worker 进程都有一个 PHP 解析器,用于 PHP 代码的解析处理;
Nginx 的 FastCGI 相关功能由 ngx_http_fastcgi_module 模块提供;
3.6.1:准备 PHP 环境
安装 php-fpm
- yum 安装 php-fpm:
[root@node106 ~]# yum install php-fpm -y
配置 php-fpm
-
php-fpm.conf:
修改
daemonize = yes
,设置为后台启动;
[root@node106 ~]# grep -v ';' /etc/php-fpm.conf | grep -v '^$'
include=/etc/php-fpm.d/*.conf
[global]
pid = /run/php-fpm/php-fpm.pid
error_log = /var/log/php-fpm/error.log
daemonize = yes
-
www.conf:
-
启动 php-fpm worker 进程的用户要和启动 nginx worker 进程的用户一致,因为涉及文件权限问题;
-
当 php-fpm 和 nginx 不在同一服务器时,需要:
- 设置 fastcgi 监听在可通信的 IP 地址上,或者直接监听所有地址
listen = 0.0.0.0:9000
; - 注释
listen.allowed_clients = 127.0.0.1
,或者设置为相应的 nginx 服务器地址;
- 设置 fastcgi 监听在可通信的 IP 地址上,或者直接监听所有地址
-
pm.max_children 的值是在实行进程动态管理(
pm = dynamic
)时,能够启动的 worker 进程数的最大值; -
pm.start_servers 的值是在实行进程动态管理(
pm = dynamic
)时,初始启动的 worker 进程数,所以需要 ≥ pm.min_spare_servers 指定的最小空闲进程数,并 ≤ pm.max_spare_servers 指定的最大空闲进程数; -
pm.max_requests 的值是单个 worker 进程累计能够处理的最大请求数,当达到这个请求数后,会回收 worker 进程,并重新启动一个 worker 进程;
-
[root@node106 ~]# grep -v ';' /etc/php-fpm.d/www.conf | grep -v '^[[:space:]]*$'
[www]
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
user = nginx
group = nginx
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 5000
pm.status_path = /pm_status
ping.path = /ping
ping.response = pong
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
启动 php-fpm
- 启动 php-fpm:
[root@node106 ~]# systemctl start php-fpm
[root@node106 ~]# systemctl enable php-fpm
Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.
- 查看端口:
[root@node106 ~]# ss -tnl | grep 9000
LISTEN 0 128 127.0.0.1:9000 *:*
准备 PHP 测试页面
- 创建 php 资源目录及信息页:
[root@node106 ~]# mkdir /data/nginx/yqc/www/php
[root@node106 ~]# vim /data/nginx/yqc/www/php/index.php
<?php
phpinfo();
?>
3.6.2:Nginx 配置 FastCGI 转发
-
配置所有以 .php 结尾的 URI 请求,都转发至 php-fpm 进行处理:
定义php资源请求的根目录为 /data/nginx/yqc/www/php;
location ~ \.php$ {
root /data/nginx/yqc/www/php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /apps/nginx/conf/fastcgi_params;
}
- 配置php状态页和/ping测试的请求转发:
location ~ ^/(pm_status|ping)$ {
fastcgi_pass 127.0.0.1;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
include /apps/nginx/conf/fastcgi_params;
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# !sys
systemctl reload nginx
- 访问php信息页:
- 访问 PHP 状态页和 ping 测试:
[root@node105 ~]# curl http://www.yqc.com/pm_status
pool: www
process manager: dynamic
start time: 05/Dec/2020:16:00:44 +0800
start since: 1071
accepted conn: 9
listen queue: 0
max listen queue: 0
listen queue len: 128
idle processes: 4
active processes: 1
total processes: 5
max active processes: 2
max children reached: 0
slow requests: 0
[root@node105 ~]# curl http://www.yqc.com/ping
pong
四:Nginx Rewrite 模块
ngx_http_rewrite_module 包含的指令:
- if
- set
- break
- return
- rewrite_log
- rewrite
4.1:if 条件判断
4.1.1:文件判断
测试 if 语句,访问的资源存在则显示 “file exists.”,不存在则显示 “file doesn’t exist.”;
- 编辑配置文件:
server {
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
if ( -f $request_filename ) {
echo "file exists.";
}
if ( !-f $request_filename ) {
echo "file doesn't exist.";
}
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备测试文件:
[root@node106 ~]# cp /etc/fstab /data/nginx/yqc/www/echo/fstab.html
- 测试访问存在的资源:
- 测试访问不存在的资源:
4.1.2:条件判断
判断访问所用协议,如果是 http,则显示 “if_http: http”,如果是 https,则显示 “if_https: https”;
- 编辑配置文件:
server {
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
# if ( -f $request_filename ) {
# echo "file exists.";
# }
# if ( !-f $request_filename ) {
# echo "file doesn't exist.";
# }
if ( $scheme = http ) {
echo "if_http: $scheme";
}
if ( $scheme = https ) {
echo "if_https: $scheme";
}
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试:
https://www.yqc.com/echo/fstab.html
4.2:set 自定义变量
- 编辑配置文件:
server {
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
set $name www.yqc.com;
set $nginx_port $server_port;
echo "$name:$nginx_port";
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试:
4.3:break 中断
测试 break 只会中断同一 location 中的 ngx_http_rewrite_module 模块中的指令,其它指令则继续运行;
- 编辑配置文件:
server {
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
set $name www.yqc.com;
echo $name;
break;
set $nginx_port $server_port;
echo "$name:$nginx_port";
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
break 并未中断后边的 echo 指令,但却中断了后边的 set 指令,使得显示时 $nginx_port 的值为空;
4.4:return
测试 return 只会中断同一作用区域的所有指令,对自身所在作用区域之外的指令没有影响;
4.4.1:return in if
- 编辑配置文件:
server {
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
if ( -f $request_filename ) {
echo "file exists.";
return 666 "return test";
}
if ( !-f $request_filename ) {
echo "file doesn't exist.";
}
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问存在的资源:
返回 return 的提示信息,并返回状态码 666;
-
访问不存在的资源:
echo 指令正常显示;
4.4.2:return in location
测试将 return 上提一层,放在 location 中的效果;
- 编辑配置文件:
server {
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
echo "return failed.";
if ( -f $request_filename ) {
echo "file exists.";
}
if ( !-f $request_filename ) {
echo "file doesn't exist.";
}
return 666 "return test";
echo "return failed.";
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
该 location 中的所有 echo 指令均未执行;
访问 server 下的其它资源,不受影响;
4.4.3:return in server
继续上提一层,放在 server 中,测试该 server 的其它页面是否可以访问;
- 编辑配置文件:
[root@node106 ~]# cat /apps/nginx/conf.d/www.yqc.com.conf
server {
# listen 192.168.1.106:80;
listen 192.168.1.106:443 ssl;
server_name www.yqc.com;
ssl_certificate /apps/nginx/ssl/www.yqc.com.crt;
ssl_certificate_key /apps/nginx/ssl/www.yqc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access_json.log format2;
error_log /data/nginx/logs/www-yqc-com_error.log;
gzip on;
gzip_comp_level 3;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
location / {
root /data/nginx/yqc/www;
index index.html;
}
location = /error.html {
root /data/nginx/yqc/redirect;
}
location = /status {
stub_status;
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
}
location = /favicon.ico {
root /data/nginx/yqc/www/images;
#log_not_found off;
access_log off;
expires 90d;
}
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
echo "return failed.";
if ( -f $request_filename ) {
echo "file exists.";
}
if ( !-f $request_filename ) {
echo "file doesn't exist.";
}
echo "return failed.";
}
return 666 "return test";
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
测试访问:
访问该 server 的所有资源,均返回 666;
4.5:rewrite_log
开启 rewrite 模块日志,查看相应日志内容;
- 开启 rewrite_log,并设置 error_log 的级别为 notice:
[root@node106 ~]# cat /apps/nginx/conf.d/www.yqc.com.conf
server {
……
error_log /data/nginx/logs/www-yqc-com_error.log notice;
……
location /echo {
root /data/nginx/yqc/www;
default_type text/html;
rewrite_log on;
set $name www.yqc.com;
echo $name;
break;
set $nginx_port $server_port;
echo "$name:$nginx_port";
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并触发 break 指令,查看日志:
https://www.yqc.com/echo
[root@node106 ~]# tail -f /data/nginx/logs/www-yqc-com_error.log
2020/12/03 17:00:53 [warn] 21064#0: *31 using uninitialized "nginx_port" variable, client: 192.168.1.9, server: www.yqc.com, request: "GET /echo HTTP/1.1", host: "www.yqc.com"
4.6:rewrite 重定向
4.6.1:redirect 临时重定向
将 wap.yqc.com 临时重定向至 www.baidu.com,查看响应状态码;
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
# listen 192.168.1.106:80;
listen 192.168.1.106:443 ssl;
server_name wap.yqc.com;
ssl_certificate /apps/nginx/ssl/wap.yqc.com.crt;
ssl_certificate_key /apps/nginx/ssl/wap.yqc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
root /data/nginx/yqc/wap;
index index.html;
rewrite / http://www.baidu.com redirect;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看响应状态码:
4.6.2:permanent 永久重定向
将 wap.yqc.com 永久重定向至 www.baidu.com,查看响应状态码;
永久重定向会缓存 A 记录,即浏览器会保存此次 DNS 的解析记录;而临时重定向则不会;
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
# listen 192.168.1.106:80;
listen 192.168.1.106:443 ssl;
server_name wap.yqc.com;
ssl_certificate /apps/nginx/ssl/wap.yqc.com.crt;
ssl_certificate_key /apps/nginx/ssl/wap.yqc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
root /data/nginx/yqc/wap;
index index.html;
# rewrite / http://www.baidu.com redirect;
rewrite / http://www.baidu.com permanent;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问并查看响应状态码:
4.6.3:标记 break 后的单次重写
测试场景:
- 访问 /break 开头的 URI,重写到 /test1 后标记 break;
- 同一个 location 中,在重写到 /test1 的指令后添加一条重写到 /test2 的指令(测试 break 后不会执行同一 location 中的 rewrite 指令);
- 在 /test1 的 location 中添加一条 rewrite 指令,重写至 /test3,(测试 break 后也会执行新的 URI 匹配到的 location 中的 rewrite 指令);
- 编辑 URI 重写规则:/break–>/test1–>/test2–>/test3,全部标记为 break(测试标记为 break 的重写 URI 只会再被 rewrite 一次,即这次连续重写只会进行到 test2);
- 将 /test1 的location 中的 rewrite 指回 /break(测试 break 不会出现循环重写);
break 后不执行同一 location 的其它 rewrite
- 编辑配置文件(测试从 /break 重写至 /test1 后,不会执行同一 location 中重写至 /test2 的指令):
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /break {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1 break;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
}
location /test2 {
root /data/nginx/yqc/wap;
index index.html;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 准备测试页面:
[root@node106 ~]# mkdir /data/nginx/yqc/wap/{break,test1,test2,test3}
[root@node106 ~]# vim /data/nginx/yqc/wap/break/index.html
break page
[root@node106 ~]# vim /data/nginx/yqc/wap/test1/index.html
test1 page
[root@node106 ~]# vim /data/nginx/yqc/wap/test2/index.html
test2 page
[root@node106 ~]# vim /data/nginx/yqc/wap/test3/index.html
test3 page
-
访问测试 break 后不会执行同一 location 中的其它 rewrite 指令:
只重写至 /test1;
[root@node105 ~]# curl -L http://wap.yqc.com/break/
test1 page
标记为 break 的新 URI 会重新匹配 location
- 编辑配置文件,在 location /test1 中添加重写至 /test3 的 rewrite 指令:
[root@node106 ~]# cat /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
error_log /data/nginx/logs/wap-yqc-com_error.log notice;
rewrite_log on;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /break {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1 break;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test1/(.*) /test3/$1 break;
}
location /test2 {
root /data/nginx/yqc/wap;
index index.html;
}
location /test3 {
root /data/nginx/yqc/wap;
index index.html;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
重写流程:break–>test1–>test3;
[root@node105 ~]# curl -L http://wap.yqc.com/break/
test3 page
break 的重写 URI 只会再被重写一次
-
编辑配置文件:
重写流程:break–>test1–>test2–>test3
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
error_log /data/nginx/logs/wap-yqc-com_error.log notice;
rewrite_log on;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /break {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/break/(.*) /test1/$1 break;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test1/(.*) /test2/$1 break;
}
location /test2 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test2/(.*) /test3/$1 break;
}
location /test3 {
root /data/nginx/yqc/wap;
index index.html;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
重写至进行到 test2 即停止;
[root@node105 ~]# curl -L http://wap.yqc.com/break/
test2 page
- 查看 rewrite 日志:
2020/12/03 23:18:31 [notice] 21902#0: *11 "^/break/(.*)" matches "/break/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:18:31 [notice] 21902#0: *11 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:18:31 [notice] 21902#0: *11 "^/test1/(.*)" matches "/test1/index.html", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:18:31 [notice] 21902#0: *11 rewritten data: "/test2/index.html", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
break 可以防止重写循环
-
将 location /test1 中的 rewrite 规则指回 /break:
现在的 rewrite 规则形成一个循环;
location /break {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1 break;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test1/(.*) /break/$1 break;
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
两条 rewrite 规则在这次请求中都只执行了一次,URI 被重新指回 /break;
[root@node105 ~]# curl -L http://wap.yqc.com/break/
break page
- 查看重写日志:
[root@node106 ~]# tail -f /data/nginx/logs/wap-yqc-com_error.log
2020/12/03 19:08:03 [notice] 21605#0: *9 "^/break/(.*)" matches "/break/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 19:08:03 [notice] 21605#0: *9 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 19:08:03 [notice] 21605#0: *9 "^/test1/(.*)" matches "/test1/index.html", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 19:08:03 [notice] 21605#0: *9 rewritten data: "/break/index.html", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /break/ HTTP/1.1", host: "wap.yqc.com"
4.6.4:标记 last 后的多次重写
last 实际应用场景不多;
测试场景:
同一个 location 中,在重写到 /test1 的指令后添加一条重写到 /test2 的指令(测试 break 后不会执行同一 location 中的 rewrite 指令);
编辑 URI 重写规则:/last–>/test1–>/test2–>/test3–>/test4–>/test5,全部标记为 last(测试标记为 last 的重写 URI 会被连续重写多次,直至所有重写规则流程结束);
编辑 URI 重写规则:/last–>/test1–>/last……,标记为 last(测试 last 可能导致的重写循环);
模拟需要多次重写的应用场景:
appv1 改版为 appv2,后又改版为 appv3,此时如果想让仍保留着 appv1 访问路径的用户,直接访问 appv3,通过连续两个标记 break 的 rewrite 规则即可实现,即 /appv1–> /appv2 --> /appv3,因为第一次 rewrite 后生成的新 URI(/appv2 )还能在经过一次 rewrite,从而重写为 appv3;
然而如果再进行了一次版本升级,想让用户通过 /appv1 访问到 /appv4,就要通过 last 来实现多次重写了;
P.S.
当然,这种应用场景基本遇不到,因为实际中只需添加 /appv1 --> /appv4 的 rewrite 规则即可,不需要连续重写;
顶多再分别单独添加 /appv2 --> /appv4、 /appv3 --> /appv4 的 rwrite 规则,即可将所有旧版本的 URL 重定向至新版本;
last 后同样不会执行同一 location 的其它 rewrite 规则
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /last {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/last/(.*) /test1/$1 last;
rewrite ^/test1/(.*) /test2/$1 last;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
}
location /test2 {
root /data/nginx/yqc/wap;
index index.html;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
测试访问:
仅执行了 /last --> /test1 的重写,而未执行同一 location 中 /test1 --> /test2 的重写;
最终显示内容为 /test1 的内容;
[root@node105 ~]# curl -L http://wap.yqc.com/last/
test1 page
标记为 last 的新 URI 会多次匹配执行 rewrite 规则
-
编辑配置文件:
重写规则:break–>test1–>test2–>test3–>test4–>test5
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
error_log /data/nginx/logs/wap-yqc-com_error.log notice;
rewrite_log on;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /last {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/last/(.*) /test1/$1 last;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test1/(.*) /test2/$1 last;
}
location /test2 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test2/(.*) /test3/$1 last;
}
location /test3 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test3/(.*) /test4/$1 last;
}
location /test4 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test4/(.*) /test5/$1 last;
}
location /test5 {
root /data/nginx/yqc/wap;
index index.html;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
会一直重写至 test5;
[root@node105 ~]# curl -L http://wap.yqc.com/last/
test5 page
- 查看 rewrite 日志:
2020/12/03 23:41:53 [notice] 22000#0: *15 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 "^/test1/(.*)" matches "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 rewritten data: "/test2/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 "^/test2/(.*)" matches "/test2/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 rewritten data: "/test3/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 "^/test3/(.*)" matches "/test3/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 rewritten data: "/test4/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 "^/test4/(.*)" matches "/test4/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
2020/12/03 23:41:53 [notice] 22000#0: *15 rewritten data: "/test5/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yqc.com"
last 导致的重写循环
-
编辑配置文件:
形成 last<–>test1 的重写循环;
[root@node106 ~]# vim /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
error_log /data/nginx/logs/wap-yqc-com_error.log notice;
rewrite_log on;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /last {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/last/(.*) /test1/$1 last;
}
location /test1 {
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/test1/(.*) /last/$1 last;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
-
访问测试:
报 500 错误;
[root@node105 ~]# curl -L http://wap.yqc.com/last/
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
-
查看 rewrite 日志:
在第一次重写为 /test1 后,又执行了 10次重写操作,最后报 500 错误;
1 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yq
c.com"
2 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "w
ap.yqc.com"
3 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/test1/(.*)" matches "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.
yqc.com"
4 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/last/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wa
p.yqc.com"
5 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yq
c.com"
6 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "w
ap.yqc.com"
7 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/test1/(.*)" matches "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.
yqc.com"
8 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/last/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wa
p.yqc.com"
9 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yq
c.com"
10 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "w
ap.yqc.com"
11 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/test1/(.*)" matches "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.
yqc.com"
12 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/last/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wa
p.yqc.com"
13 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yq
c.com"
14 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "w
ap.yqc.com"
15 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/test1/(.*)" matches "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.
yqc.com"
16 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/last/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wa
p.yqc.com"
17 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yq
c.com"
18 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "w
ap.yqc.com"
19 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/test1/(.*)" matches "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.
yqc.com"
20 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/last/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wa
p.yqc.com"
21 2020/12/03 23:54:47 [notice] 22025#0: *18 "^/last/(.*)" matches "/last/", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "wap.yq
c.com"
22 2020/12/03 23:54:47 [notice] 22025#0: *18 rewritten data: "/test1/", args: "", client: 192.168.1.105, server: wap.yqc.com, request: "GET /last/ HTTP/1.1", host: "w
ap.yqc.com"
23 2020/12/03 23:54:47 [error] 22025#0: *18 rewrite or internal redirection cycle while processing "/test1/", client: 192.168.1.105, server: wap.yqc.com, request: "GE
T /last/ HTTP/1.1", host: "wap.yqc.com"
模拟用到 last 多次重写的场景
appv1 改版为 appv2,后又改版为 appv3,此时如果想让仍保留着 appv1 访问路径的用户,直接访问 appv3,通过连续两个标记 break 的 rewrite 规则即可实现,即 /appv1–> /appv2 --> /appv3,因为第一次 rewrite 后生成的新 URI(/appv2 )还能在经过一次 rewrite,从而重写为 appv3;
然而如果再进行了一次版本升级,想让用户通过 /appv1 访问到 /appv4,就要通过 last 来实现多次重写了;需要在追加 /appv3 --> /appv4 的重写规则时,将 /appv2 --> /appv3 的重写规则标记为 last;
P.S.
当然,这种应用场景基本遇不到,因为实际中只需添加 /appv1 --> /appv4 的 rewrite 规则即可,不需要连续重写;
顶多再分别单独添加 /appv2 --> /appv4、 /appv3 --> /appv4 的 rwrite 规则,即可将所有旧版本的 URL 重定向至新版本;
- 编辑配置文件:
[root@node106 ~]# cat /apps/nginx/conf.d/wap.yqc.com.conf
server {
listen 192.168.1.106:80;
server_name wap.yqc.com;
error_log /data/nginx/logs/wap-yqc-com_error.log notice;
rewrite_log on;
location / {
root /data/nginx/yqc/wap;
index index.html;
}
location /appv1{
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/appv1/(.*) /appv2/$1 break;
}
location /appv2{
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/appv2/(.*) /appv3/$1 last;
}
location /appv3{
root /data/nginx/yqc/wap;
index index.html;
rewrite ^/appv3/(.*) /appv4/$1 break;
}
location /appv4{
root /data/nginx/yqc/wap;
index index.html;
}
}
- 准备测试文件:
[root@node106 ~]# mkdir /data/nginx/yqc/wap/appv{1..4}
[root@node106 ~]# vim /data/nginx/yqc/wap/appv1/index.html
appv1
[root@node106 ~]# vim /data/nginx/yqc/wap/appv2/index.html
appv2
[root@node106 ~]# vim /data/nginx/yqc/wap/appv3/index.html
appv3
[root@node106 ~]# vim /data/nginx/yqc/wap/appv4/index.html
appv4
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试:
rwrite 规则如果都标记为 break,则重写至 /appv3 即停止;
将 /appv2 --> /appv3 的 rewrite 规则标记为 last,即可继续向后重写;
将 /appv3 --> /appv4 的rewrite 规则标记为 break,即可防止继续向后重写;
[root@node105 ~]# curl -L http://wap.yqc.com/appv1
appv4
4.6.5:rewrite 案例
rewrite 自动跳转 https
实现访问 http://www.yqc.com 时,自动跳转到 https://www.yqc.com;
- 编辑配置文件:
[root@node106 ~]# cat /apps/nginx/conf.d/www.yqc.com.conf
server {
listen 192.168.1.106:80;
listen 192.168.1.106:443 ssl;
server_name www.yqc.com;
ssl_certificate /apps/nginx/ssl/www.yqc.com.crt;
ssl_certificate_key /apps/nginx/ssl/www.yqc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/www-yqc-com_access_json.log format2;
error_log /data/nginx/logs/www-yqc-com_error.log notice;
gzip on;
gzip_comp_level 3;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
location / {
root /data/nginx/yqc/www;
index index.html;
if ( $scheme = http ) {
rewrite (.*) https://www.yqc.com permanent;
}
}
……
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试
rewrite 跳转默认页面
当访问的资源不存在时,自动跳转至默认页面;
- 编辑配置文件:
location / {
root /data/nginx/yqc/www;
index index.html;
if ( !-f $request_filename ) {
rewrite (.*) http://www.yqc.com/default.html;
}
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 访问测试:
五:Nginx http 反向代理
Nginx 反向代理功能涉及的模块:
- ngx_http_proxy_module: 将客⼾端的请求以http协议转发⾄指定服务器进⾏处理。
- ngx_stream_proxy_module:将客⼾端的请求以tcp协议转发⾄指定服务器处理。
- ngx_http_fastcgi_module:将客⼾端对php的请求以fastcgi协议转发⾄指定服务器助理。
- ngx_http_uwsgi_module:将客⼾端对Python的请求以uwsgi协议转发⾄指定服务器处理。
5.1:准备后端 Web 服务器
后端 Web 服务采用 httpd;
- 安装 httpd:
~]# yum install httpd -y
- 启动 httpd 并设置为开机启动
~]# systemctl start httpd
~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
- 准备测试页面:
[root@node107 ~]# echo "node107 httpd page" > /var/www/html/index.html
[root@node108 ~]# echo "node108 httpd page" > /var/www/html/index.html
- 访问测试:
[root@node105 ~]# curl http://192.168.1.107
node107 httpd page
[root@node105 ~]# curl http://192.168.1.108
node108 httpd page
5.2:proxy_pass
5.2.1:代理单台 Web 服务器
将 www.yqc.com 和 www.yqc.com/images 代理至后端 web 服务器 node107;
注意 proxy_pass 后指定的 URL,末尾代
/
和不代/
的区别:
- 代
/
,表示无论 location 指定的是哪个 URI,都直接跳转至后端服务器的根/
(即指向 httpd 服务器的 /var/www/html,在此目录下要有指定的资源);- 不代
/
,表示访问 location 指定 URI 在后端服务器中对应的相同路径(后端 web 服务器要存在相应的资源目录);
- 编辑 nginx 配置文件:
location / {
proxy_pass http://192.168.1.107:80;
}
location /images {
proxy_pass http://192.168.1.107:80;
}
- 后端 web 服务器准备相应资源目录:
[root@node107 ~]# mkdir /var/www/html/images
[root@node107 ~]# scp 192.168.1.106:/data/nginx/yqc/www/images/ironman.jpg /var/www/html/images/
-
删除 nginx 服务器的对应资源:
测试确实是从httpd返回的访问资源;
[root@node106 ~]# mv /data/nginx/yqc/www/images/ironman.jpg /root
- 重置nginx后访问测试:
[root@node105 ~]# curl www.yqc.com
node107 httpd page
http://www.yqc.com/images/ironman.jpg
- 日志:
{"@timestamp":"2020-12-04T16:54:52+08:00","host":"192.168.1.106","clientip":"192.168.1.105","size":19,"responsetime":0.002,"upstreamtime":"0.002","upstreamhost":"192.168.1.107:80","http_host":"www.yqc.com","uri":"/","domain":"www.yqc.com","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"curl/7.29.0","status":"200"}
{"@timestamp":"2020-12-04T17:09:16+08:00","host":"192.168.1.106","clientip":"192.168.1.9","size":249054,"responsetime":0.029,"upstreamtime":"0.021","upstreamhost":"192.168.1.107:80","http_host":"www.yqc.com","uri":"/images/ironman.jpg","domain":"www.yqc.com","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36","status":"200"}
- 测试 proxy_pass 指定的 URL 代
/
的效果:
location /images {
proxy_pass http://192.168.1.107:80/;
}
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# !sys
systemctl reload nginx
[root@node105 ~]# curl www.yqc.com/images/ironman.jpg
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /ironman.jpg was not found on this server.</p>
</body></html>
You have new mail in /var/spool/mail/root
[root@node105 ~]# curl www.yqc.com/images
node107 httpd page
访问 www.yqc.com/images/ironman.jpg,被代理至后端 web 服务器后,实际的URL为 http://192.168.1.107/ironman.jpg,这个资源路径是不存在的;
访问 www.yqc.com/images,实际URL 为后端 web 服务器的根路径 http://192.168.1.107;所以一般建议不要代
/
去指定后端服务器,这样可以保证前后端资源路径的一致性;
5.3:proxy_cache* 代理缓存
5.3.1:非缓存场景下的压测
- node107 准备测试页面:
[root@node107 ~]# ll -h /var/log/messages
-rw-------. 1 root root 305K Dec 4 17:30 /var/log/messages
You have new mail in /var/spool/mail/root
[root@node107 ~]# cp /var/log/messages /var/www/html/messages.html
- 安装 httpd-tools:
[root@node105 ~]# yum provides */bin/ab
httpd-tools-2.4.6-95.el7.centos.x86_64 : Tools for use with the Apache HTTP Server
Repo : base
Matched from:
Filename : /usr/bin/ab
[root@node105 ~]# yum install httpd-tools -y
-
进行压测:
以对比后续配置代理缓存后的压测结果;
[root@node105 ~]# ab -c 500 -n 5000 http://www.yqc.com/messages.html
Concurrency Level: 500
Time taken for tests: 14.377 seconds
Complete requests: 5000
Failed requests: 0
Write errors: 0
Total transferred: 1560810000 bytes
HTML transferred: 1559405000 bytes
Requests per second: 347.79 [#/sec] (mean)
Time per request: 1437.663 [ms] (mean)
Time per request: 2.875 [ms] (mean, across all concurrent requests)
Transfer rate: 106021.26 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 8.2 0 53
Processing: 69 1363 237.0 1422 1538
Waiting: 5 1355 238.2 1415 1495
Total: 76 1366 229.1 1423 1539
5.3.2:代理缓存配置
定义缓存路径及参数
-
在 http 配置段定义代理缓存:
配置:
- 定义缓存路径为 /data/nginx/proxycache;
- 缓存目录结构为 1:1:1,即三层目录结构,每层目录名均由一位十六进制数字表示,即每层可以有2^4个目录,总共可以有 16×16×16=4096 个缓存目录;
- 指定缓存名称为 proxycache,大小为 20m;
- 缓存有效时间为 120s,120s 内未被命中的缓存将被删除;
- 缓存占用的最大磁盘空间为 1g;
[root@node106 ~]# vim /apps/nginx/conf/nginx.conf
http {
……
proxy_cache_path /data/nginx/proxycache levels=1:1:1 keys_zone=proxycache:20m inactive=120s max_size=1g;
}
调用缓存
-
在 location / 中调用缓存,并设置相关参数:
配置:
- 调用缓存 proxycache;
- 向后端 web 服务器转发请求时,在报文头部添加 client,值为 $remote_addr,将客户端 ip 传送给后端服务器;
- 指定要缓存的内容为 $request_uri(即缓存用户请求的完整 URI);
- 定义状态码为 301 时,缓存时长为 1h(因为 301 永久重定向一般不会修改);
- 定义状态码为 200、302 时,缓存时长为 10m(因为 200 和 302 表示成功的访问,短时间不会产生大的变动);
- 定义其它状态码的缓存时长为 1m(这其中可能包括错误的访问缓存,故障一般会尽快处理,所以缓存不能过长,以让用户及时访问到恢复了的页面);
location / {
proxy_pass http://192.168.1.107:80;
proxy_cache proxycache;
proxy_set_header clientip $remote_addr;
proxy_cache_key $request_uri;
proxy_cache_valid 301 1h;
proxy_cache_valid 200 302 10m;
proxy_cache_valid any 1m;
}
- 检查配置文件并重载 nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# !sys
systemctl reload nginx
验证缓存效果
-
重新进行压测,对比未配置缓存时的数据(需要先访问一次压测资源,以生成缓存):
配置缓存前,每秒处理的请求数量为:347.79 个
配置缓存后,每秒处理的请求数量为:720.92 个
[root@node105 ~]# curl http://www.yqc.com/messages.html
[root@node105 ~]# ab -c 500 -n 5000 http://www.yqc.com/messages.html
Concurrency Level: 500
Time taken for tests: 6.936 seconds
Complete requests: 5000
Failed requests: 0
Write errors: 0
Total transferred: 1560810000 bytes
HTML transferred: 1559405000 bytes
Requests per second: 720.92 [#/sec] (mean)
Time per request: 693.557 [ms] (mean)
Time per request: 1.387 [ms] (mean, across all concurrent requests)
Transfer rate: 219769.85 [Kbytes/sec] received
- 查看缓存目录及文件:
[root@node106 ~]# tree /data/nginx/proxycache/
/data/nginx/proxycache/
└── 9
└── 5
└── 3
└── 478ab3190259513b48f079a5b5d8f359
3 directories, 1 file
[root@node106 ~]# ll -h /data/nginx/proxycache/9/5/3/478ab3190259513b48f079a5b5d8f359
-rw------- 1 nginx nginx 306K Dec 4 18:24 /data/nginx/proxycache/9/5/3/478ab3190259513b48f079a5b5d8f359
[root@node107 ~]# ll -h /var/www/html/messages.html
-rwxrwxrwx 1 root root 305K Dec 4 17:39 /var/www/html/messages.html
- 缓存文件头部会添加访问的响应码(用于确定此缓存文件的缓存时长):
[root@node106 ~]# head -n10 /data/nginx/proxycache/9/5/3/478ab3190259513b48f079a5b5d8f359
KEY: /messages.html
HTTP/1.1 200 OK
Date: Fri, 04 Dec 2020 10:31:13 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Fri, 04 Dec 2020 09:39:50 GMT
ETag: "4c249-5b5a04207e0f1"
Accept-Ranges: bytes
Content-Length: 311881
Connection: close
5.4:add_header 添加报文头部信息
- 编辑配置文件,添加头部信息:
location / {
proxy_pass http://192.168.1.107:80;
proxy_set_header clientip $remote_addr;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 301 1h;
proxy_cache_valid 200 302 10m;
proxy_cache_valid any 1m;
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
}
-
重载 nginx 并测试访问,查看响应头部:
第一次访问的缓存状态为 MISS,未命中缓存,因为还未生成缓存;
第二次访问的缓存状态为 HIT,表示命中缓存;
[root@node105 ~]# curl -I http://www.yqc.com/messages.html
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Fri, 04 Dec 2020 10:54:04 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 311881
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Fri, 04 Dec 2020 09:39:50 GMT
ETag: "4c249-5b5a04207e0f1"
X-Via: 192.168.1.106
X-Cache: MISS
X-Accel: www.yqc.com
Accept-Ranges: bytes
[root@node105 ~]# curl -I http://www.yqc.com/messages.html
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Fri, 04 Dec 2020 10:54:07 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 311881
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Fri, 04 Dec 2020 09:39:50 GMT
ETag: "4c249-5b5a04207e0f1"
X-Via: 192.168.1.106
X-Cache: HIT
X-Accel: www.yqc.com
Accept-Ranges: bytes
5.5:upstream 添加后端服务器组
5.5.1:实现七层负载均衡
-
定义后端服务器组(upstream 应用于 http 配置段,与 server 配置段平级):
定义一个 upstream 后端服务器组,添加两台后端 web 服务器;
upstream webserver {
server 192.168.1.107:80 weight=1 fail_timeout=5s max_fails=3;
server 192.168.1.108:80 weight=1 fail_timeout=5s max_fails=3;
}
-
www.yqc.com 的 location / 调用 webserver 服务器组:
并向后端服务器透传客户端 IP 地址;
注释代理缓存配置,以验证负载均衡效果;
location / {
proxy_pass http://webserver/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_cache proxycache;
#proxy_cache_key $request_uri;
#proxy_cache_valid 301 1h;
#proxy_cache_valid 200 302 10m;
#proxy_cache_valid any 1m;
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
}
- 重载 nginx 并访问测试:
[root@node105 ~]# curl http://www.yqc.com
node107 httpd page
[root@node105 ~]# curl http://www.yqc.com
node108 httpd page
[root@node105 ~]# curl http://www.yqc.com
node107 httpd page
[root@node105 ~]# curl http://www.yqc.com
node108 httpd page
5.5.2:查看客户端 IP 透传日志
-
更改后端httpd 的日志格式:
combined 日志格式中添加 X-Forwarded-For;
[root@node107 ~]# vim /etc/httpd/conf/httpd.conf
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[root@node107 ~]# systemctl restart httpd
- 访问并查看后端httpd日志,验证客户端 IP 透传效果:
[root@node107 ~]# tail -f /var/log/httpd/access_log
# 从 192.168.1.105 用curl访问的日志:
192.168.1.105 192.168.1.106 - - [05/Dec/2020:11:03:54 +0800] "GET / HTTP/1.0" 200 19 "-" "curl/7.29.0"
# 从 192.168.1.9 用chrome访问的日志:
192.168.1.9 192.168.1.106 - - [05/Dec/2020:11:20:24 +0800] "GET / HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
- 如果后端 web 服务是 nginx,则main配置格式默认就有 $http_x_forwarded_for,其中同样记录了请求中的X-Forwarded-For信息:
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;
- 将 node108 的web服务改为 nginx:
[root@node108 ~]# yum install epel-release -y
[root@node108 ~]# yum install nginx -y
[root@node108 ~]# systemctl stop httpd
[root@node108 ~]# systemctl start nginx
[root@node108 ~]# cp /var/www/html/index.html /usr/share/nginx/html/index.html
- 访问并查看nginx日志,验证客户端 IP 透传效果:
[root@node108 ~]# tail -f /var/log/nginx/access.log
# 从 192.168.1.105 用curl访问的日志:
192.168.1.106 - - [05/Dec/2020:11:50:32 +0800] "GET / HTTP/1.0" 200 19 "-" "curl/7.29.0" "192.168.1.105"
# 从 192.168.1.9 用chrome访问的日志:
192.168.1.106 - - [05/Dec/2020:11:50:46 +0800] "GET / HTTP/1.0" 200 19 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "192.168.1.9"
六:Nginx tcp 负载均衡
6.1:主配置文件添加 stream 配置段
- 编辑nginx.conf,添加 stream 配置段:
[root@node106 ~]# vim /apps/nginx/conf/nginx.conf
stream {
log_format stream '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
include /apps/nginx/stream_conf.d/*.conf;
}
-
创建 stream 配置文件目录:
以实现 stream 相关的配置文件模块化;
[root@node106 ~]# mkdir /apps/nginx/stream_conf.d/
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
6.2:Redis 负载均衡
6.2.1:后端服务器安装 Redis
- node107 和 node108 分别安装 Redis;
~]# yum install redis -y
- 配置 redis 监听在所有 IP:
~]# vim /etc/redis.conf
- 启动 redis:
~]# systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.
~]# systemctl start redis
~]# ss -tnl | grep 6379
LISTEN 0 511 *:6379 *:*
-
进入redis,分别设置 name 为 node107 和 node108:
以便验证负载均衡的效果;
[root@node107 ~]# redis-cli
127.0.0.1:6379> set name node107
OK
127.0.0.1:6379> get name
"node107"
[root@node108 ~]# redis-cli
127.0.0.1:6379> set name node108
OK
127.0.0.1:6379> get name
"node108"
6.2.2:Nginx 配置 Redis 代理
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/stream_conf.d/redis.conf
upstream redis {
server 192.168.1.107:6379 weight=1 fail_timeout=5s max_fails=3;
server 192.168.1.108:6379 weight=1 fail_timeout=5s max_fails=3;
}
server {
listen 192.168.1.106:6379;
proxy_connect_timeout 3s;
proxy_timeout 30s;
proxy_pass redis;
access_log /data/nginx/logs/stream_redis_access.log stream;
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 查看监听端口:
[root@node106 ~]# ss -tnl | grep 6379
LISTEN 0 511 192.168.1.106:6379 *:*
- 访问验证:
# 首次调度到 192.168.1.107:
[root@node105 ~]# redis-cli -h 192.168.1.106
192.168.1.106:6379> get name
"node107"
192.168.1.106:6379> quit
# 第二次调度到 192.168.1.108:
[root@node105 ~]# redis-cli -h 192.168.1.106
192.168.1.106:6379> get name
"node108"
- 查看日志:
[root@node106 ~]# tail -f /data/nginx/logs/stream_redis_access.log
192.168.1.105 [05/Dec/2020:13:54:56 +0800] TCP 200 9941 40 4.376 "192.168.1.107:6379" "40" "9941" "0.001"
192.168.1.105 [05/Dec/2020:13:55:30 +0800] TCP 200 9941 40 32.544 "192.168.1.108:6379" "40" "9941" "0.001"
6.3:MySQL 负载均衡
6.3.1:后端服务器安装 MariaDB
- 分别在 node107 和node108 上安装 mariadb-server:
~]# yum install mariadb-server -y
- 启动mariadb:
~]# systemctl start mariadb
~]# systemctl enable mariadb
- 授权远程登录用户 test:
MariaDB [(none)]> GRANT ALL ON *.* TO 'test'@'192.168.1.%' IDENTIFIED BY '123456';
MariaDB [(none)]> FLUSH PRIVILEGES;
-
分别创建 node107 和 node108 数据库:
以便验证负载均衡效果;
MariaDB [(none)]> CREATE DATABASE node107;
MariaDB [(none)]> CREATE DATABASE node108;
6.3.2:Nginx 配置 MySQL 代理
- 编辑配置文件:
[root@node106 ~]# vim /apps/nginx/stream_conf.d/mysql.conf
upstream mysql {
server 192.168.1.107:3306 weight=1 fail_timeout=5s max_fails=3;
server 192.168.1.108:3306 weight=1 fail_timeout=5s max_fails=3;
}
server {
listen 192.168.1.106:3306;
proxy_connect_timeout 3s;
proxy_timeout 30s;
proxy_pass mysql;
access_log /data/nginx/logs/stream_mysql_access.log stream;
}
- 检查配置文件并重载nginx:
[root@node106 ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@node106 ~]# systemctl reload nginx
- 验证监听端口:
[root@node106 ~]# ss -tnl | grep 3306
LISTEN 0 511 192.168.1.106:3306 *:*
- 访问验证:
# 首次调度到 192.168.1.107:
[root@node105 ~]# mysql -h192.168.1.106 -utest -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 5.5.68-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| node107 |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.01 sec)
MariaDB [(none)]> QUIT
Bye
# 第二次调度到 192.168.1.108
[root@node105 ~]# mysql -h192.168.1.106 -utest -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 5
Server version: 5.5.68-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| node108 |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.01 sec)
- 查看日志:
[root@node106 ~]# tail -f /data/nginx/logs/stream_mysql_access.log
192.168.1.105 [05/Dec/2020:14:07:18 +0800] TCP 200 361 145 17.681 "192.168.1.107:3306" "145" "361" "0.002"
192.168.1.105 [05/Dec/2020:14:07:57 +0800] TCP 200 361 140 34.734 "192.168.1.108:3306" "140" "361" "0.001"
更多推荐
所有评论(0)