- Nginx 核心知识 100 讲
- Nginx 核心知识 100 讲学习笔记
- 初识 nginx
- 给master进程发送一个信号,用新的nginx启动
- 可以看到新旧进程都在运行
- 新的master会生成新的work,老的master和work也在运行,他们会平滑的把所有的请求过度到新的二进制文件启的进程中
- 老的master和work已经不再监听80和443端口 所以新的请求,新的连接会进入新的nginx
- 优雅的关闭所有work进程
- 老的master进程还在运行、所有的请求已经转接到新的nginx上了 但是我们又可能会发生一些问题
- 新版本退回到老版本,所以我们还可以给老的master发送信号重新把老的work拉起来
- 老的master是不会自动退出 允许我们做版本回退
- nginx.conf
- Nginx 架构基础 (一)
- Nginx 架构基础 (二)
- 详解 HTTP 模块
- real_ip_header X-Real-IP;
- real_ip_recursive on;
- 测试
- 开启 real_ip_recursive on;
- 从/first 重定向到 /second rewrite后面没有break,依次向下执行
- 打开rewrite /second(.*) /third$1 break;
- 实际访问目录是
- 通过打开的rewrite_log on; 查看日志
- 将objs下的nginx复制到安装目录
- 热部署
- 日志信息
- ** 以html的形式显示文件目录 **
- 403 Forbidden
- 403 Forbidden
- 403 Forbidden
- 403 Forbidden
Nginx 核心知识 100 讲
发表于 2021-03-04 分类于 学习笔记 , 极客时间
本文字数: 40k 阅读时长 ≈ 37 分钟
Nginx 核心知识 100 讲学习笔记
初识 nginx
nginx 适用场景
静态资源服务:通过本地文件系统提供服务。
反向代理服务:nginx 的强大性能,缓存,负载均衡。
API 服务:OpenRestyNginx 的优点
- 高并发,高性能
- 可扩展性好
- 高可靠性
- 热部署
- BSD 许可证(开源免费)
Nginx 的组成
Nginx 的版本发布
nginx 编译
- vim 语法支持
cp -r contrib/vim/* ~/.vim/
- vim 语法支持
- 查看帮助文件 ``` [root@ecs nginx-1.18.0]# ./configure —help|more
…… 第一类
—prefix=PATH
第二类:使用哪些和不使用哪些模块
—with-http_ssl_module #默认是不编译进nginx的 —without-http_charset_module #默认是编译进nginx,加这个参数就是卸载这个模块
第三类:特殊优化参数 —with-cc=PATH set C compiler pathname —with-cpp=PATH set C preprocessor pathname —with-cc-opt=OPTIONS set additional C compiler options —with-ld-opt=OPTIONS set additional linker options —with-cpu-opt=CPU
-
中间文件介绍
<br />**生成中间文件在什么地方?**
```powershell
[root@ecs nginx-1.18.0]# cd objs/
[root@ecs objs]# ll
total 5148
-rw-r--r-- 1 root root 17457 Feb 16 09:53 autoconf.err
-rw-r--r-- 1 root root 40144 Feb 16 09:53 Makefile
-rwxr-xr-x 1 root root 5130480 Feb 16 09:55 nginx
-rw-r--r-- 1 root root 5375 Feb 16 09:55 nginx.8
-rw-r--r-- 1 root root 7037 Feb 16 09:53 ngx_auto_config.h
-rw-r--r-- 1 root root 657 Feb 16 09:53 ngx_auto_headers.h
-rw-r--r-- 1 root root 5856 Feb 16 09:53 ngx_modules.c #所有的模块都放在 ngx_modules.c
-rw-r--r-- 1 root root 45232 Feb 16 09:55 ngx_modules.o
drwxr-xr-x 9 root root 91 Feb 16 09:53 src
为什么要知道 nginx 编译中间文件是放在这里呢?
在进行 nginx 版本升级的时候不能执行 make instal 需要把中间文件拷贝到安装目录下
c 语言编辑生成的所有中间目录都会放在 src 目录中
/[root@ecs objs]# cd src
[root@ecs src]# ll
total 8
drwxr-xr-x 2 root root 4096 Feb 16 09:55 core
drwxr-xr-x 3 root root 191 Feb 16 09:55 event
drwxr-xr-x 4 root root 4096 Feb 16 09:55 http
drwxr-xr-x 2 root root 6 Feb 16 09:53 mail
drwxr-xr-x 2 root root 6 Feb 16 09:53 misc
drwxr-xr-x 4 root root 31 Feb 16 09:53 os
drwxr-xr-x 2 root root 6 Feb 16 09:53 stream
如果使用了动态模块、生成的 so 文件也会放在这个目录下
- 编译安装
./configure --prefix=/usr/local/nginx
make
make install
编译安装nginx需要pcre包,未安装会有如下提示:
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
需要安装pcre的devel包,pcre-devel。使用yum安装即可:(以下命令还带有ssl、zlib等依赖的安装)
yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel
再重新编译安装
nginx 配置语法
配置文件由指令与指令块构成
每条指令以;分号结尾,指令与参数间以空格符号分隔
指令块以{}大括号将多条指令组织在一起
include 语句允许组合多个配置文件以提升可维护性
使用 #符号添加注释,提高可读性
使用 $ 符号使用变量
部分指令的参数支持正则表达式nginx 的命令行
- 重载配置文件
[root@ecs sbin]# ./nginx
[root@ecs sbin]# ps -ef|grep nginx
root 254641 1 0 10:21 ? 00:00:00 nginx: master process ./nginx
nobody 254642 254641 0 10:21 ? 00:00:00 nginx: worker process
root 254644 221527 0 10:21 pts/0 00:00:00 grep --color=auto nginx
[root@ecs sbin]# vim ../conf/nginx.conf
[root@ecs sbin]# ./nginx -s reload
[root@ecs sbin]# ps -ef|grep nginx
root 254641 1 0 10:21 ? 00:00:00 nginx: master process ./nginx
nobody 254682 254641 0 10:22 ? 00:00:00 nginx: worker process
root 254694 221527 0 10:23 pts/0 00:00:00 grep --color=auto nginx
- 重载配置文件
- 热部署
```powershell
[root@ecs sbin]# pwd
/usr/local/nginx/sbin
[root@ecs sbin]# cp nginx nginx.old
[root@ecs sbin]# cd /data/soft/nginx/nginx-1.18.0/objs/
[root@ecs objs]# ll
total 5148
-rw-r—r— 1 root root 17457 Feb 16 09:53 autoconf.err
-rw-r—r— 1 root root 40144 Feb 16 09:53 Makefile
-rwxr-xr-x 1 root root 5130480 Feb 16 09:55 nginx
-rw-r—r— 1 root root 5375 Feb 16 09:55 nginx.8
-rw-r—r— 1 root root 7037 Feb 16 09:53 ngx_auto_config.h
-rw-r—r— 1 root root 657 Feb 16 09:53 ngx_auto_headers.h
-rw-r—r— 1 root root 5856 Feb 16 09:53 ngx_modules.c
-rw-r—r— 1 root root 45232 Feb 16 09:55 ngx_modules.o
drwxr-xr-x 9 root root 91 Feb 16 09:53 src
[root@ecs objs]# cp -r nginx /usr/local/nginx/sbin/ -f
cp: overwrite ‘/usr/local/nginx/sbin/nginx’? y
给master进程发送一个信号,用新的nginx启动
[root@ecs objs]# kill -USR2 254641可以看到新旧进程都在运行
新的master会生成新的work,老的master和work也在运行,他们会平滑的把所有的请求过度到新的二进制文件启的进程中
老的master和work已经不再监听80和443端口 所以新的请求,新的连接会进入新的nginx
[root@ecs objs]# ps -ef|grep nginx root 254641 1 0 10:21 ? 00:00:00 nginx: master process ./nginx nobody 254682 254641 0 10:22 ? 00:00:00 nginx: worker process root 254778 254641 0 10:35 ? 00:00:00 nginx: master process ./nginx nobody 254779 254778 0 10:35 ? 00:00:00 nginx: worker process root 254789 221527 0 10:36 pts/0 00:00:00 grep —color=auto nginx
优雅的关闭所有work进程
[root@ecs objs]# kill -WINCH 254641 [root@ecs objs]# ps -ef|grep nginx root 254641 1 0 10:21 ? 00:00:00 nginx: master process ./nginx root 254778 254641 0 10:35 ? 00:00:00 nginx: master process ./nginx nobody 254779 254778 0 10:35 ? 00:00:00 nginx: worker process root 254800 221527 0 10:40 pts/0 00:00:00 grep —color=auto nginx
老的master进程还在运行、所有的请求已经转接到新的nginx上了 但是我们又可能会发生一些问题
新版本退回到老版本,所以我们还可以给老的master发送信号重新把老的work拉起来
老的master是不会自动退出 允许我们做版本回退
-
切割日志
```shell
[root@ecs logs]# mv access.log bak.log
[root@ecs logs]# ll
total 12
-rw-r--r-- 1 nobody root 0 Feb 16 10:21 bak.log
-rw-r--r-- 1 nobody root 438 Feb 16 10:49 error.log
-rw-r--r-- 1 root root 7 Feb 16 10:35 nginx.pid
-rw-r--r-- 1 root root 7 Feb 16 10:21 nginx.pid.oldbin
# 重新启动之后会重新生成access.log
[root@ecs logs]# ../sbin/nginx -s reopen
[root@ecs logs]# ll
total 12
-rw-r--r-- 1 nobody root 0 Feb 16 10:50 access.log
-rw-r--r-- 1 nobody root 0 Feb 16 10:21 bak.log
-rw-r--r-- 1 nobody root 500 Feb 16 10:50 error.log
-rw-r--r-- 1 root root 7 Feb 16 10:35 nginx.pid
-rw-r--r-- 1 root root 7 Feb 16 10:21 nginx.pid.oldbin
# 定时切割日志
[root@ecs logs]# crontab -l
0 0 1 * * root /usr/local/nginx/logs/rotate.sh
[root@ecs logs]# cat rotate.sh
#!/bin/bash
LOGS_PATH=/usr/local/nginx/logs/history
CUR_LOGS_PATH=/usr/local/nginx/logs
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
mv ${CUR_LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log
mv ${CUR_LOGS_PATH}/error.log ${LOGS_PATH}/error_${YESTERDAY}.log
# 向nginx主进程发送USR1信号。USR1信号是重新打开日志文件
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)
搭建静态资源
[root@ecs nginx]# vi conf/nginx.conf
server {
listen 8080;
server_name www.test.com;
#charset koi8-r;
access_log logs/test.access.log main;
location / {
alis dlib/;
# 打开目录
#autoindex on;
# 限制访问速度
#set $limit_rate 1k;
#index index.html index.htm;
}
#error_page 404 /404.html;
}
打开 gzip
gzip on;
gzip_min_length 1;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
- 搭建具备缓存功能的反向代理服务
```shell
nginx.conf
proxy_cache_path /tmp/nginxcache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;
upstream local { server 127.0.0.1:8080; } server { listen 80; server_name www.test.com;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache my_cache;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 304 302 1d;
proxy_pass http://local;
}
#error_page 404 /404.html;
}
server { listen 127.0.0.1:8080;
#server_name www.test.com;
#charset koi8-r;
access_log logs/test.access.log main;
location / {
alias dlib/;
autoindex on;
set $limit_rate 1k;
index index.html index.htm;
}
#error_page 404 /404.html;
}
upstream local { server 127.0.0.1:8080; } server { listen 80; server_name www.test.com;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache my_cache;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 304 302 1d;
proxy_pass http://local;
}
#error_page 404 /404.html;
}
10.
用 GoAccess 实现可视化并实时监控 access 日志
-
安装 GoAccess `https://www.goaccess.cc/?mod=download`
<br />说明:
<br />GoAccess 在使用源码安装时,依赖下列组件。
<br />为方便最终日志统计时显示 IP 地理位置,需要安装依赖项 GeoIP-devel:
<br />执行命令:_yum install GeoIP-devel.x86_64_
<br />安装 ncurses-devel 开发库:
<br />执行命令:_yum install ncurses-devel_
<br />安装 openssl-devel 开发库:
<br />执行命令:_yum install openssl-devel_
-
执行报错
```powershell
[root@ecs logs]# goaccess test.access.log -o ../html/report.html --real-time-html --time-format='%H:%M:%S'--date-format='%d/%b/%Y' --log-format=COMBINE
GoAccess - version 1.2 - Feb 16 2021 17:14:24
Config file: /usr/local/etc/goaccess.conf
Fatal error has occurred
Error occured at: src/parser.c - parse_log - 2705
No date format was found on your conf file.
# 生成报告
[root@ecs logs]# goaccess test.access.log -a -o ../html/report.html
# 配置nginx,访问查看
location /report.html {
alias /usr/local/nginx/html/report.html;
}
从网络协议来看 SSL 安全协议
- TLS 安全密码套件解读
对称加密与非对称加密各自的应用场景
- 对称加密
- 非对称加密
SSL 证书的公信力是如何保证的?
- PKI 公钥基础设施
- 证书类型
SSL 协议握手时 Nginx 的性能瓶颈在哪里?
用免费 SSL 证书实现一个 HTTPS 站点
安装yum install certbot python2-certbot-nginx -y
配置certbot --nginx --nginx-server-root=/usr/local/nginx/conf/ -d www.test.com
nginx 配置listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pazzn.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pazzn.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
基于 OpenResty 用 Lua 语言实现简单服务
- 下载安装 openresty
[root@ecs soft]# wget https://openresty.org/download/openresty-1.19.3.1.tar.gz
[root@ecs openresty-1.19.3.1]# ./configure
- 下载安装 openresty
location /lua {
default_type text/html;
content_by_lua 'ngx.say("User-Agent: ", ngx.req.get_headers()["User-Agent"])';
}
Nginx 架构基础 (一)
Nginx 请求处理流程
Nginx 进程结构
进程说明
Master 进程
1、是进行 work 进程的监控管理的
2、看看 work 进程是否正常工作需不需要进行热部署、需不需要重新载入配置文件Cache manager 缓存的管理
1、缓存为反向代理后端发来的动态请求做缓存使用
2、缓存在不光是在 work 进程间使用、还要被 Cache manager 和 Cache loader 使用Cache loader 载入缓存
实例演示
[root@ecs conf]# ps -ef|grep nginx
root 262788 1 0 18:09 ? 00:00:00 nginx: master process ../sbin/nginx
root 262789 262788 0 18:09 ? 00:00:00 nginx: worker process
root 262790 262788 0 18:09 ? 00:00:00 nginx: cache manager process
root 274250 221527 0 19:54 pts/0 00:00:00 grep --color=auto nginx
[root@ecs conf]# ../sbin/nginx -s reload
[root@ecs conf]# ps -ef|grep nginx
root 262788 1 0 18:09 ? 00:00:00 nginx: master process ../sbin/nginx
root 274252 262788 0 19:54 ? 00:00:00 nginx: worker process
root 274253 262788 0 19:54 ? 00:00:00 nginx: cache manager process
root 274255 221527 0 19:54 pts/0 00:00:00 grep --color=auto nginx
[root@ecs conf]# kill -SIGHUP 262788
[root@ecs conf]# ps -ef|grep nginx
root 262788 1 0 18:09 ? 00:00:00 nginx: master process ../sbin/nginx
root 274267 262788 0 19:55 ? 00:00:00 nginx: worker process
root 274268 262788 0 19:55 ? 00:00:00 nginx: cache manager process
root 274270 221527 0 19:55 pts/0 00:00:00 grep --color=auto nginx
使用信号管理 Nginx 的父子进程
CHLD:终止进程信号。
TERM,INT: 立刻停止进程
QUIT: 优雅停止进程
HUP: 重载配置文件
USR1: 重新打开日志文件
USR2、WINCH: 需要通过命令行结合 kill 命令使用reload 重载配置文件真相
热升级的完整流程
Nginx 架构基础 (二)
网络收发与 Nginx 事件间的对应关系
Nginx 网络事件实例演示
抓包工具:https://www.wireshark.org/#downloadTCP 层:本地打开了 54756,Nginx 打开的是 8080 端口 进程与进程通信
IP 层:本机 IP 地址:192.168.1.196 nginx 服务器的 IP 地址:127.0.0.1
三次握手
windows 先向 nginx 发送一个 SYN
相反的 nginx 所在的 linux 也会向 windos 发送一个 SYN,这个时候 nginx 是没有感知到的、因为这是一个半打开的状态
直到 widows 再向 nginx 所在的 linux 服务器发送一个 ACK 时,linux 操作系统才会通知 nginx 这时有一个读事件需要处理
epoll 的优劣及原理
详解 HTTP 模块
冲突的配置指令以谁为准?
- 配置块的嵌套
main
http {
upstream { … }
split_clients {…}
map {…}
geo {…}
server {
if () {…}
location {
limit_except {…}
}
location {
location {
}
}
}
server {
}
}
- 配置块的嵌套
- 指令的 Context ```shell Syntax: log_format name [escape=default|json|none] string …; Default: log_format combined “…”; Context: http
Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; access_log off; Default: access_log logs/access.log combined; Context: http, server, location, if in location, limit_excep
-
指令的合并
<br />![](https://gitee.com/dong618/blog/raw/master/img/202101/20210219171227.png#alt=)
-
存储值的指令集成规则:向上覆盖
<br />子配置不存在时,直接使用父配置块;
<br />子配置存在时,直接覆盖父配置块。
```powershell
server {
listen 8080;
root /home/geek/nginx/html;
access_log logs/geek.access.log main;
location /test {
root /home/geek/nginx/test;
access_log logs/access.test.log main;
}
location /dlib {
alias dlib/;
}
location / {
}
}
HTTP 模块合并配置的实现
- 指令在哪个块下生效?11 个阶段
指令允许出现在那些块下?
{ ngx_string("valid_referers"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
......
在 server 块内生效、从 http 向 server 合并指令:
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
- 配置缓存在内存
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
- Listen 指令
listen unix:/var/run/nginx.sock;
listen 127.0.0.1:8000;
listen 127.0.0.1;
listen 8000;
listen *:8000;
listen localhost:8000 bind;
listen [::]:8000 ipv6only=on;
listen [::1];
- Listen 指令
处理 HTTP 请求头部的流程
- 接收请求事件模块
- 接收请求 HTTP 模块
如何找到处理请求的 server 指令块
- server 匹配顺序
1、精确匹配
2、 在前的泛域名
3、 在后的泛域名
4、按文件中的顺序匹配正则表达式域名
5、default server
第 1 个
listen 指定 default
- server 匹配顺序
详解 HTTP 请求的 11 个阶段
参考地址:https://www.cnblogs.com/luoahong/p/13542203.html
11 个阶段的顺序处理
| 阶段 | 使用的模块 | 备注 | | | | | | —- | —- | —- | —- | —- | —- | —- | | POST_READ | realip | 刚读完 http 请求头、没有经过任何加工过、获取到一些原始的值 | | | | | | SERVER_REWRITE | rewrite | 它和下面 REWRITE 的只有一个模块 | | | | | | FIND_CONFIG | 这个只有 nginx 框架会做 | 所以没有任何的模块、就是在做 location 的一个匹配 | | | | | | REWRITE | rewrite | 一般第三方模块没有一个处理 REWRITE | | | | | | POST_REWRITE | | 刚刚 REWRITE 之后要做的一些事情 | | | | | | PREACCESS | limt_conn, limit_req | 在 access 之前要不要做一些工作、 限制速度、 限制连接数 | | | | | | ACCESS | auth_basic | access | auth_request | 确认访问权限的 能不能访问 | 根据访问的 ip | 根据第三方的服务 | | POST_ACCESS | | | | | | | | PRECONFTENT | try_files mirrors | 处理 CONTENT 之前 会把这个服务发送给第三方服务、一个请求产生多个请求值 | | | | | | CONTENT | index | autoindex | concat | 反向代理 | | | | LOG | access_log | 打印 access 日志的 | | | | |
postread 阶段:获取真实客户端地址的 realip 模块 ```shell [root@ecs conf.d]# cat realip.conf server { server_name realip.test.com;
error_log logs/myerror.log debug; set_real_ip_from 127.0.0.1;
real_ip_header X-Real-IP;
real_ip_recursive off;
real_ip_recursive on;
real_ip_header X-Forwarded-For;
location /{
return 200 "Client real ip: $remote_addr\n";
} }
测试
[root@ecs conf.d]# curl -H ‘X-Forwarded-For: 1.1.1.1,127.0.0.1’ realip.test.com Client real ip: 127.0.0.1
开启 real_ip_recursive on;
[root@ecs conf.d]# curl -H ‘X-Forwarded-For: 1.1.1.1,127.0.0.1’ realip.test.com Client real ip: 1.1.1.1
7.
rewrite 阶段的 rewrite 模块:return 指令
<br />![](https://gitee.com/dong618/blog/raw/master/img/202101/20210220095723.png#alt=)
```shell
[root@ecs conf.d]# cat return.conf
server {
server_name return.test.com;
listen 8080;
root html/;
error_page 404 /403.html;
#return 405;
location /{
#return 404 "find nothing!\n";
}
}
[root@ecs conf.d]# curl return.test.com:8080/aaa.html
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>403 forbidden.</h1>
</body>
</html>
# 去掉 return 404 "find nothing!\n"; 注释
[root@ecs conf.d]# curl return.test.com:8080/aaa.html
find nothing!
# 去掉 return 405注释
# 说明 return 405是在SERVER_REWRITE 阶段,而return 404 "find nothing!\n"处于REWRITE,优先处理SERVER_REWRITE
[root@ecs conf.d]# curl return.test.com:8080/aaa.html
<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>
rewrite 阶段的 rewrite 模块:重写 URL
```shell [root@ecs conf.d]# cat rewrite.conf server { server_name rewrite.test.com; rewrite_log on; error_log logs/rewrite_error.log notice;root html/; location /first {
rewrite /first(.*) /second$1 last;
return 200 'first!\n';
}
location /second {
#rewrite /second(.*) /third$1 break;
rewrite /second(.*) /third$1;
return 200 'second!\n';
}
location /third {
return 200 'third!\n';
}
location /redirect1 {
rewrite /redirect1(.*) $1 permanent;
}
location /redirect2 {
rewrite /redirect2(.*) $1 redirect;
}
location /redirect3 {
rewrite /redirect3(.*) http://rewrite.test.com$1;
}
location /redirect4 {
rewrite /redirect4(.*) http://rewrite.test.com$1 permanent;
}
}
从/first 重定向到 /second rewrite后面没有break,依次向下执行
[root@ecs conf.d]# curl rewrite.test.com/first/3.txt second!
打开rewrite /second(.*) /third$1 break;
[root@ecs conf.d]# curl rewrite.test.com/first/3.txt test3
实际访问目录是
[root@ecs conf.d]# cat /usr/local/nginx/html/third/3.txt test3
[root@ecs conf.d]# curl rewrite.test.com/redirect1/ -I HTTP/1.1 301 Moved Permanently Server: nginx/1.18.0 Date: Sat, 20 Feb 2021 03:06:51 GMT Content-Type: text/html Content-Length: 169 Location: http://rewrite.test.com/ Connection: keep-alive
[root@ecs conf.d]# curl rewrite.test.com/redirect2/ -I HTTP/1.1 302 Moved Temporarily Server: nginx/1.18.0 Date: Sat, 20 Feb 2021 03:06:57 GMT Content-Type: text/html Content-Length: 145 Location: http://rewrite.test.com/ Connection: keep-alive
[root@ecs conf.d]# curl rewrite.test.com/redirect3/ -I HTTP/1.1 302 Moved Temporarily Server: nginx/1.18.0 Date: Sat, 20 Feb 2021 03:07:25 GMT Content-Type: text/html Content-Length: 145 Connection: keep-alive Location: http://rewrite.test.com/
[root@ecs conf.d]# curl rewrite.test.com/redirect4/ -I HTTP/1.1 301 Moved Permanently Server: nginx/1.18.0 Date: Sat, 20 Feb 2021 03:07:44 GMT Content-Type: text/html Content-Length: 169 Connection: keep-alive Location: http://rewrite.test.com/
通过打开的rewrite_log on; 查看日志
[root@ecs logs]# cat rewrite_error.log 2021/02/20 11:06:51 [notice] 295965#0: 12 “/redirect1(.)” matches “/redirect1/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect1/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:06:51 [notice] 295965#0: 12 rewritten redirect: “/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect1/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:06:57 [notice] 295965#0: 13 “/redirect2(.)” matches “/redirect2/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect2/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:06:57 [notice] 295965#0: 13 rewritten redirect: “/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect2/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:07:25 [notice] 295965#0: 14 “/redirect3(.)” matches “/redirect3/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect3/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:07:25 [notice] 295965#0: 14 rewritten redirect: “http://rewrite.test.com/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect3/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:07:44 [notice] 295965#0: 15 “/redirect4(.)” matches “/redirect4/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect4/ HTTP/1.1”, host: “rewrite.test.com” 2021/02/20 11:07:44 [notice] 295965#0: 15 rewritten redirect: “http://rewrite.test.com/“, client: 127.0.0.1, server: rewrite.test.com, request: “HEAD /redirect4/ HTTP/1.1”, host: “rewrite.test.com”
9.
rewrite 阶段的 rewrite 模块:条件判断
<br />![](https://gitee.com/dong618/blog/raw/master/img/202101/20210220111129.png#alt=)
<br />![](https://gitee.com/dong618/blog/raw/master/img/202101/20210220111153.png#alt=)
10.
find_config 阶段:找到处理请求的 location 指令块
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220111521.png#alt=)
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220111636.png#alt=)
```shell
[root@ecs conf.d]# cat locations.conf
server {
server_name location.test.com;
error_log logs/error.log debug;
#root html/;
default_type text/plain;
merge_slashes off;
location ~ /Test1/$ {
return 200 'first regular expressions match!\n';
}
location ~* /Test1/(\w+)$ {
return 200 'longest regular expressions match!\n';
}
location ^~ /Test1/ {
return 200 'stop regular expressions match!\n';
}
location /Test1/Test2 {
return 200 'longest prefix string match!\n';
}
location /Test1 {
return 200 'prefix string match!\n';
}
location = /Test1 {
return 200 'exact match!\n';
}
}
[root@ecs conf.d]# curl location.test.com/Test1
exact match!
[root@ecs conf.d]# curl location.test.com/Test1/
stop regular expressions match!
[root@ecs conf.d]# curl location.test.com/Test1/Test2
longest regular expressions match!
[root@ecs conf.d]# curl location.test.com/Test1/Test2/
longest prefix string match!
- preaccess 阶段:对连接做限制的 limit_conn 模块
限制发生时的日志级别Syntax: limit_conn_log_level info | notice | warn | error;
Default: limit_conn_log_level error;
Context: http, server, location
限制发生时向客户端返回的错误码
Syntax: limit_conn_status code;
Default: limit_conn_status 503;
Context: http, server, location
[root@ecs conf.d]# cat limit_conn.conf
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m;
server {
server_name limit.test.com;
root html/;
error_log logs/myerror.log info;
location /{
limit_conn_status 500; #返回错误码500
limit_conn_log_level warn;
limit_rate 50; #限制每秒钟向用户返回50Byte
limit_conn addr 1; #限制并发连接数1
#limit_req zone=one burst=3 nodelay;
#limit_req zone=one;
}
}
# 打印错误日志
2021/02/20 13:40:08 [info] 296750#0: *45 client 127.0.0.1 closed keepalive connection
2021/02/20 13:40:13 [warn] 296750#0: *47 limiting connections by zone "addr", client: 127.0.0.1, server: limit.test.com, request: "GET / HTTP/1.1", host: "limit.test.com"
2021/02/20 13:40:17 [info] 296750#0: *46 client prematurely closed connection while sending response to client, client: 127.0.0.1, server: limit.test.com, request: "GET / HTTP/1.1", host: "limit.test.com"
2021/02/20 13:40:26 [warn] 296750#0: *49 limiting connections by zone "addr", client: 127.0.0.1, server: limit.test.com, request: "GET / HTTP/1.1", host: "limit.test.com"
2021/02/20 13:40:34 [info] 296750#0: *48 client 127.0.0.1 closed keepalive connection
- preaccess 阶段:对请求做限制的 limit_req 模块
限制发生时的日志级别Syntax: limit_req_log_level info | notice | warn | error;
Default: limit_req_log_level error;
Context: http, server, location
限制发生时向客户端返回的错误码
Syntax: limit_req_status code;
Default: limit_req_status 503;
Context: http, server, location
[root@ecs conf.d]# cat limit_conn.conf
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m;
server {
server_name limit.test.com;
root html/;
error_log logs/myerror.log info;
location /{
limit_conn_status 500;
limit_conn_log_level warn;
#limit_rate 50;
#limit_conn addr 1;
#limit_req zone=one burst=3 nodelay;
limit_req zone=one;
}
}
[root@ecs conf.d]# ../../sbin/nginx -s reload
#第一次访问正常
[root@ecs conf.d]# curl limit.test.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#第二次返回503
[root@ecs conf.d]# curl limit.test.com
<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
# 打开 limit_req zone=one burst=3 nodelay; 之后,访问3次正常,第四次返回503
# 同时打开limit_conn 和 limit_req,返回503,limit_req访问在前。
access 阶段:对 ip 做限制的 access 模块
如何限制某些 IP 地址的访问权限。access 阶段:对用户名密码做限制的 auth_basic 模块
auth_basic 模块指令:# 安装工具包
[root@ecs ~]# yum install httpd-tools -y
# 生成文件
[root@ecs conf.d]# htpasswd -c auth.pass temp
New password:
Re-type new password:
Adding password for user temp
- access 阶段:使用第三方做权限控制的 auth_request 模块
重新编译安装 ```powershell [root@ecs nginx]# cd sbin/ [root@ecs sbin]# ll total 15724 -rwxr-xr-x 1 root root 5833272 Feb 20 09:43 nginx -rwxr-xr-x 1 root root 5130480 Feb 16 10:32 nginx.2.old -rwxr-xr-x 1 root root 5130480 Feb 16 10:26 nginx.old [root@ecs sbin]# mv nginx nginx.3.old
[root@ecs nginx-1.18.0]# ./configure —prefix=/usr/local/nginx —with-http_ssl_module —with-http_realip_module —with-http_auth_request_module [root@ecs nginx-1.18.0]# make #切勿执行make install
将objs下的nginx复制到安装目录
[root@ecs objs]# cp nginx /usr/local/nginx/sbin/
热部署
[root@ecs nginx-1.18.0]# kill -USR2 300175
```shell
server {
server_name access.test.com;
error_log logs/error.log debug;
#root html/;
default_type text/plain;
location /auth_basic {
satisfy any;
auth_basic "test auth_basic";
auth_basic_user_file conf.d/auth.pass;
deny all;
}
location / {
auth_request /test_auth;
}
location = /test_auth {
proxy_pass http://127.0.0.1:8090/auth_upstream;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
}
access 阶段的 satisfy 指令
如果有 return 指令,access 阶段会生效吗?
不会生效,因为 return 指令在 SERVER_REWRITE 和 REWRITE 阶段,领先于 access。多个 access 模块的顺序有影响吗?
查看 ngx-modules.c
&ngx_http_auth_request_module,
&ngx_http_auth_basic_module
&ngx_http_access_module
有影响输对密码,下面可以访问到文件吗?可以
location/{
satisfy any;
auth_basic "test auth basic"
auth_basic_user_file examples/auth.pass;
deny all:
}
如果把 deny all 提到 auth basic 之前呢?
可以,和指令顺序无关,主要取决于模块顺序。如果改为 allow all, 有机会输入密码吗?
没有,因为配置的 satisfy any; 只要有一个模块放行即可。而且 allow 属于 access, 先于 auth_basic 执行。
precontent 阶段:按序访问资源的 try_files 模块
```powershell [root@ecs conf.d]# cat tryfiles.conf server { server_name tryfiles.test.com; error_log logs/myerror.log info; root html/; default_type text/plain;location /first {
try_files /system/maintenance.html
$uri $uri/index.html $uri.html
@lasturl;
}
location @lasturl {
return 200 'lasturl!\n';
}
location /second {
try_files $uri $uri/index.html $uri.html =404;
}
} [root@ecs conf.d]# curl tryfiles.test.com/first lasturl! [root@ecs conf.d]# curl tryfiles.test.com/second
404 Not Found
18.
实时拷贝流量:precontent 阶段的 mirror 模块
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220145826.png#alt=)
powershell
# 本地服务
[root@ecs conf.d]# cat mirror.conf
server {
listen 10020;
location / {
return 200 ‘mirror response!’;
}
}
#上游服务
[root@ecs conf]# vim mirror.conf
server{
listen 8001;
error_log Logs/error. log debug;
location / {
mirror /mirror;
mirror request _body off;
}
location =/mirror {
internal;
proxy_pass http://127.0.0.1:10020$request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length “”;
proxy_set_header X-Oriqinal-URI $request_uri;
}
}
19.
content 阶段:详解 root 和 alias 指令
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220151044.png#alt=)
powershell
[root@ecs conf.d]# cat static.conf
server {
server_name static.test.com;
error_log logs/myerror.log info;
location /root {
root html;
}
location /alias {
alias html;
}
location ~ /root/(\w+.txt) {
root html/first/$1;
}
location ~ /alias/(\w+.txt) {
alias html/first/$1;
}
location /RealPath/ {
alias html/realpath/;
return 200 ‘$request_filename:$document_root:$realpath_root\n’;
}
}
[root@ecs conf.d]# curl static.test.com/root/
404 Not Found
404 Not Found
日志信息
2021/02/20 15:15:09 [error] 300277#0: *7 open() “/usr/local/nginx/html/first/1.txt/root/1.txt” failed (20: Not a directory), client: 127.0.0.1, server: static.test.com, request: “GET /root/1.txt HTTP/1.1”, host: “static.test.com”
[root@ecs conf.d]# curl static.test.com/alias/ <!DOCTYPE html>
Welcome to nginx!
[root@ecs conf.d]# curl static.test.com/alias/1.txt test120.
static 模块提供的 3 个变量
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220151852.png#alt=)
powershell
# 建立软连接
[root@ecs html]# ln -s first realpath
[root@ecs html]# ll
total 352
-rw-r—r— 1 root root 242 Feb 20 10:05 403.html
-rw-r—r— 1 root root 494 Feb 16 09:55 50x.html
drwxr-xr-x 2 root root 32 Feb 20 15:23 first
-rw-r—r— 1 root root 612 Feb 16 09:55 index.html
lrwxrwxrwx 1 root root 5 Feb 20 15:23 realpath -> first
-rw-r—r— 1 root root 344328 Feb 16 17:55 report.html
drwxr-xr-x 2 root root 19 Feb 20 10:59 second
drwxr-xr-x 2 root root 19 Feb 20 10:59 third
[root@ecs html]# pwd
/usr/local/nginx/html
location /RealPath/ {
alias html/realpath/;
return 200 ‘$request_filename:$document_root:$realpath_root\n’;
}
[root@ecs conf.d]# curl static.test.com/RealPath/1.txt
/usr/local/nginx/html/realpath/1.txt:/usr/local/nginx/html/realpath/:/usr/local/nginx/html/first
-
静态文件返回时的 content-type
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220152722.png#alt=)
-
未找到文件时的错误日志
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220152733.png#alt=)
21.
static 模块对 url 不以斜杠结尾却访问目录的做法
powershell
[root@ecs conf.d]# cat dirredirect.conf
server {
server_name return.test.com dir.test.com;
server_name_in_redirect off;
listen 8088;
port_in_redirect on;
absolute_redirect off;
root html/;
}
[root@ecs conf.d]# curl localhost:8088/first -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Sat, 20 Feb 2021 07:31:28 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: /first/
# 添加注释 absolute_redirect off
[root@ecs conf.d]# curl localhost:8088/first -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Sat, 20 Feb 2021 07:40:40 GMT
Content-Type: text/html
Content-Length: 169
Location: http://localhost:8088/first/
Connection: keep-alive
[root@ecs conf.d]# curl -H ‘Host:aaa’ localhost:8088/first -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Sat, 20 Feb 2021 07:41:24 GMT
Content-Type: text/html
Content-Length: 169
Location: http://aaa:8088/first/
Connection: keep-alive
# 修改 server_name_in_redirect on 返回server_name中的域名
[root@ecs conf.d]# curl -H ‘Host:aaa’ localhost:8088/first -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Sat, 20 Feb 2021 07:42:15 GMT
Content-Type: text/html
Content-Length: 169
Location: http://return.test.com:8088/first/
Connection: keep-alive
22.
index 和 autoindex 模块的用法
-
对访问 / 时的处理:content 阶段的 index 模块
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220155144.png#alt=)
-
随机 index.html 文件:content 阶段的 autoindex 模块
<br />
-
显示目录内容:content 阶段的 autoindex 模块
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220155334.png#alt=)
-
autoindex 模块的指令
<br />![](https://gitee.com/dong618/blog/raw/master/img/202102/20210220155501.png#alt=)
powershell
[root@ecs conf.d]# cat autoindex.conf
server {
server_name autoindex.test.com;
listen 8080;
location / {
alias html/;
autoindex on;
#index a.html;
autoindex_exact_size off;
autoindex_format html;
autoindex_localtime on;
}
}
[root@ecs conf.d]# curl autoindex.test.com:8080
<!DOCTYPE html>
** 以html的形式显示文件目录 **
[root@ecs conf.d]# cat autoindex.conf server { server_name autoindex.test.com; listen 8080; location / { alias html/; autoindex on; index a.html; autoindex_exact_size off; autoindex_format html; autoindex_localtime on; } } [root@ecs conf.d]# ../../sbin/nginx -s reload [root@ecs conf.d]# curl autoindex.test.com:8080
Index of /
```
../first/realpath/second/third/403.htmlnginx.org
nginx.com
Thank you for using nginx.
nginx.org
nginx.com
Thank you for using nginx.
For online documentation and support please refer to
sub.test.com/nginx.
Commercial support is available at
sub.test.com/nginx.