0%

Nginx 核心知识 100 讲

Nginx 核心知识 100 讲学习笔记

初识 nginx

  1. nginx 适用场景

    静态资源服务:通过本地文件系统提供服务。

    反向代理服务:nginx 的强大性能,缓存,负载均衡。

    API 服务:OpenResty

    image-20210216091502611

  2. Nginx 的优点

    • 高并发,高性能

    • 可扩展性好

    • 高可靠性

    • 热部署

    • BSD 许可证(开源免费)

    image-20210216091747299

  3. Nginx 的组成

    image-20210216091839131

  4. Nginx 的版本发布

    image-20210216092422869

  5. nginx 编译

    • vim 语法支持 cp -r contrib/vim/* ~/.vim/

    image-20210216094538152

    • 查看帮助文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      [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
    • 中间文件介绍

      生成中间文件在什么地方?

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      [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 目录中

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      /[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 文件也会放在这个目录下

    • 编译安装

      1
      2
      3
      ./configure --prefix=/usr/local/nginx
      make
      make install
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      编译安装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

      再重新编译安装
  6. nginx 配置语法

    配置文件由指令与指令块构成

    每条指令以;分号结尾,指令与参数间以空格符号分隔

    指令块以{}大括号将多条指令组织在一起

    include 语句允许组合多个配置文件以提升可维护性

    使用 #符号添加注释,提高可读性

    使用 $ 符号使用变量

    部分指令的参数支持正则表达式

    image-20210216101716303

  7. nginx 的命令行

    image-20210216101741507

    • 重载配置文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      [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

    • 热部署

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      [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是不会自动退出 允许我们做版本回退
    • 切割日志

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      [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)
  8. 搭建静态资源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [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;
    }

    image-20210216131359256

    打开 gzip

    1
    2
    3
    4
    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;

    image-20210216131257211

  9. 搭建具备缓存功能的反向代理服务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #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

      说明:

      GoAccess 在使用源码安装时,依赖下列组件。

      为方便最终日志统计时显示 IP 地理位置,需要安装依赖项 GeoIP-devel:

      执行命令:yum install GeoIP-devel.x86_64

      安装 ncurses-devel 开发库:

      执行命令:yum install ncurses-devel

      安装 openssl-devel 开发库:

      执行命令:yum install openssl-devel

    • 执行报错

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      [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;
      }

      image-20210216181819318

  11. 从网络协议来看 SSL 安全协议

    image-20210216182402487

    • TLS 安全密码套件解读

    image-20210216182532032

  12. 对称加密与非对称加密各自的应用场景

    • 对称加密

    image-20210216182710344

    • 非对称加密

image-20210216182729612

  1. SSL 证书的公信力是如何保证的?

    • PKI 公钥基础设施

    image-20210216183108379

    • 证书类型

    image-20210216183147565

  2. SSL 协议握手时 Nginx 的性能瓶颈在哪里?

    image-20210216183402502

  3. 用免费 SSL 证书实现一个 HTTPS 站点

    安装

    yum install certbot python2-certbot-nginx -y

    配置

    certbot --nginx --nginx-server-root=/usr/local/nginx/conf/ -d www.test.com

    nginx 配置

    1
    2
    3
    4
    5
    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
  4. 基于 OpenResty 用 Lua 语言实现简单服务

    • 下载安装 openresty
    1
    2
    [root@ecs soft]# wget https://openresty.org/download/openresty-1.19.3.1.tar.gz
    [root@ecs openresty-1.19.3.1]# ./configure

    添加 Lua 代码

    1
    2
    3
    4
    location /lua {
    default_type text/html;
    content_by_lua 'ngx.say("User-Agent: ", ngx.req.get_headers()["User-Agent"])';
    }

Nginx 架构基础 (一)

  1. Nginx 请求处理流程

    image-20210216194216098

  2. Nginx 进程结构

    image-20210216194436464

    • 进程说明

      • Master 进程
        1、是进行 work 进程的监控管理的
        2、看看 work 进程是否正常工作需不需要进行热部署、需不需要重新载入配置文件

      • Cache manager 缓存的管理
        1、缓存为反向代理后端发来的动态请求做缓存使用

        2、缓存在不光是在 work 进程间使用、还要被 Cache manager 和 Cache loader 使用

      • Cache loader 载入缓存

    • 实例演示

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      [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
    1. 使用信号管理 Nginx 的父子进程

      image-20210216200057165

      CHLD:终止进程信号。

      TERM,INT: 立刻停止进程

      QUIT: 优雅停止进程

      HUP: 重载配置文件

      USR1: 重新打开日志文件

      USR2、WINCH: 需要通过命令行结合 kill 命令使用

    2. reload 重载配置文件真相

      image-20210216200509924

      image-20210216200645297

    3. 热升级的完整流程

      image-20210216200813214

      image-20210216200839986

Nginx 架构基础 (二)

  1. 网络收发与 Nginx 事件间的对应关系

    image-20210219160443138

    image-20210219160513587

    image-20210219160530518

  2. Nginx 网络事件实例演示

    抓包工具:https://www.wireshark.org/#download

    • TCP 层:本地打开了 54756,Nginx 打开的是 8080 端口 进程与进程通信

      image-20210219162313093

    • IP 层:本机 IP 地址:192.168.1.196 nginx 服务器的 IP 地址:127.0.0.1

      image-20210219162424652

    • 三次握手

      windows 先向 nginx 发送一个 SYN
      相反的 nginx 所在的 linux 也会向 windos 发送一个 SYN,这个时候 nginx 是没有感知到的、因为这是一个半打开的状态
      直到 widows 再向 nginx 所在的 linux 服务器发送一个 ACK 时,linux 操作系统才会通知 nginx 这时有一个读事件需要处理

      image-20210219162528218

  3. epoll 的优劣及原理

    image-20210219163036992

详解 HTTP 模块

  1. 冲突的配置指令以谁为准?

    • 配置块的嵌套

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      main
      http {
      upstream { … }
      split_clients {…}
      map {…}
      geo {…}
      server {
      if () {…}
      location {
      limit_except {…}
      }
      location {
      location {
      }
      }
      }
      server {
      }
      }
    • 指令的 Context

      1
      2
      3
      4
      5
      6
      7
      8
      9
      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
    • 指令的合并

      image-20210219171225935

    • 存储值的指令集成规则:向上覆盖

      子配置不存在时,直接使用父配置块;

      子配置存在时,直接覆盖父配置块。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      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 个阶段
      • 指令允许出现在那些块下?
      1
      2
      3
       { 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);
  2. Listen 指令

    1
    2
    3
    4
    5
    6
    7
    8
    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];
  3. 处理 HTTP 请求头部的流程

    • 接收请求事件模块

    image-20210219172504477

    • 接收请求 HTTP 模块

      image-20210219172554657

  4. 如何找到处理请求的 server 指令块

    image-20210219173022622

    • server 匹配顺序

      1、精确匹配

      2、* 在前的泛域名

      3、* 在后的泛域名

      4、按文件中的顺序匹配正则表达式域名

      5、default server

      ​ 第 1 个

      ​ listen 指定 default

  5. 详解 HTTP 请求的 11 个阶段

    image-20210219174238372

    image-20210219174301234

    参考地址:https://www.cnblogs.com/luoahong/p/13542203.html

    11 个阶段的顺序处理

    image-20210219174359347

    阶段 使用的模块 备注
    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 日志的
  6. postread 阶段:获取真实客户端地址的 realip 模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [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 指令

    image-20210220095721052

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    [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>

  8. rewrite 阶段的 rewrite 模块:重写 URL

    image-20210220105241215

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    [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 模块:条件判断

    image-20210220111128109

    image-20210220111152689

  10. find_config 阶段:找到处理请求的 location 指令块

    image-20210220111520074

    image-20210220111635553

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    [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!
  11. preaccess 阶段:对连接做限制的 limit_conn 模块

    image-20210220113226272

    image-20210220113240479

    限制发生时的日志级别

    1
    2
    3
    Syntax: limit_conn_log_level info | notice | warn | error;
    Default: limit_conn_log_level error;
    Context: http, server, location

    限制发生时向客户端返回的错误码

    1
    2
    3
    Syntax: limit_conn_status code;
    Default: limit_conn_status 503;
    Context: http, server, location

    image-20210220114938614

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    [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
  12. preaccess 阶段:对请求做限制的 limit_req 模块

    image-20210220134607600

    限制发生时的日志级别

    1
    2
    3
    Syntax: limit_req_log_level info | notice | warn | error;
    Default: limit_req_log_level error;
    Context: http, server, location

    限制发生时向客户端返回的错误码

    1
    2
    3
    Syntax: limit_req_status code;
    Default: limit_req_status 503;
    Context: http, server, location
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    [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访问在前。
  13. access 阶段:对 ip 做限制的 access 模块

    如何限制某些 IP 地址的访问权限。

    image-20210220135653450

  14. access 阶段:对用户名密码做限制的 auth_basic 模块

    auth_basic 模块指令:

    image-20210220135930926

    1
    2
    3
    4
    5
    6
    7
    # 安装工具包
    [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
  15. access 阶段:使用第三方做权限控制的 auth_request 模块

    重新编译安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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;
    }
    }
  16. access 阶段的 satisfy 指令

    image-20210220144001826

    • 如果有 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

      有影响

    • 输对密码,下面可以访问到文件吗?可以

      1
      2
      3
      4
      5
      6
      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 执行。

  17. precontent 阶段:按序访问资源的 try_files 模块

    image-20210220145724664

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    [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
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
  18. 实时拷贝流量:precontent 阶段的 mirror 模块

    image-20210220145825406

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    # 本地服务
    [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 指令

    image-20210220151043106

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    [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/
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    # 日志信息
    2021/02/20 15:13:46 [error] 300277#0: *5 "/usr/local/nginx/html/root/index.html" is not found (2: No such file or directory), client: 127.0.0.1, server: static.test.com, request: "GET /root/ HTTP/1.1", host: "static.test.com"

    [root@ecs conf.d]# curl static.test.com/root/1.txt
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>

    # 日志信息
    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>
    <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>
    [root@ecs conf.d]# curl static.test.com/alias/1.txt
    test1
  20. static 模块提供的 3 个变量

    image-20210220151851113

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 建立软连接
    [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

      image-20210220152721793

    • 未找到文件时的错误日志

      image-20210220152732954

  21. static 模块对 url 不以斜杠结尾却访问目录的做法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    [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 模块

      image-20210220155143765

    • 随机 index.html 文件:content 阶段的 autoindex 模块

      image-20210220155228796

    • 显示目录内容:content 阶段的 autoindex 模块

      image-20210220155333189

    • autoindex 模块的指令

      image-20210220155500362

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      [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>
      <head>
      <title>Welcome to nginx!</title>

      # ****** 以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
      <html>
      <head><title>Index of /</title></head>
      <body>
      <h1>Index of /</h1><hr><pre><a href="../">../</a>
      <a href="first/">first/</a> 20-Feb-2021 15:23 -
      <a href="realpath/">realpath/</a> 20-Feb-2021 15:23 -
      <a href="second/">second/</a> 20-Feb-2021 10:59 -
      <a href="third/">third/</a> 20-Feb-2021 10:59 -
      <a href="403.html">403.html</a>
  23. 提升多个小文件性能的 concat 模块

    image-20210220160243581

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    # 安装concat模块
    git clone git://github.com/alibaba/nginx-http-concat.git
    [root@ecs nginx]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_realip_module --with-http_auth_request_module --add-module=/data/soft/nginx/nginx-http-concat

    [root@ecs conf.d]# cat concat.conf
    server {
    server_name concat.test.com;

    error_log logs/myerror.log debug;
    concat on;
    root html;

    location /concat {
    concat_max_files 20;
    concat_types text/plain;
    concat_unique on;
    concat_delimiter ':::';
    concat_ignore_file_error on;
    }

    }
    [root@ecs conf.d]# curl concat.test.com/concat/??1.txt,2.txt
    test1
    :::test2
  24. access 日志的详细用法

    • access 日志格式

      image-20210220163039376

    • 配置日志文件路径

      image-20210220163109724

    • 对日志文件名包含变量时的优化

      image-20210220163147343

  25. HTTP 过滤模块的调用流程

    image-20210220163539880

    image-20210220163657268

  26. 用过滤模块更改响应中的字符串:sub 模块

    image-20210220163738030

    image-20210220163752610

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    # 添加模块
    [root@ecs nginx]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_realip_module --with-http_auth_request_module --add-module=/data/soft/nginx/nginx-http-concat --with-http_sub_module

    [root@ecs conf.d]# cat sub.conf
    server {
    server_name sub.test.com;
    error_log logs/myerror.log info;

    location / {
    #sub_filter 'Nginx.oRg' '$host/nginx';
    #sub_filter 'nginX.cOm' '$host/nginx';
    #sub_filter_once on;
    #sub_filter_once off;
    #sub_filter_last_modified off;
    #sub_filter_last_modified on;
    }
    }
    [root@ecs conf.d]# curl sub.test.com
    <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>

    #进行替换
    [root@ecs conf.d]# cat sub.conf
    server {
    server_name sub.test.com;
    error_log logs/myerror.log info;

    location / {
    sub_filter 'Nginx.oRg' '$host/nginx';
    sub_filter 'nginX.cOm' '$host/nginx';
    sub_filter_once on;
    #sub_filter_once off;
    sub_filter_last_modified off;
    #sub_filter_last_modified on;
    }
    }
    [root@ecs conf.d]# curl sub.test.com
    <a href="http://sub.test.com/nginx/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://sub.test.com/nginx/">nginx.com</a>.</p>

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

    # 全部替换
    location / {
    sub_filter 'Nginx.oRg' '$host/nginx';
    sub_filter 'nginX.cOm' '$host/nginx';
    #sub_filter_once on;
    sub_filter_once off;
    #sub_filter_last_modified off;
    sub_filter_last_modified on;
    }

    [root@ecs conf.d]# curl sub.test.com
    <p>For online documentation and support please refer to
    <a href="http://sub.test.com/nginx/">sub.test.com/nginx</a>.<br/>
    Commercial support is available at
    <a href="http://sub.test.com/nginx/">sub.test.com/nginx</a>.</p>

  27. 用过滤模块在 http 响应的前后添加内容:addition 模块

    image-20210220165320179

    image-20210220165104305

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    # 添加模块
    [root@ecs nginx]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_realip_module --with-http_auth_request_module --add-module=/data/soft/nginx/nginx-http-concat --with-http_sub_module --with-http_addition_module

    [root@ecs conf.d]# cat addition.conf
    server {
    server_name addition.test.com;
    error_log logs/myerror.log info;

    location / {
    add_before_body /before_action;
    add_after_body /after_action;
    addition_types *;
    }
    location /before_action {
    return 200 'new content before\n';
    }
    location /after_action {
    return 200 'new content after\n';
    }

    location /testhost {
    uninitialized_variable_warn on;
    set $foo 'testhost';
    return 200 '$gzip_ratio\n';
    }

    }
    [root@ecs conf.d]# curl addition.test.com/a.txt
    new content before
    aaa
    new content after
  28. Nginx 变量的运行原理

    • 变量的惰性求值

      image-20210220165957254

    • 变量的特性

      • 惰性求值

      • 变量值可以时刻变化,其值为使用时的那一刻的值

  29. HTTP 框架提供的请求相关的变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    [root@ecs conf.d]# cat var.conf 
    log_format vartest '$remote_addr - $remote_user [$time_local] "$request" '
    '$status bytes_sent=$bytes_sent body_bytes_sent=$body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$sent_http_abc"';

    server {
    server_name var.test.com localhost;
    #error_log logs/myerror.log debug;
    access_log logs/vartest.log vartest;
    listen 9090;

    location / {
    set $limit_rate 10k;
    return 200 '
    arg_a: $arg_a,arg_b: $arg_b,args: $args
    connection: $connection,connection_requests: $connection_requests
    cookie_a: $cookie_a
    uri: $uri,document_uri: $document_uri, request_uri: $request_uri
    request: $request
    request_id: $request_id
    server: $server_addr,$server_name,$server_port,$server_protocol
    tcpinfo: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space
    host: $host,server_name: $server_name,http_host: $http_host
    limit_rate: $limit_rate
    hostname: $hostname
    content_length: $content_length
    status: $status
    body_bytes_sent: $body_bytes_sent,bytes_sent: $bytes_sent
    time: $request_time,$msec,$time_iso8601,$time_local
    ';
    }
    }
    [root@ecs conf.d]# curl -H 'Content-Length: 0' -H 'Cookie: a=c1' 'localhost:9090?a=1&b=22'

    arg_a: 1,arg_b: 22,args: a=1&b=22
    connection: 4,connection_requests: 1
    cookie_a: c1
    uri: /,document_uri: /, request_uri: /?a=1&b=22
    request: GET /?a=1&b=22 HTTP/1.1
    request_id: 00c17d3d3fe9a07a362e7709ef28aab9
    server: 127.0.0.1,var.test.com,9090,HTTP/1.1
    tcpinfo: 12, 6, 10, 43690
    host: localhost,server_name: var.test.com,http_host: localhost:9090
    limit_rate: 10240
    hostname: ecs
    content_length: 0
    status: 200
    body_bytes_sent: 0,bytes_sent: 0
    time: 0.000,1613812049.725,2021-02-20T17:07:29+08:00,20/Feb/2021:17:07:29 +0800
  30. HTTP 框架提供的其他变量

    image-20210220171005344

    image-20210220171017970

    image-20210220171026325

    image-20210220171035536

    image-20210220171048990

    image-20210220171104655

  31. 使用变量防盗链的 referer 模块

    image-20210220171329363

    image-20210220171401234

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    [root@ecs conf.d]# cat referer.conf 
    server {
    server_name referer.test.com;

    error_log logs/myerror.log debug;
    root html;
    location /{
    valid_referers none blocked server_names
    *.test.pub www.test.org.cn/nginx/
    ~\.google\.;

    if ($invalid_referer) {
    return 403;
    }

    return 200 'valid\n';
    }

    }
    [root@ecs conf.d]# curl -H 'referer: http://www.test.org.cn/ttt' referer.test.com/
    <html>
    <head><title>403 Forbidden</title></head>
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    [root@ecs conf.d]# curl -H 'referer: http://www.test.pub/ttt' referer.test.com/
    valid
    [root@ecs conf.d]# curl -H 'referer: ' referer.test.com/
    valid
    [root@ecs conf.d]# curl referer.test.com/
    valid
    [root@ecs conf.d]# curl -H 'referer: http://www.test.com' referer.test.com/
    <html>
    <head><title>403 Forbidden</title></head>
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    [root@ecs conf.d]# curl -H 'referer: http://referer.test.com' referer.test.com/
    valid
    [root@ecs conf.d]# curl -H 'referer: http://image.baidu.com/search/detail' referer.test.com/
    <html>
    <head><title>403 Forbidden</title></head>
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    [root@ecs conf.d]# curl -H 'referer: http://image.google.com/search/detail' referer.test.com/
    valid
  32. 使用变量实现防盗链功能实践:secure_link 模块

    image-20210220172815652

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    # 添加模块
    [root@ecs nginx]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_realip_module --with-http_auth_request_module --add-module=/data/soft/nginx/nginx-http-concat --with-http_sub_module --with-http_addition_module --with-http_secure_link_module


    [root@ecs conf.d]# cat secure_link.conf
    server {
    server_name securelink.test.com;
    error_log logs/myerror.log info;
    default_type text/plain;
    location /{
    secure_link $arg_md5,$arg_expires;
    secure_link_md5 "$secure_link_expires$uri$remote_addr secret";

    if ($secure_link = "") {
    return 403;
    }

    if ($secure_link = "0") {
    return 410;
    }

    return 200 '$secure_link:$secure_link_expires\n';
    }

    location /p/ {
    secure_link_secret mysecret2;

    if ($secure_link = "") {
    return 403;
    }

    rewrite ^ /secure/$secure_link;
    }

    location /secure/ {
    alias html/;
    internal;
    }
    }
    # 生成hash摘要
    [root@ecs conf.d]# echo -n '52656565776/test1.txt127.0.0.1 secret' | openssl md5 -binary | openssl base64 | tr +/ - | tr -d =
    FQuWy7wgjy9V8yLg7M7ZoA
    [root@ecs conf.d]# curl 'securelink.test.com/test1.txt?md5=FQuWy7wgjy9V8yLg7M7Zo&expires=52656565776'
    <html>
    <head><title>403 Forbidden</title></head>
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    [root@ecs conf.d]# curl 'securelink.test.com/test1.txt?md5=FQuWy7wgjy9V8yLg7M7ZoA&expires=52656565776'
    1:52656565776

    [root@ecs conf.d]# echo -n 'test1.txtmysecret2' | openssl md5 -hex
    (stdin)= c3f9b32bf901b04c052ea9511e29a918
    [root@ecs conf.d]# curl 'securelink.test.com/p/c3f9b32bf901b04c052ea9511e29a918/test1.txt'
    1111
  33. 为复杂的业务生成新的变量:map 模块

    image-20210220174901693

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [root@ecs conf.d]# cat map.conf 
    map $http_host $name {
    hostnames;

    default 0;

    ~map\.test\w+\.org.cn 1;
    *.test.org.cn 2;
    map.test.com 3;
    map.test.* 4;
    }

    map $http_user_agent $mobile {
    default 0;
    "~Opera Mini" 1;
    }
    [root@ecs conf.d]# curl -H 'Host: map.test.com' 127.0.0.1:10001
    3:0
    [root@ecs conf.d]# curl -H 'Host: map.test.org.cn' 127.0.0.1:10001
    2:0
    [root@ecs conf.d]# curl -H 'Host: map.test123.org.cn' 127.0.0.1:10001
    1:0
  34. 通过变量指定少量用户实现 AB 测试:split_client 模块

    image-20210220174922875

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    [root@ecs conf.d]# cat map.conf 
    server {
    listen 10001;
    default_type text/plain;
    location /{
    return 200 '$name:$mobile\n';
    }
    }

    split_clients "${http_testcli}" $variant {
    0.51% .one;
    20.0% .two;
    50.5% .three;
    #40% .four;
    * "";
    }

    server {
    server_name split_clients.test.com;
    error_log logs/error.log debug;
    default_type text/plain;
    location /{
    return 200 'ABtestfile$variant\n';
    }
    }
    [root@ecs conf.d]# curl -H 'testcli: 354165131351315aaaabb' split_clients.test.com/
    ABtestfile
    [root@ecs conf.d]# curl -H 'testcli: 354165131351315aaaabb&&&&ddddddd' split_clients.test.com/
    ABtestfile.three
  35. 根据 IP 地址范围的匹配生成新变量:geo 模块

    image-20210220180038644

    image-20210220180107063

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    [root@ecs conf.d]# cat geo.conf 
    geo $country {
    default ZZ;
    #include conf/geo.conf;
    proxy 127.0.0.1;

    127.0.0.0/24 US;
    127.0.0.1/32 RU;
    10.1.0.0/16 RU;
    192.168.1.0/24 UK;
    }

    server {
    server_name geo.test.com;
    location /{
    return 200 '$country\n';
    }
    }

    [root@ecs conf.d]# ../../sbin/nginx -s reload
    [root@ecs conf.d]# curl -H 'X-Forwarded-For: 10.1.0.0,127.0.0.1,172.27.57.6' geo.test.com
    ZZ
    [root@ecs conf.d]# curl -H 'X-Forwarded-For: 10.1.0.0,127.0.0.1,192.168.1.123' geo.test.com
    UK
    [root@ecs ~]# curl -H 'X-Forwarded-For: 10.1.0.0' geo.test.com
    RU
    [root@ecs ~]# curl -H 'X-Forwarded-For: 10.1.0.0,127.0.0.1' geo.test.com
    RU

  36. 使用变量获得用户的地理位置:geoip 模块

    image-20210222151514513

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    # 添加模块
    [root@ecs nginx]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_realip_module --with-http_auth_request_module --add-module=/data/soft/nginx/nginx-http-concat --with-http_sub_module --with-http_addition_module --with-http_secure_link_module --with-http_geoip_module

    # 下载安装GeoIp(nginx是C语言编写的)
    # 访问地址:https://dev.maxmind.com/geoip/legacy/downloadable/
    # 下载地址:https://github.com/maxmind/geoip-api-c/releases
    # 安装编译
    [root@ecs nginx]# tar -zxvf GeoIP-1.6.12.tar.gz
    [root@ecs GeoIP-1.6.12]# ./configure
    [root@ecs GeoIP-1.6.12]# make
    [root@ecs GeoIP-1.6.12]# make install

    [root@ecs share]# cd /usr/share/GeoIP
    [root@ecs GeoIP]# ll
    total 59784
    lrwxrwxrwx 1 root root 18 Feb 16 17:12 GeoIP.dat -> GeoLiteCountry.dat
    -rw-r--r--. 1 root root 56548946 Jun 8 2018 GeoLite2-City.mmdb
    -rw-r--r--. 1 root root 3423846 Jun 8 2018 GeoLite2-Country.mmdb
    -rw-r--r-- 1 root root 1242574 Apr 4 2018 GeoLiteCountry.dat

    [root@ecs conf.d]# cat geoip.conf
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    geoip_city /usr/share/GeoIP/GeoLiteCountry.dat;
    geoip_proxy 127.0.0.1/32;
    geoip_proxy_recursive on;

    server {
    server_name geoip.test.com;
    error_log logs/myerror.log info;
    keepalive_requests 2;
    keepalive_timeout 75s 20;
    location /{
    return 200 'country:$geoip_country_code,$geoip_country_code3,$geoip_country_name
    country from city:$geoip_city_country_code,$geoip_city_country_code3,$geoip_city_country_name
    city:$geoip_area_code,$geoip_city_continent_code,$geoip_dma_code
    $geoip_latitude,$geoip_longitude,$geoip_region,$geoip_region_name,$geoip_city,$geoip_postal_code
    ';
    }
    }
    [root@ecs ~]# curl -H 'X-Forwarded-For: 124.205.155.154' geoip.test.com
  37. 对客户端使用 keepalive 提升连接效率

    image-20210222160836086