第448集Nginx应用指南
Nginx应用指南
1. Nginx基本简述
1.1 什么是Nginx
Nginx(发音为”engine x”)是一个开源且高性能、可靠的HTTP中间件、代理服务。由俄罗斯程序员Igor Sysoev开发,2004年首次公开发布。
Nginx核心特性:
- 开源:直接获取源代码,可自由使用和修改
- 高性能:支持海量并发,单机可处理数万并发连接
- 高可靠:稳定性好,适合生产环境
- 轻量级:资源占用少,功能模块化
1.2 常见的HTTP服务
| HTTP服务 | 开发组织 | 特点 |
|---|---|---|
| HTTPD | Apache基金会 | 功能丰富,模块化,传统Web服务器 |
| IIS | 微软 | Windows平台,集成度高 |
| GWS | Google内部使用,不对外 | |
| OpenResty | OpenResty社区 | 基于Nginx + Lua,支持动态编程 |
| Tengine | 淘宝 | 基于Nginx开发,针对中国互联网优化 |
1.3 Nginx应用场景
1.3.1 静态资源处理
场景:
- 处理静态文件(HTML、CSS、JS、图片等)
- 替代Apache处理静态资源
- 提供高性能的静态文件服务
优势:
- 性能高,资源占用少
- 支持sendfile零拷贝
- 支持gzip压缩
1.3.2 反向代理
场景:
- 作为反向代理服务器
- 隐藏后端服务器信息
- 提供负载均衡功能
优势:
- 高性能反向代理
- 支持多种负载均衡算法
- 支持健康检查
1.3.3 负载均衡
场景:
- 分发请求到多个后端服务器
- 提高系统可用性和性能
- 实现水平扩展
负载均衡算法:
- 轮询(round-robin)
- 加权轮询(weighted round-robin)
- IP哈希(ip_hash)
- 最少连接(least_conn)
1.3.4 资源缓存
场景:
- 缓存静态资源
- 缓存后端响应
- 减少后端服务器压力
优势:
- proxy_cache缓存功能
- 支持缓存过期策略
- 支持缓存清理
1.3.5 安全防护
场景:
- 限制访问频率
- IP白名单/黑名单
- SSL/TLS加密
- 防止DDoS攻击
1.3.6 访问限制
场景:
- 限制连接数
- 限制请求速率
- 限制并发数
1.3.7 访问认证
场景:
- HTTP基本认证
- 基于IP的访问控制
- 自定义认证模块
1.4 Nginx优秀特性
1.4.1 基于IO多路复用
IO多路复用:
IO复用解决的是并发性的问题,Socket作为复用。多个描述符的I/O操作都能在一个线程内并发交替地顺序完成,这就叫I/O多路复用,这里的”复用”指的是复用同一个线程。
IO多路复用的实现方式:
- select:传统方式,有连接数限制
- poll:改进的select,无连接数限制
- epoll:Linux高效实现,事件驱动
IO复用对比:
传统IO(串行,产生阻塞):
1 | 进程1 → 等待IO → 处理 |
- 每个进程阻塞等待IO
- 资源浪费,效率低
多线程IO(消耗大):
1 | 线程1 → 等待IO → 处理 |
- 需要大量线程
- 上下文切换开销大
IO多路复用(主动上报):
1 | 单个线程 → select/epoll → 处理多个IO |
- 单线程处理多个IO
- 事件驱动,效率高
1.4.2 select模型
select工作原理:
- 轮询所有文件描述符
- 检查哪些fd就绪
- 返回就绪的fd列表
select缺点:
- 连接数限制:能够监视文件描述符的数量存在最大限制(通常1024)
- 效率低下:线性遍历扫描效率低下,O(n)复杂度
1.4.3 epoll模型
epoll工作原理:
- 每当FD就绪,采用系统的回调函数之间将fd放入就绪队列
- 只返回就绪的fd,效率更高
- 最大连接无限制
epoll优势:
- O(1)时间复杂度
- 支持数万并发连接
- 性能稳定,不随连接数增加而下降
1.4.4 轻量级
轻量级特性:
- 功能模块少:核心功能精简,按需加载模块
- 代码模块化:模块化设计,易于扩展和维护
优势:
- 资源占用少
- 启动速度快
- 配置简单
1.4.5 CPU亲和(Affinity)
CPU亲和性:
将CPU核心和Nginx工作进程绑定方式,把每个worker进程固定在一个CPU上执行,减少切换CPU的cache miss,获得更好的性能。
配置示例:
1 | worker_processes 4; |
优势:
- 减少CPU缓存失效
- 提高CPU利用率
- 提升性能
1.4.6 sendfile零拷贝
传统文件传输:
传统文件传输在实现上比较复杂,需要经过四次复制操作:
- 调用read函数,文件数据被复制到内核缓冲区
- read函数返回,文件数据从内核缓冲区复制到用户缓冲区
- write函数调用,将文件数据从用户缓冲区复制到内核与socket相关的缓冲区
- 数据从socket缓冲区复制到相关协议引擎
传统文件传输流程:
1 | 硬盘 → 内核buf → 用户buf → socket缓冲区(内核) → 协议引擎 |
问题:
- 需要经过多次上下文的切换
- 数据拷贝次数多
- 效率不高
sendfile零拷贝:
sendfile文件传输是在内核中操作完成的,函数直接在两个文件描述符之间传递数据,从而避免了内核缓冲区数据和用户缓冲区数据之间的拷贝,操作效率很高,被称之为零拷贝。
sendfile流程:
- 系统调用sendfile函数通过DMA把硬盘数据拷贝到kernel buffer
- 数据被kernel直接拷贝到另外一个与socket相关的kernel buffer
- DMA把数据从kernel buffer直接拷贝给协议栈
sendfile优势:
- 没有用户空间和内核空间之间的切换
- 在内核中直接完成了从一个buffer到另一个buffer的拷贝
- 减少数据拷贝次数
- 提高性能
配置示例:
1 | http { |
2. Nginx快速安装
2.1 Nginx版本说明
版本类型:
| 版本类型 | 说明 | 推荐使用 |
|---|---|---|
| Mainline version | 开发版 | 不推荐生产环境 |
| Stable version | 稳定版 | 推荐生产环境 |
| Legacy version | 历史版本 | 不推荐 |
版本选择建议:
- 生产环境:使用Stable version
- 测试环境:可以使用Mainline version
- 不建议使用Legacy version
2.2 基础环境准备
2.2.1 系统检查
1 | # 确认系统网络 |
2.2.2 关闭防火墙
1 | # 关闭firewalld(CentOS 7+) |
2.2.3 关闭SELinux
1 | # 临时关闭SELinux |
2.2.4 初始化目录
1 | # 创建基本目录 |
2.2.5 安装基础依赖
1 | # 安装基本工具和开发包 |
依赖说明:
gcc/gcc-c++:C/C++编译器autoconf/automake:自动配置工具pcre/pcre-devel:正则表达式库make:编译工具wget:下载工具httpd-tools:Apache工具(用于htpasswd等)vim:文本编辑器tree:目录树显示工具
2.3 使用YUM安装Nginx
2.3.1 配置Nginx官方YUM源
1 | # 创建Nginx YUM源配置 |
配置内容:
1 | [nginx] |
CentOS 6配置:
1 | [nginx] |
2.3.2 安装Nginx
1 | # 清理YUM缓存 |
输出示例:
1 | nginx version: nginx/1.12.2 |
2.3.3 启动Nginx
1 | # 启动Nginx |
2.4 Nginx安装目录
2.4.1 查看Nginx文件
1 | # 查看Nginx安装的所有文件 |
2.4.2 Nginx目录结构
| 路径 | 说明 |
|---|---|
/etc/nginx/ |
配置文件目录 |
/etc/nginx/nginx.conf |
主配置文件 |
/etc/nginx/conf.d/ |
额外配置文件目录 |
/usr/sbin/nginx |
Nginx可执行文件 |
/var/log/nginx/ |
日志文件目录 |
/var/cache/nginx/ |
缓存文件目录 |
/usr/share/nginx/html/ |
默认网站根目录 |
/etc/nginx/mime.types |
MIME类型文件 |
3. Nginx编译参数
3.1 查看Nginx编译参数
1 | # 查看Nginx编译参数和版本 |
输出示例:
1 | nginx version: nginx/1.12.2 |
3.2 Nginx编译参数说明
3.2.1 路径参数
| 参数 | 说明 | 示例 |
|---|---|---|
--prefix |
Nginx安装路径 | /etc/nginx |
--sbin-path |
Nginx可执行文件路径 | /usr/sbin/nginx |
--conf-path |
配置文件路径 | /etc/nginx/nginx.conf |
--error-log-path |
错误日志路径 | /var/log/nginx/error.log |
--access-log-path |
访问日志路径 | /var/log/nginx/access.log |
--pid-path |
PID文件路径 | /var/run/nginx.pid |
--lock-path |
锁文件路径 | /var/run/nginx.lock |
--http-log-path |
HTTP访问日志路径 | /var/log/nginx/access.log |
--http-client-body-temp-path |
客户端请求体临时文件路径 | /var/cache/nginx/client_temp |
--http-proxy-temp-path |
代理临时文件路径 | /var/cache/nginx/proxy_temp |
--http-fastcgi-temp-path |
FastCGI临时文件路径 | /var/cache/nginx/fastcgi_temp |
--http-uwsgi-temp-path |
uWSGI临时文件路径 | /var/cache/nginx/uwsgi_temp |
--http-scgi-temp-path |
SCGI临时文件路径 | /var/cache/nginx/scgi_temp |
3.2.2 用户和组参数
| 参数 | 说明 | 示例 |
|---|---|---|
--user |
运行Nginx的用户 | nginx |
--group |
运行Nginx的组 | nginx |
3.2.3 模块参数
HTTP模块:
| 参数 | 说明 |
|---|---|
--with-http_ssl_module |
启用HTTPS支持 |
--with-http_realip_module |
启用真实IP模块 |
--with-http_addition_module |
启用响应追加模块 |
--with-http_sub_module |
启用响应替换模块 |
--with-http_dav_module |
启用WebDAV模块 |
--with-http_flv_module |
启用FLV视频流模块 |
--with-http_mp4_module |
启用MP4视频流模块 |
--with-http_gunzip_module |
启用gunzip解压模块 |
--with-http_gzip_static_module |
启用gzip静态压缩模块 |
--with-http_random_index_module |
启用随机首页模块 |
--with-http_secure_link_module |
启用安全链接模块 |
--with-http_degradation_module |
启用降级模块 |
--with-http_slice_module |
启用分片模块 |
--with-http_stub_status_module |
启用状态统计模块 |
--with-http_auth_request_module |
启用认证请求模块 |
--with-http_xslt_module |
启用XSLT转换模块 |
--with-http_image_filter_module |
启用图片过滤模块 |
--with-http_geoip_module |
启用GeoIP模块 |
--with-http_perl_module |
启用Perl模块 |
--with-http_v2_module |
启用HTTP/2模块 |
邮件模块:
| 参数 | 说明 |
|---|---|
--with-mail |
启用邮件代理模块 |
--with-mail_ssl_module |
启用邮件SSL模块 |
流媒体模块:
| 参数 | 说明 |
|---|---|
--with-stream |
启用流媒体代理模块 |
--with-stream_ssl_module |
启用流媒体SSL模块 |
--with-stream_realip_module |
启用流媒体真实IP模块 |
--with-stream_geoip_module |
启用流媒体GeoIP模块 |
--with-stream_ssl_preread_module |
启用流媒体SSL预读模块 |
第三方模块:
| 参数 | 说明 |
|---|---|
--add-module=path |
添加第三方模块 |
--add-dynamic-module=path |
添加动态模块 |
3.2.4 其他参数
| 参数 | 说明 |
|---|---|
--with-pcre |
PCRE库路径 |
--with-pcre-jit |
启用PCRE JIT编译 |
--with-zlib |
zlib库路径 |
--with-openssl |
OpenSSL库路径 |
--with-openssl-opt |
OpenSSL编译选项 |
--with-debug |
启用调试日志 |
--with-cc-opt |
编译器选项 |
--with-ld-opt |
链接器选项 |
3.3 常用编译配置示例
3.3.1 基础编译配置
1 | ./configure \ |
3.3.2 完整编译配置
1 | ./configure \ |
4. Nginx常用模块
4.1 Nginx模块分类
4.1.1 官方模块
核心模块:
ngx_core_module:核心模块ngx_http_module:HTTP模块ngx_mail_module:邮件模块ngx_stream_module:流媒体模块
HTTP模块:
ngx_http_core_module:HTTP核心模块ngx_http_access_module:访问控制模块ngx_http_auth_basic_module:HTTP基本认证模块ngx_http_proxy_module:反向代理模块ngx_http_upstream_module:负载均衡模块ngx_http_fastcgi_module:FastCGI模块ngx_http_rewrite_module:URL重写模块ngx_http_ssl_module:SSL模块
4.1.2 第三方模块
常用第三方模块:
nginx-accesskey:访问密钥模块ngx_http_consistent_hash:一致性哈希模块nginx-static-etags:静态ETag模块nginx-http-footer-filter:页脚过滤模块form-input-nginx-module:表单输入模块ngx_http_accounting_module:统计模块ngx_log_if:条件日志模块nginx-limit-upstream:限制上游模块limit_upload_rate:上传速率限制模块ngx_devel_kit:开发工具包nginx-module-vts:虚拟主机流量统计模块nginx_tcp_proxy_module:TCP代理模块nginx-http-concat:资源合并模块
5. Nginx内置变量
5.1 HTTP核心模块内置变量
5.1.1 请求变量
| 变量 | 说明 | 示例 |
|---|---|---|
$uri |
当前请求的URI,不带参数 | /index.html |
$request_uri |
请求的URI,带完整参数 | /index.html?id=1 |
$args |
请求参数 | id=1&name=test |
$query_string |
同$args | id=1&name=test |
$request_method |
请求方法 | GET、POST |
$request_filename |
请求的文件路径 | /usr/share/nginx/html/index.html |
$document_root |
当前请求映射到的root配置 | /usr/share/nginx/html |
$request_body |
请求体内容 | POST数据 |
5.1.2 主机变量
| 变量 | 说明 | 示例 |
|---|---|---|
$host |
HTTP请求报文中host首部,如果没有则以处理此请求的虚拟主机的主机名代替 | example.com |
$hostname |
Nginx服务运行在主机的主机名 | nginx-server |
$server_name |
服务器名称 | example.com |
$server_addr |
服务器地址 | 192.168.1.100 |
$server_port |
服务器端口 | 80、443 |
$server_protocol |
服务器向客户端发送响应时的协议 | HTTP/1.1、HTTP/1.0 |
$scheme |
请求使用的scheme | http、https |
5.1.3 客户端变量
| 变量 | 说明 | 示例 |
|---|---|---|
$remote_addr |
客户端IP地址 | 192.168.1.200 |
$remote_port |
客户端端口 | 54321 |
$remote_user |
使用用户认证时客户端用户输入的用户名 | admin |
$http_user_agent |
客户端User-Agent | Mozilla/5.0... |
$http_referer |
客户端Referer | http://example.com |
5.1.4 响应变量
| 变量 | 说明 | 示例 |
|---|---|---|
$status |
HTTP响应状态码 | 200、404、500 |
$body_bytes_sent |
发送给客户端的字节数 | 1234 |
$bytes_sent |
发送给客户端的字节数(包括响应头) | 1500 |
$request_length |
请求的长度(包括请求行、请求头、请求体) | 500 |
5.1.5 时间变量
| 变量 | 说明 | 示例 |
|---|---|---|
$time_iso8601 |
ISO8601格式的本地时间 | 2019-03-26T10:15:30+08:00 |
$time_local |
通用日志格式的本地时间 | 26/Mar/2019:10:15:30 +0800 |
$msec |
当前时间(秒.毫秒) | 1553571330.123 |
5.1.6 HTTP头变量
| 变量 | 说明 | 示例 |
|---|---|---|
$http_HEADER |
匹配请求报文中指定的HEADER | $http_host、$http_user_agent |
$sent_http_HEADER |
响应报文中指定的HEADER | $sent_http_content_type |
5.1.7 上游变量
| 变量 | 说明 | 示例 |
|---|---|---|
$upstream_addr |
上游服务器地址 | 192.168.1.100:8080 |
$upstream_status |
上游服务器响应状态码 | 200、502 |
$upstream_response_time |
上游服务器响应时间 | 0.123 |
$upstream_cache_status |
缓存状态 | HIT、MISS、EXPIRED |
5.2 变量使用示例
5.2.1 日志格式中使用变量
1 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' |
5.2.2 配置中使用变量
1 | location / { |
6. Nginx编译安装
6.1 OpenResty编译安装
6.1.1 OpenResty简介
OpenResty:
- 基于Nginx和LuaJIT的Web平台
- 集成了大量精良的Lua库
- 支持动态编程,功能强大
OpenResty优势:
- 高性能:基于Nginx
- 动态编程:支持Lua脚本
- 功能丰富:集成了大量模块
6.1.2 基础环境准备
1 | # 创建目录 |
6.1.3 下载依赖包
1 | cd /soft/package/src |
6.1.4 下载第三方模块
1 | cd /soft/package/src/ngx_3rd |
6.1.5 编译OpenResty
1 | cd /soft/package/src/openresty-1.11.2.2 |
6.1.6 验证安装
1 | # 查看版本 |
7. Nginx配置最佳实践
7.1 基础配置优化
7.1.1 worker进程配置
1 | # 根据CPU核心数设置 |
7.1.2 事件模型配置
1 | events { |
7.1.3 HTTP基础配置
1 | http { |
7.2 安全配置
7.2.1 隐藏版本信息
1 | http { |
7.2.2 限制请求大小
1 | http { |
7.2.3 访问控制
1 | location /admin { |
8. 故障排查
8.1 常见问题
8.1.1 编译错误
问题:编译时缺少依赖
解决:
1 | # 安装所有依赖 |
8.1.2 启动失败
问题:端口被占用
排查:
1 | # 检查端口占用 |
8.1.3 配置错误
问题:配置文件语法错误
排查:
1 | # 测试配置文件 |
9. 总结
9.1 核心要点
- Nginx特性:高性能、轻量级、基于epoll
- 安装方式:YUM安装(简单)和源码编译(灵活)
- 编译参数:根据需求选择合适的模块
- 内置变量:丰富的变量支持灵活的配置
- OpenResty:基于Nginx + Lua的强大平台
9.2 架构师建议
安装选择:
- 快速部署:使用YUM安装
- 定制需求:使用源码编译
模块选择:
- 根据业务需求选择模块
- 避免加载不必要的模块
性能优化:
- 使用epoll事件模型
- 启用sendfile零拷贝
- 合理设置worker进程数
9.3 最佳实践
- 标准化:统一安装和配置标准
- 模块化:按需加载模块
- 监控化:监控Nginx状态和性能
- 文档化:维护配置文档
相关文章:
- [第447集 Apache select和Nginx epoll模型区别](./第447集Apache select和Nginx epoll模型区别.md)
- [第446集 Nginx Cache缓存网站数据实践](./第446集Nginx Cache缓存网站数据实践.md)
- 第445集 Tomcat常用设置及安全管理规范
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 1024bibi.com!
评论


