nginx的模块分类
-
按结构分类
- 核心模块: HTTP模块, EVENT模块, MAIL模块
- 基础模块: HTTP Access模块, HTTP FastCGI模块, HTTP Proxy模块, Http Rewrite模块
- 第三方模块: HTTP Upstream Request Hash模块, Notice模块, HTTP Access Key模块
-
按功能分类
- Handlers(处理器模块): 直接处理请求, 并进行输出内容和修改headers信息等操作, 一般只能有一个
- Filters(过滤器模块): 此类模块主要对其他处理器模块输出的内容进行修改, 最后由nginx输出
- Proxies(代理模块): 此模块是nginx的http upstream之类的模块, 主要与后端一些服务(FastCGI)等进行交互,实现服务代理和负载均衡等功能
工作原理
- 当它接到一个HTTP请求时, nginx仅仅是通过查找配置文件将此次请求映射到一个location
- 在location中所配置的各个指令则会启动不同的模块去完成工作, 因此模块可以看做Nginx真正的劳动工作者
- 通常一个location中的指令会涉及一个handler模块和多个filter模块
- handler模块负责处理请求, 完成响应内容的生成, 而filter模块对响应内容进行处理
进程模型
- 在工作模式上, 分为单工作进程和多工作进程两种模式
- 单worker进程模式, 除主进程外, 还有一个worker进程, worker进程是单线程的
- 多worker进程模式下, 每个worker进程包含多个线程
- nginx默认为单工作进程模式, 启动之后, 会有一个master进程和多个worker进程
master 进程
- 主要用来管理worker进程
- 接收来自外界的信号
- 向各worker进程发送信号
- 监控worker进程的运行状态
- 当worker进程异常退出后, 自动启动新的worker进程
- master进程充当整个进程组与用户的交互接口, 同时对进程进行监护
- 它不需要处理网络事件, 不负责业务的执行
- 只负责管理worker进程来实现重启服务, 平滑升级, 更换日志文件, 配置文件实时生效等功能
worker 进程
- 基本的网络事件, 由worker进程处理
- 多个worker进程之间是对等且独立的, 同等竞争来自客户端的请求
Nginx+FastCGI
什么是FastCGI
- 它是一个可伸缩的, 高速的在HTTP server和动态脚本语言间通信的接口
大多数流行的HTTP server都支持FastCGI, 包括Apache, Nginx, lighttpd等 - FastCGI采用C/S结构, 可以将HTTP服务器和脚本解析服务器分开
同时在脚本解析服务器上启动一个或多个脚本解析守护进程
当HTTP服务器每次遇到动态程序时, 可以直接将其交付给FastCGI来执行, 结果返回给浏览器
这种方式让HTTP服务器专一的处理静态请求, 并将动态脚本服务器的结果返回给Client
运行原理
- 为了调用CGI程序, 还需要一个FastCGI的wrapper, 用来启动线程
- wrapper绑定在.sock文件或端口上
- 当nginx将CGI请求发送给socket的时候, wrapper接收到请求, 然后fork一个新的线程,
这个线程调用解释器或者外部的程序处理脚本, 并读取返回的数据
- 将数据通过FastCGI接口, 沿着sock传回nginx
- 最终返回的数据发送给客户端
spawn-fcgi和php-fpm
- 它们是两个支持php的FastCGI进程管理器
- HTTPServer完全解放出来, 更好的进行相应和处理并发
- spawn-fcgi
- spawn-fcgi是http服务器lighttpd的一部分, 目前已经独立出来, 一般与lighttpd配合使用
- 在高并发访问的时候, 会出现内存泄露, 甚至自动重启FastCGI的问题
- 容易崩溃, 需要crontab对状态做监控
- php-fpm
- 作为php插件开发, 安装的时候和php源码一起编译, 性能优秀一些
- 高并发方面, 至少不会自动重启FastCGI(:-D)
- cpu和内存控制方面都比spawn-fcgi好, 不易崩溃
Nginx+php-fpm
- 在php5.3.3后, 已经集成了php-fpm, 不在是第三方的包
- 编译的时候, 增加 -enable-fpm 参数即可开启php-fpm
- 一般web都做同一入口, 把php请求都发送到同一个文件上, 然后再文件里通过"REQIEST_URI"实现路由
配置文件
- 常见的次序, 从外到内依次是 [http] -> [server] -> [location]
- 缺省的继承关系是从外到内, 也就是内层块会自动获取外层块的值作为默认值
""" 示例配置文件 """
server {
listen 80;
server_name exp.com;
root /xx;
"""
index 不应该定义在location中, 会出现重复
直接定义在server中, 通过继承生效
"""
index index.html index.htm index.php;
location / {
"""
1. 尽量适用try_files指令而不是if
2. 下边这个逻辑
1. 当用户请求 http://www.exp.com/a 时,这里的 $uri 就是 /a
2. 如果存在就返回
3. 目录中没有叫 a 的文件。然后就看 $uri/,增加了一个 /,也就是看有没有名为 a 的目录
4. 再没有找到的话, 跳转到http://www.exp.com/index.php
"""
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri = 400;
"""
直接引入fastcgi.conf文件, 它比fastcgi_params多定义了一行
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
"""
include fastcgi.conf;
"""
也可以
fastcgi_pass unix:/xx/xx/xx/xx.sock
"""
fastcgi_pass 127.0.0.1:9000; # 也可以 fastcgi_pass unix:/xx/xx/xx/xx.sock
}
}
nginx的多进程IO模型
优点
- 独立进程不需要加锁, 减少开销
- 排错方便, 便于开发
- 不会相互影响, 降低影响
nginx的异步非阻塞
- 请求过来 --> 建立连接 --> 接收数据 --> 读写操作 --> 返回数据
- 读写操作这一步, 当io等待的时候, cpu在不同进程间切换, 检查哪个进程完成了io, 继续下一步操作
- 注意cpu切换也是有开销的
nginx的事件模型
事件模型 | 描述 |
---|---|
select | 标准方法, 是编译时默认选择的方法, 可以使用 --with-select_module 和 --without-select_module 来启用或禁用它 |
poll | 标准方法, 可以使用配置参数 --with-poll_module 和 --without-poll_module 来启用或禁用这个模块 |
kqueue | 高效方法, 在FreeBSD 4.1+, OpenBSD 2.9+, MacOS X和使用双处理器的MacOS X系统使用可能造成内核崩溃 |
epoll | 对于linux来说, 只有它是高效方法 |
epoll的优点
推荐设置worker的个数为cpu的核数, 更多的worker数, 只会导致进程来竞争cpu资源了, 从而带来不必要的上下文切换
nginx为了更好的利用多核特性, 提供了cpu亲缘性的绑定选项, 我们可以将某一个进程绑定在某一个核上
这样就不会因为进程的切换带来cache的失效, 像这种小的优化在nginx中非常常见
nginx在做4个字节的字符串比较时, 会将4个字符转换成一个int型, 再作比较, 以减少cpu的指令数等
nginx 的优化
减小nginx编译后文件大小
"""
编译nginx默认使用debug模式进行, 信息量会很大
可以修改相关源码, 取消debug模式
"""
# 在源码目录下找到 auto/cc/gcc 文件, 删除或注释下边两行, 可以取消debug模式
# debug
CFLAGS="$CFLAGS -g"
为特定的CPU指定CPU类型编译
"""
在编译Nginx时,默认的GCC编译参数是“-O”,要优化GCC编译,可以使用以下两个参数
1. --with-cc-opt='-O3'
2. --with-cpu-opt=CPU #为特定的 CPU 编译, 有效的值包括:
pentium, pentiumpro, pentium3, # pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64
"""
# 要确定cpu类型, 可以通过下边这个命令
cat /proc/cpuinfo | grep "model name"
利用 TCMalloc 优化nginx
TCMalloc库在内存分配效率和速度上要高很多,这在很大程度上提高了服务器在高并发情况下的性能,从而降低了系统的负载
针对nginx的内核参数优化
# 将下边的参数加入 /etc/sysctl.conf 中
net.ipv4.tcp_max_tw_buckets = 6000 # timewait 最大数量
net.ipv4.ip_local_port_range = 1024 65000 # 开放端口
net.ipv4.tcp_tw_recycle = 1 # 选项用于设置启用timewait快速回收
net.ipv4.tcp_tw_reuse = 1 # 选项用于设置开启重用, 允许将TIME-WAIT sockets重新用于新的TCP连接
net.ipv4.tcp_syncookies = 1 # 当出现SYN等待队列溢出时,启用cookies进行处理
net.core.somaxconn = 262144
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 1 # 内核放弃连接之前发送SYN+ACK包的数量
net.ipv4.tcp_syn_retries = 1 # 在内核放弃建立连接之前发送SYN包的数量
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30 # 表示当keepalive启用时, TCP发送keepalive消息的频度, 单位小时
# 生效
/sbin/sysctl -p
针对nginx的php-fpm优化
-
增加FastCGI的进程数
4G内存的服务器上, 将FastCGI的子进程数调到200, 就可以获取最佳效果 -
增加 PHP-FPM打开文件描述符的限制
打开 php-fpm.conf
修改 “<valuename=“rlimit_files”>1024” 将1024改为4096或更大
这个值和系统参数文件打开数有联系, 修改文件打开数
在 /etc/security/limits.conf 加入
hard nofile 65535
soft nofile 65535 -
适当增加max_requests
标签max_requests指明了每个children最多处理多少个请求后便会被关闭, 默认的设置是500
500
nginx.conf优化
# 假设是8核cpu
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000
# 使用epoll模式
use epoll
# 每个工作进程的最大连接数
work_connects 65535
# 请求头大小, 请求头缓冲大小
client_header_buffer_size 16k
large_client_header_buffers 4 32k
# 开启gzip
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-JavaScript text/css
application/xml;
gzip_vary on;
# 缓存静态文件:
location ~* ^.+\.(swf|gif|png|jpg|js|css)$ {
root /usr/local/ku6/ktv/show.ku6.com/;
expires 1m;