编译所需依赖库

  • GCC : 编译器
  • PCRE : 用于正则表达式处理
  • zlib : 用于 gzip 处理
  • openssl : 用于HTTPS, MD5 等处理

    sudo apt-get update 
    build-essential libtool gcc automake autoconf make
    sudo apt-get install openssl libssl-dev
    sudo apt-get install zlib1g-dev
    sudo apt-get install libpcre3 libpcre3-dev
    

系统常用参数配置

查看原来的值

sysctl fs.file-max
sysctl net.ipv4.tcp_tw_reuse
sysctl net.ipv4.tcp_keepalive_time
sysctl net.ipv4.tcp_fin_timeout
sysctl net.ipv4.tcp_max_tw_buckets
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem
sysctl net.core.netdev_max_backlog
sysctl net.core.rmem_default
sysctl net.core.wmem_default
sysctl net.core.rmem_max
sysctl net.core.wmem_max
sysctl net.ipv4.tcp_syncookies
sysctl net.ipv4.tcp_max_syn_backlog

/etc/sysctl.conf

fs.file-max=999999
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_keepalive_time=600
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_max_tw_buckets=5000
net.ipv4.ip_local_port_range=1024 65535
net.ipv4.tcp_rmem=4096 32768 262142
net.ipv4.tcp_wmem=4096  32768 262142
net.core.netdev_max_backlog=8096
net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=2097152
net.core.wmem_max=2097152
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_max_syn_backlog=1024

查看某个值: sysctl net.ipv4.ip_local_port_range
之后执行 sudo sysctl -p 命令来生效

陶辉 著. 深入理解Nginx:模块开发与架构解析(第2版) (Linux/Unix技术丛书) (Chinese Edition) (Kindle Locations 427-430). Kindle Edition. 

编译/控制命令

查看编译参数 ./configure --help

./configure
make -j8
make install

常用命令

# 启动
nginx

# 指定配置文件
nginx -c path/to/nginx.conf

# 显示版本
nginx -v

# 显示编译参数
nginx -V

# 快速停止. 注意, 这种是不会等处理完请求的...
nginx -s stop
等效于
kill -s SIGTERM pid
kill -s SIGINT pid

# 优雅停止
nginx -s quit
等效于
kill -s SIGQUIT pid

停止 worker 的话则
kill -s SIGWINCH workerPid

# 重新读取配置文件
nginx -s reload

# 日志文件回滚
nginx -s reopen 
等效于
kill -s SIGUSR1 pid

Nginx配置

  • 配置项的单位. K 或 k 表示 KB, M 或 m 表示 MB
  • 时间的单位: ms, s, m, h, d, w, M, y

核心功能配置 http://nginx.org/en/docs/ngx_core_module.html

注意, 如果想要 debug 信息, 需要在编译时, 加上 --with-debug 配置项

  • include 指令, 可以是绝对路径, 也可以相对路径(即相对于 nginx.conf 所在的目录)

性能配置项

worker_processes
worker_cpu_affinity
worker_rlimit_nofile
# ssl 硬件加速
ssl_engine
# 系统调用 gettimeofday 的执行频率
timer_resolution
# worker 进程的 nice 优先级. -20 ~ 19 . 越小表示优先级越高
worker_priority

事件配置项

# 负载均衡锁. 它可让多个 worker 轮流地, 序列化地与新客户建立 TCP. 当某个 woker 达到 worker_connections 配置的最大连接数的 7/8 时, 会大大减小该 woker 试图建立连接的机会
accept_mutex

# accept_mutex 可能需要. 只有在开启 accept_mutex , 并且系统不支持原子锁, 才会用文件锁来实现
lock_file

# 使用锁后到真正建立连接之间的延迟时间. 即如果 worker 试图获取 accept 锁而没有取到, 则至少等待该时间间隔后才能再次试图获取
accept_mutex_delay 

# 批量建立连接. 即尽可能地对本次调度中客户端发起的所有 TCP 请求都建立连接
multi_accept

虚拟主机

每个 server 块就是一个虚拟主机. 可显式通过 default 指定整个 Web 服务的默认虚拟主机.

如果没有指定 default , 则会在 nginx.conf 中找到的第一个 server 作为默认的虚拟主机.

deferred 指令. 只有连接真正有数据时, 才会唤醒 worker 来处理这个连接, 而不是建立连接时就唤醒.

server_name 指令匹配

  • header 中获取 Host, 然后与每个 server 中的 server_name 匹配
  • 首先完全匹配 server_name . 如 www.qq.com
  • 其次通配符在前端的 server_name . 如 *.qq.com
  • 再次通配符在后面的. 如 www.qq.*
  • 最后使用正则才匹配的.
  • 如果以上都不匹配. 则再按以下顺序处理
    • 优先 listen 后加上 default 的 server
    • 找到匹配 listen 的第一个 server
  • 如果 server_name 后是字字符串, 那么表示匹配没有 Host 这个 HTTP 头部的请求

server_name_hash_bucket_size , nginx 使用散列表来存储 server name . 该参数表示每个散列桶占用的内存大小.

server_name_hash_max_size : 它会影响散列表的冲突率. 越大, 冲突越小, 检索速度也越快.

location 指令. 匹配规则

  • = 表示把 URI 作为字符串, 以便与参数中的 uri 做完全匹配
  • ~ 表示匹配 URI 时是大小写敏感的
  • ~* 表示 URI 大小写不敏感
  • ^~ 表示只需要前半部分与 uri 参数匹配即可
  • @ 仅用于 nginx 内部请求之间的重定向, 不直接处理用户请求.
  • uri 参数可以用正则表达式
  • 它是有顺序的, 请求会被第一个匹配到的 location 处理

root 指令 . 路径配置

  • 它定义的是相对于 HTTP 请求的根目录.
  • 例如 root /opt/html/; 则请求的 URI 是 /res/hello.html, 则文件完整的路径为 /opt/html/res/hello.html

alias 指令.

  • 它不同于 root. 它是解读紧跟在 location 后的 uri 参数的.
  • 一个请求 /res/hello.html , 而实际想访问的是 /opt/html/res/hello.html
  • 则配置为 location /res { alias /opt/html/res/; }
  • 如果为 root 则是 /opt/html/

index 指令: 访问首页. 可跟多个文件参数. 按顺序优先访问.

error_page code : 根据错误码重定向新 URI

内存及磁盘分配

# 请求 body 只存储到文件. on 表示请求完后不删除. clean 表示请求完后删除
client_body_in_file_only

# 请求头保存时分配的 buffer 大小. 有时会超过该大小, 这时 large_client_header_buffers 将会生效
client_header_buffer_size

# 超大请求头. 如果请求行大小超过单个 buffer 大小, 则返回 Request URI too large 414. (注意, 是请求行, 即请求头的每一行)
# 请求行和请求头的总和, 不可以超过 buffer 个数 *  buffer 大小
large_client_header_buffers

# 存储请求 body 的内存 buffer 大小
client_body_buffer_size

# 请求 body 临时存放目录. 如果 body 大小超过 client_body_buffer_size, 则会以一个递增的整数命名并存放到 client_body_temp_path 指定的目录中. 后面的 level1, level2, level3 是为了防止一个目录下的文件数量太多, 从而导致性能下降, 因此使用了 level 参数.
client_body_temp_path

# 每个建立成功的 TCP 会预先分配一个内存池, 这个参数将指定内存池的初始大小. TCP 连接关闭时会销毁.
connection_pool_size

# 为每个请求都分配一个内存池. 该参数指定初始大小.http 请求结束时会销毁. 注意, 一条连接, 可能被复用于多个请求
request_pool_size

网络连接配置

# 读取 header 时超时
client_header_timeout

# 读取 body 时超时
client_body_timeout

# 发送响应超时. 即服务器向 client 发送了数据, 但客户端一直没接收 
send_timeout

# 连接超时后, 向客户端发送 RST 包来重置连接
reset_timedout_connection

# nginx 关闭用户连接的方式. 
## always 表示无条件处理连接上所有用户发送的数据. 
## off 表示不管连接是否有数据
## on 中间值. 一般会处理完数据.
lingering_close

# 经过 lingering_time 后, nginx 将不管用户是否仍在发送数据, 都会将连接关闭
lingering_time

# lingering_close 生效后, 在关闭之前, 会检测是否有用户数据到达. 超过 lingering_timeout 时间后还没有数据, 则直接关闭连接. 否则在读取完连接缓冲区上的数据并丢弃后才会关闭连接
lingering_timeout

keepalive_timeout

# 一个 keepalive 长连接上允许承载的请求最大数(注意, 是按每条)
keepalive_requests

tcp_nodelay

tcp_nopush

core module 的变量

http://nginx.org/en/docs/http/ngx_http_core_module.html#variables

变量 描述
$arg_name 请求参数中的某个值
$args$query_string 请求中的完整参数
$binary_remote_addr 二进制客户端IP地址
$body_bytes_sent 发送给 client 的 body 大小没包含 header
$bytes_sent 发送给 client 的总大小
$connection 连接序列号
$connection_requests 连接中的请求数
$content_length 请求中的 content_length
$content_type 请求中的 content_type
$cookie_name 获取 cookie 中的 name 的值
$document_root 当前请求的 rootalias
$document_uri$uri 当前请求的 URI
$host 请求的 Host
$hostname
$http_name 获取 http header 中指定的 name 的值
$https 是否是 https
$is_args 如果有请求参数, 则返回 ? , 否则为空字符串
$limit_rate 当前限速
$msec 当前时间, 秒, 精度到毫秒
$nginx_version Nginx 版本
$pid Worker 的 pid
$pipe 请求是否 pipeline. 是的话为 p, 否则为 .
$proxy_protocol_addr 从代理协议中获取客户端地址
$proxy_protocol_port 从代理协议中获取客户端端口
$proxy_protocol_server_addr 从代理协议中获取服务器地址
$proxy_protocol_server_port 从代理协议中获取服务器端口
$realpath_root 请求的真实资源路径. 从 root 或 alias 中解析
$remote_addr Client 地址
$remote_port client 端口
$remote_user 从 Basic 认证中获取的用户名
$request 完整的请求行
$request_body 请求 body. 只有在传给 proxy_pass, fastcgi_pass, uwsgi_pass, and scgi_pass 指令时, 该参数才有值
$request_body_file 保存请求 body 的临时文件
$request_completion 请求是否完成. OK 表示完成. 否则返回空字符串
$request_filename 当前请求的文件路径
$request_id 当前请求的唯一 ID 标识
$request_length 当前请求的大小. 包含请求行, header, body,
$request_method 当前请求的方法类型
$request_time 当前请求的处理时间. 它是从读取 client 的第一个字节算起.
$request_uri 完整的 URI, 包含参数
$scheme 协议名. 如 http 或 https
$sent_http_name 发送指定的响应头 name
$sent_trailer_name 发送指定响应字段 name
$server_addr 服务器地址
$server_name
$server_port
$server_protocol 请求协议. 如 HTTP/1.1
$status 响应状态码
$tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space 在所有支持 tcp_info 系统上的 socket 选项有效
$time_iso8601 ISO 8601 时间格式
$time_local Common Log Format 时间格式

反向代理

  • Nginx 是在接收完 client 的请求后缓存数据, 然后再向上游服务器发起连接
  • Squid 则是一边接收, 一边传到上游服务器

负载均衡

http://nginx.org/en/docs/http/ngx_http_upstream_module.html

注意, backup 参数不能用在 hash, ip_hash, and random 均衡算法中.

Upstream 的变量. 支持记录到日志中.

http://nginx.org/en/docs/http/ngx_http_upstream_module.html#variables

变量 描述
$upstream_addr 处理请求的 upstream 的地址
$upstream_bytes_received 从 upstream server 中接收到的字节数
$upstream_bytes_sent 发送到 upstream server 的字节数
$upstream_cache_status 访问响应缓存状态
$upstream_connect_time 与 upstream server 建立连接消耗的时间. 如果是 SSL, 则包括handshake时间.
$upstream_cookie_*name* Upstream server 中set-cookie 中指定 name 的 cookie 值
$upstream_header_time 从 upstream server 中获取响应的 header 的耗时
$upstream_http_name 从 upstream server 中获取响应的指定 header
$upstream_queue_time 在 upstream queue 中消耗的时间
$upstream_response_length 从 upstream server 中获取响应的长度
$upstream_response_time 从 upstream 获取响应的耗时
$upstream_status 从 upstream server 中获取状态码
$upstream_trailer_name 从 upstream server 响应中获取指定字段

Nginx 处理 HTTP 的11 个阶段

  1. NGX_HTTP_POST_READ_PHASE : 接收到客户发送的完整 HTTP 请求头时执行
  2. NGX_HTTP_SERVER_REWRITE_PHASE : 将 URI 转换为虚拟主机 ( server )
  3. NGX_HTTP_FIND_CONFIG_PHASE : 根据上一阶段重写后的 URI 检索出匹配的 location 块.
  4. NGX_HTTP_REWRITE_PHASE : 相应的 location 块可能再次利用 rewrite 重写 URL
  5. NGX_HTTP_POST_REWRITE_PHASE : 检查 rewrite 次数不可超过 10 次, 以防 rewrite 死循环
  6. NGX_HTTP_PREACCESS_PHASE : 访问控制预处理
  7. NGX_HTTP_ACCESS_PHASE : 访问验证
  8. NGX_HTTP_POST_ACCESS_PHASE : 访问验证结果处理
  9. NGX_HTTP_TRY_FILES_PHASE : try_files 处理
  10. NGX_HTTP_CONTENT_PHASE : 响应生成阶段
  11. NGX_HTTP_LOG_PHASE : 日志记录

OpenResty 处理阶段

image-20191113173536999

参考资料