2002年,俄罗斯程序员伊戈尔·赛索耶夫为了解决Rambler.ru网站面临的C10K问题(即单机同时处理1万个连接的问题),开始着手开发一款全新的Web服务器软件。经过两年打磨,Nginx 0.1.0版本于2004年正式发布。这款采用事件驱动架构的服务器软件,很快以其卓越的性能表现震惊业界。
2019年,F5 Networks以6.7亿美元收购Nginx公司,这笔交易让业界重新认识了开源软件的价值——Nginx核心模块代码仅198430行(含空格和注释),相当于每行代码价值约2.2万人民币。如今,从淘宝、京东到新浪、网易,国内一线互联网公司都在使用或基于Nginx进行二次开发。
Nginx之所以备受青睐,主要得益于三大核心优势:
在CentOS/RHEL系统上,我们需要先安装编译工具链和必要的开发库:
bash复制# 安装基础编译工具
dnf install gcc make -y
# 安装Nginx依赖库
dnf install openssl-devel pcre2-devel zlib-devel -y
特别提醒:
下载最新稳定版源码并解压:
bash复制wget https://nginx.org/download/nginx-1.28.1.tar.gz
tar zxf nginx-1.28.1.tar.gz
cd nginx-1.28.1/
生产环境推荐编译参数:
bash复制./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
关键模块说明:
--with-http_stub_status_module:启用状态监控页面--with-stream:支持TCP/UDP代理--with-http_gzip_static_module:预压缩静态文件支持编译安装完成后,需要创建专用系统账户:
bash复制useradd -s /sbin/nologin -M nginx
配置环境变量:
bash复制echo 'export PATH=$PATH:/usr/local/nginx/sbin' >> ~/.bash_profile
source ~/.bash_profile
创建systemd服务单元文件:
bash复制cat > /lib/systemd/system/nginx.service <<'EOF'
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network-online.target
[Service]
Type=forking
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx
生产环境升级步骤:
bash复制sed -i 's/#define NGINX_VERSION "1.28.1"/#define NGINX_VERSION ""/' src/core/nginx.h
sed -i 's/#define NGINX_VER "nginx\/" NGINX_VERSION/#define NGINX_VER "Custom\/" NGINX_VERSION/' src/core/nginx.h
bash复制./configure [原参数] && make
bash复制cp -f objs/nginx /usr/local/nginx/sbin/
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
bash复制kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin`
回滚操作:
bash复制mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.new
mv /usr/local/nginx/sbin/nginx.old /usr/local/nginx/sbin/nginx
kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
nginx.conf关键参数优化:
nginx复制worker_processes auto; # 自动匹配CPU核心数
worker_cpu_affinity auto; # CPU亲和处理
worker_rlimit_nofile 65535; # 文件描述符限制
events {
worker_connections 10240; # 每个worker最大连接数
use epoll; # Linux系统启用epoll模型
multi_accept on; # 一次性接受所有新连接
}
http {
sendfile on; # 启用零拷贝传输
tcp_nopush on; # 优化数据包发送
keepalive_timeout 65; # 长连接超时
keepalive_requests 1000; # 单个连接最大请求数
}
基于域名的虚拟主机示例:
nginx复制server {
listen 80;
server_name example.com;
location / {
root /data/www/example;
index index.html;
# 目录浏览控制
autoindex off;
# 访问控制
allow 192.168.1.0/24;
deny all;
}
location /static/ {
alias /data/shared/static/;
expires 30d; # 静态资源缓存
}
}
上游服务器组配置:
nginx复制upstream backend {
least_conn; # 最少连接算法
server 192.168.1.10:8080 weight=5;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
server backup.example.com:8080 backup;
}
server {
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_next_upstream error timeout invalid_header;
}
}
nginx复制server_tokens off; # 隐藏Nginx版本
proxy_hide_header X-Powered-By; # 隐藏后端框架信息
nginx复制server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 其他SSL优化参数...
}
nginx复制limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
location / {
limit_req zone=one burst=20;
# 其他配置...
}
以echo模块为例的扩展步骤:
bash复制wget https://github.com/openresty/echo-nginx-module/archive/v0.64.tar.gz
tar zxf v0.64.tar.gz
bash复制./configure [原参数] --add-module=../echo-nginx-module-0.64
make && make install
nginx复制location /test {
echo "Client IP: $remote_addr";
echo "User-Agent: $http_user_agent";
}
结构化日志配置:
nginx复制log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":$request_time'
'}';
access_log /var/log/nginx/access.log json_combined;
使用GoAccess进行实时分析:
bash复制goaccess /var/log/nginx/access.log --log-format=JSON --real-time-html --port=7890
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 502 Bad Gateway | 后端服务不可用 | 检查后端服务状态和连接超时设置 |
| 403 Forbidden | 文件权限问题 | 确保nginx用户有读取权限 |
| 地址重写循环 | rewrite规则错误 | 检查rewrite规则是否有终止标志(last/break) |
| SSL握手失败 | 证书链不完整 | 使用openssl s_client -connect测试证书链 |
bash复制watch -n 1 "curl -s http://localhost/nginx_status"
bash复制top -p `pgrep -d',' nginx`
nginx复制location / {
# 记录超过2秒的请求
log_subrequest on;
access_log /var/log/nginx/slow.log timing;
}
经过多年运维经验,我总结出以下关键建议:
目录结构规划:
配置管理原则:
监控指标要点:
自动化维护脚本示例(每日日志切割):
bash复制#!/bin/bash
LOG_DIR=/var/log/nginx
DATE=`date -d "yesterday" +%Y%m%d`
mv ${LOG_DIR}/access.log ${LOG_DIR}/access_${DATE}.log
kill -USR1 `cat /run/nginx.pid`
find ${LOG_DIR} -name "access_*.log" -mtime +30 -exec rm -f {} \;