跳到主要内容

Nginx

概念

官网链接

  • epoll 系统调用 -> IO 多路复用 -> 单进程高并发
  • sendfile 系统调用 -> 磁盘到网络Socket -> 内核空间传输,不经过用户空间

编译安装

1. 依赖安装

# Ubuntu / Debian
apt update
apt install -y build-essential libpcre3 libpcre3-dev \
zlib1g zlib1g-dev libssl-dev libgd-dev \
libxslt1-dev libgeoip-dev git curl

# CentOS / RHEL
yum groupinstall -y "Development Tools"
yum install -y pcre pcre-devel zlib zlib-devel \
openssl openssl-devel gd gd-devel \
libxslt libxslt-devel GeoIP GeoIP-devel git curl

2. 下载解压

# 查看最新稳定版:https://nginx.org/en/download.html
NGINX_VERSION=1.26.2
cd /usr/local/src
curl -O https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar -xzf nginx-${NGINX_VERSION}.tar.gz
cd /usr/local/src/nginx-${NGINX_VERSION}

3. 下载第三方模块

按需下载
cd /usr/local/src

# headers-more-nginx-module:自定义响应头
git clone https://github.com/openresty/headers-more-nginx-module.git

# ngx_cache_purge:主动清除 FastCGI/proxy 缓存
git clone https://github.com/FRiCKLE/ngx_cache_purge.git

# echo-nginx-module:调试用,方便输出变量
git clone https://github.com/openresty/echo-nginx-module.git

4. 配置编译参数

./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_gunzip_module \
--with-http_auth_request_module \
--with-http_xslt_module \
--with-http_image_filter_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--with-pcre \
--with-pcre-jit \
--with-file-aio \
--with-threads \
--without-http_auth_basic_module \
--add-module=/usr/local/src/headers-more-nginx-module \
--add-module=/usr/local/src/ngx_cache_purge \
--add-module=/usr/local/src/echo-nginx-module \
--with-cc-opt='-O2 -fstack-protector-strong -Wno-error=deprecated-declarations' \
--with-ld-opt='-Wl,-z,relro'

5. 编译安装

# 使用所有 CPU 核心并行编译
make -j$(nproc)

# 安装
make install

6. 创建用户

useradd --system --no-create-home --shell /sbin/nologin nginx

6. 配置 Systemd 服务

tee /usr/lib/systemd/system/nginx.service > /dev/null <<'EOF'
[Unit]
Description=Nginx HTTP Server
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
LimitNOFILE=65535
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

修改版本

编译前通过修改源码, 修改对外展示的版本和 nginx 名称

#define NGINX_VERSION "1.99.99"
#define NGINX_VER "mynginx/" NGINX_VERSION
static u_char ngx_http_server_string[] = "Server: mynginx" CRLF;

配置

# worker 进程数量, 一般设为 CPU 核心数一致
worker_processes auto;

# worker 进程与 CPU 核心绑定, 每个核心用掩码表示
worker_cpu_affinity auto;

# worker 进程调度优先级, 范围是[-20,20), 越小越优先
worker_priority -20;

# worker 进程最多打开的文件数量
worker_rlimit_nofile 6666;
# 单个 worker 进程可打开的文件数量
worker_connections 6666;
# 启用/禁用 nginx 版本输出
server_tokens off;

# 字符集
charset utf-8;

平滑升级及回滚

1. 备份旧二进制

cp -a /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old

2. 编译新版本

cd /usr/local/src
NGINX_NEW=1.18.0
curl -O https://nginx.org/download/nginx-${NGINX_NEW}.tar.gz
tar -xzf nginx-${NGINX_NEW}.tar.gz
cd nginx-${NGINX_NEW}

# 查看旧版本编译参数
/usr/local/nginx/sbin/nginx -V

./configure # ... 复制旧版本编译参数

make -j$(nproc)

# 仅替换二进制
cp -f objs/nginx /usr/local/nginx/sbin/nginx

# 验证二进制新版本是否替换成功
/usr/local/nginx/sbin/nginx -V

3. 平滑升级

# 给旧 master PID 发送 USR2 信号 - 启动新 master,新旧并存
kill -USR2 /usr/local/nginx/logs/nginx.pid

# 看到两个 master 进程
ps auxf | grep nginx

# 旧 PID 被移到 nginx.pid.oldbin - 发送 WINCH 信号,让旧 master 优雅停止旧 worker
kill -WINCH /usr/local/nginx/logs/nginx.pid.oldbin

# 验证新版本
curl -I http://your_nginx_ip

# 确保无误后, 优雅停止旧 master
# kill -QUIT /usr/local/nginx/logs/nginx.pid.oldbin

4. 回滚

新版本刚启动,旧 master 仍存活
# 让旧的 master 拉起新 worker
kill -HUP /usr/local/nginx/logs/nginx.pid.oldbin

# 停止新 master 的 worker
kill -WINCH /usr/local/nginx/logs/nginx.pid

# 等旧 worker 正常接管请求后,退出新 master
kill -QUIT /usr/local/nginx/logs/nginx.pid

# 恢复旧版二进制
cp /usr/local/nginx/sbin/nginx.old /usr/local/nginx/sbin/nginx

5. 注意事项

用 systemd 管理 nginx,平滑升级后需同步更新服务状态
systemctl daemon-reload