Nginx笔记(未完成)

本文最后更新于:2022年1月17日 凌晨

本文主要整理 Nginx 学习中的一些重要知识点。

本文中测试环境部分为 Nginx 官方 Docker 镜像,Nginx 版本:1.20.5

Nginx 容器相关

创建镜像

Dockerfile

FROM nginx:stable

VOLUME [ "/var/log/error.log", "/var/run/", "/etc/nginx", "/usr/share/nginx"]

COPY ./application.conf /etc/nginx/conf.d/
COPY ./nginx.conf /etc/nginx/nginx.conf

nginx.conf

user  nginx;
worker_processes  auto;

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


events {
    worker_connections  1024;
}


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

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

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

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;
  
  
    include /etc/nginx/conf.d/application.conf;
}

application.conf

用于连接远程服务器的 Application Server

upstream application {
    server ip:port;
    keepalive 32;
    keepalive_requests 100;
    keepalive_timeout 60s;
}

server {
    listen *:80;
    server_name localhost;

    location / {
        proxy_pass http://application/;
    }
}

Docker CMD

docker build -t nginx:self .

docker run --name nginx_self -p 80:80 -d nginx:self

使用命令查看 Nginx 相关路径

nginx -h

Beginner’s Guide

nginx has one master process and several worker processes. The main purpose of the master process is to read and evaluate configuration, and maintain worker processes.

Nginx 拥有一个主进程和一些工作进程,主进程的作用主要是读取并校验配置文件,并维护工作进程。

nginx employs event-based model and OS-dependent mechanisms to efficiently distribute requests among worker processes.

Nginx 采用基于事件的模型,并且依赖操作系统的机制来有效地在工作进程间分配请求。

To start nginx, run the executable file. Once nginx is started, it can be controlled by invoking the executable with the -s parameter. Use the following syntax:

# -s means -singal
nginx -s signal

Where signal may be one of the following:

  • stop — fast shutdown

    快速关闭

  • quit — graceful shutdown

    等待工作进程处理完毕之后关闭

  • reload — reloading the configuration file

    重新加载配置文件,当主进程导入配置文件并且成功,Nginx 会重新启动新的工作进程,并发送信息给旧的工作进程,让他们完成任务后 shut down,期间,旧的工作进程不会接受新的请求。如果失败则回滚,使用原来的工作进程。

  • reopen — reopening the log files

For getting the list of all running nginx processes, the ps utility may be used, for example, in the following way:

# invalid in container
ps -ax | grep nginx

nginx.conf

main

# 如果主进程使用root运行,那么nginx 将会调用 setuid()/setgid() 去设置 user/group。
# 如果 group 没有特别指定,那么 nginx 会使用 user 相同的名称设置 group。
# 默认为 nobody nogroup 或者安装nginx的时候在 ./configure 指定的 --user=USER 和 --group=GROUP
user nginx;

pid /run/nginx.pid;

# 指定异常退出后生层 core 文件 大小 位置
# worker_rlimit_core 50M;
# worker_directory /etc/nginx/temp

# 指定 Nginx 的工作进程个数(可用auto)
worker_processes 2;

# 指定 worker 子进程最大句柄数,linux 默认最大句柄数为 65535
worker_rlimit_nofile 1024;

# 绑定 Nginx 工作进程到某个 CPU
# 好处:减少进程在不同CPU间上下文切换所浪费的资源,充分利用 CPU 缓存
# 注意:此处意思并不是完全避免进程上下文切换
# 两个物理核心,两个 worker 进程,诸如以下示例
worker_cpu_affinity 01 10;
# 两个物理核心,四个 worker 进程
# 意思就是第一三个进程用一个核心,二四进程用另一个核心
# worker_cpu_affinity 01 10 01 10

# 指定工作进程 nice 值,调整 nginx 进程优先级,通常设定为负值,以优先调用nginx
# linux 默认优先级为 120,值越小越优先,nice 设定范围 -20 ~ 19
# priority = 120 + nice
worker_priority -10;

# 指定 worker 进程优雅退出的超时时间
# worker_shutdown_timeout 5s;

# 指定 worker 子进程内部调用内核态计时器的时间,调整时间间隔越大,系统调用越少,有利于性能提升
timer_resolution 100ms;

# 开启守护进程
daemon on;

# 负载均衡锁文件默认配置
# lock_file logs/nginx.lock;

补充知识

客户端请求流程

用户向服务器发起请求,网卡接收到请求,内核态通过 TCP/IP 解析 IP 和端口,找到对应监听这个 IP 和端口的程序,程序进程进行处理。过程中,程序会获取内核态的一些信息,比如计时器等,由于工作进程在用户态,因此内核态和用户态的切换会消耗资源。

events

events {
  # 使用 linux 的io复用模型
  # 推荐默认
  # use epoll;
  
  # 每个 worker 子进程的最大连接数
  # 推荐 65535 / worker_processes || 65535
  # 注意,上面定义了worker进程的句柄数,不要超过
  worker_connections 1024;
  
  # 开启负载均衡锁
  # 当关闭时,master 给所有 worker 都发一次信号,唤醒所有 worker 来争抢这个请求
  # 打开时,相当于让 worker 串行获取请求的锁,其它进程就获取不到这个请求了
  # 推荐打开
  accept_mutex on;
  
  # 如果负载均衡给一个 worker,但超时指定时间不响应,master 就分发给其他 worker
  accept_mutex_delay 200ms;
  
  # 让 worker 子进程在同一时刻接收多个请求
  multi_accept on;
  
}

补充知识

accept_mutex 详解

IO复用技术

http

http {
  server {
    listen 80;
    # 注意。其中的 server_name 的选择是根据请求头中的 host (或者https中的:authority)字段来判断
    server_name www.rootzwy.com;
    root html/domain_vm1;
    location / {
      index index.html;
    }
  }
}

补充知识

root 和 alias 的区别:root 作用域比 alias 大,且 root 在寻找磁盘文件时会在后面加上 location 后的路径,而 alias 不会。

location

匹配规则 含义 示例
= 精确匹配,匹配优先级最高 location = /images/ {}
~ 区分大小写正则匹配,优先级第三高 location ~ \.(jpg|gif)$ {}
~* 不区分大小写正则匹配,优先级第四高 location ~* \.(jpg|gif)$ {}
^~ 匹配到停止搜索,比如:/images?id=11&name=11,优先级第二高 location ^~ /images/ {}
不带符号 location / {}

补充知识

location 中带不带斜杠的区别

http {
  root html;
  server {
    # 按照目录匹配,如果不存在,也不会按照文件匹配
    location /img/ {
      
    }
	}
  server {
    # 首先按目录进行匹配,如果匹配失败,将img按文件匹配
    location /img {
      
    }
  }
}

反向代理

img

反向代理在生产环境中是很常用的实现负载均衡的一个手段,也是处理动态请求的常用方法。

反向代理优势

隐藏真实服务器,实现 Application 的封装。

便于横向拓展后端动态服务。

动静分离,提升系统健壮性。

动静分离

指的是静态资源请求直接由 nginx 服务器返回,动态请求则按一定的策略分发给反向代理的 Application Server,Application Server 处理完请求后,发送给 nginx ,nginx 再将请求回传给用户。

除此之外,反向代理的好处就是实现 Application Server、Nginx(HTTP Server)、Client 之间传输协议的解耦,用户可以用 http 请求访问 nginx ,而 nginx 可以用 grpc 等其他协议与 Application Server 交互。

实例

在 conf.d 目录下创建 app_server,创建一个简易的应用服务器(此处可以替换为Application Server)

server {
    listen 8080;
    server_name localhost;
   
    location /proxy/ {
        root /opt/nginx/html/app;
        index proxy.html;
    }
}

在另一个nginx上配置反向代理:

upstream upstreamName {
    server ip:port weight 3 max_conns=1000 fail_timeout=10s max_fails=3;
    keepalive 32;
    keepalive_requests 80;
    keepalive_time_out 20s;
}

server {
    listen 80;
    server_name name;
    
    # 史前巨坑,在 location 路径存在时(如:/ali),spring boot 2.6.1 会显示 url 错误,报错为:存在两条下划线(如://security/..),若 location 为 / 时正常运行,除此之外,如果 Spring Boot 没有 指定 mvc context,也无法正常运行。
    location /path {
        proxy_pass http://upstreamName/;
    }   
}

proxy_pass 加不加 / 的区别

加 / 会自动去掉 location 中的 path,然后上传到上游服务器。不加,则 path 原封不动,上传到上游服务器。

proxy_request_buffering

作用域:http、server、location

默认值:on

nignx 开启缓冲区,用于缓存请求体,等待接收请求发送完毕再发送至 Application Server,能减少上游服务器的并发量。

除此之外,开启缓冲区还能减少磁盘 IO

client_max_body_size

作用域:http、server、location

默认值:1M

根据 Content-Length 判断,大于该参数则返回 412 Response,如果小于,则存储到内存中。

client_body_buffer_size

作用域:http、server、location

默认值:8k | 16k

client_body_in_single_buffer

作用域:http、server、location

默认值:off

让请求体在内存中尽量按照顺序存储,减少读取开销。

还有许多有用的指令,待以后补充……

HTTP请求更改

状态行

proxy_method

proxy_http_version

请求头

proxy_set_header

默认:

proxy_set_header Host $proxy_host

proxy_set_header Connection close

proxy_pass_request_header

默认:on

请求体

proxy_set_body

proxy_pass_request_body