使用场景
特性
IO多路复用
使用epoll模型,高并发处理客户端的请求
CPU亲和
把working进程与CPU绑定,避免working进程不必要的在CPU之间切换
sendfile
从读文件到返回socket,都是从内核态完成,不需要经过用户态,减少拷贝和上下文的切换
模块说明
功能模块 | 模块说明 |
---|---|
ngx_http_core_module | 包含一些核心的http参数配置,对应Nginx的配置为http区块部分 |
ngx_http_access_module | 访问控制模块,用来控制网站用户对Nginx的访问 |
ngx_http_gzip_module | 压缩模块,对返回的数据压缩,属于性能优化模块 |
ngx_http_proxy_module | proxy代理模块 |
ngx_http_upstram_module | 负载均衡模块,可以实现网站的负载均衡功能及节点的健康检查 |
ngx_http_rewrite_module | URL地址重写模块 |
ngx_http_limit_conn_module | 限制用户并发连接数及请求数模块 |
ngx_http_limit_req_module | 根据定义的key限制Nginx请求过程的速率 |
ngx_http_log_module | 访问日志模块,以指定的格式记录Nginx客户访问日志等信息 |
ngx_http_auth_basic_module | Web认证模块,设置web用户通过账号密码访问Nginx |
ngx_http_ssl_module | ssl模块,用于加密的http连接,如https |
ngx_http_stub_status_module | 记录Nginx基本访问状态信息等的模块 |
常用变量
变量 | 说明 |
---|---|
$args | 请求中的参数,如[www.123.com/1.php?a=1&b=2的args就是a=1&b=2) |
$content_length | HTTP请求信息里的"Content-Length" |
$conten_type | HTTP请求信息里的"Content-Type" |
$document_root | nginx虚拟主机配置文件中的root参数对应的值 |
$document_uri | 当前请求中不包含指令的URI,如[www.123.com/1.php?a=1&b=2的document_uri就是1.php),不包含后面的参数 |
$host | 主机头,也就是域名 |
$http_user_agent | 客户端的详细信息,也就是浏览器的标识,用curl -A可以指定 |
$http_cookie | 客户端的cookie信息 |
$limit_rate | 如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0 |
$remote_addr | 客户端的公网ip |
$remote_port | 客户端的port |
$remote_user | 如果nginx有配置认证,该变量代表客户端认证的用户名 |
$request_body_file | 做反向代理时发给后端服务器的本地资源的名称 |
$request_method | 请求资源的方式,GET/PUT/DELETE等 |
$request_filename | 当前请求的资源文件的路径名称,相当于是document_uri的组合 |
$request_uri | 请求的链接,包括args |
$scheme | 请求的协议,如ftp,http,https |
$server_protocol | 客户端请求资源使用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等 |
$server_addr | 服务器IP地址 |
$server_name | 服务器的主机名 |
$server_port | 服务器的端口号 |
$uri | 和$document_uri相同 |
$http_referer | 客户端请求时的referer,通俗讲就是该请求是通过哪个链接跳过来的,用curl -e可以指定 |
配置文件
路径
默认/etc/nginx/nginx.conf
配置说明
- Main位于nginx.conf配置文件的最高层
- Main层下可以有Event/HTTP
- HTTP层下面可以有多个Server层,用于对不同的网站做配置
- Server层可以有多个Location,用于对不同的路径进行不同模块的配置
########### 每个指令必须有分号结束。#################
#user administrator administrators; #配置用户或者组,默认为nobody nobody。
#worker_processes 2; #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid; #指定nginx进程运行文件存放地址
error_log log/error.log debug; #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
#use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
worker_connections 1024; #最大连接数,默认为512
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
access_log log/access.log myFormat; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。
upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
error_page 404 https://www.baidu.com; #错误页
server {
keepalive_requests 120; #单连接请求上限次数。
listen 4545; #监听端口
server_name 127.0.0.1; #监听地址
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index vv.txt; #设置默认页
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
}
}
热更新配置
#update conf files
nginx -s reload
#会导致除了master进程之外的进程,全部重起
# kill -SIGHUP 同样效果
# 子进程退出,会发信号给master,master就会再起一个worker
热部署
cp /nginx /sbin/nginx
kill -USR2 #开启新进程
kill -WINCH #退出旧的worker进程
开启新的log文件
nginx -s reopen #旧的log文件会被改名,生成新的log文件
状态监控
--with-http_stub_status_module记录Nginx客户端基本访问状态信息,stub_status可以配置在server/loaction中
location /mystatus{
stub_status on;
}
下载站点
可以配置在http/server/location中
location /down {
root /opt/
autoindex on; #开启目录访问
autoindex_localtime on; #显示文件的时间
autoindex_exact_size off; #文件大小,on的单位是bytes,off单位为kb/mb/gb
charset utf-8; 字符集,解决乱码
}
访问限制
limit_conn_module:连接频率限制
limit_req_module:请求频率限制
可以配置在http/server/location
#rate限速速率,一秒一个request,超出则丢弃
#limit_req_zone只能定义在http
limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s;
limit_req zone=req_zone
#或者可以允许多3个请求延后处理
limit_req zone=req_zone burst=3 nodelay;
#可以使用ab工具来压测
信号
- CHLD:子进程退出,通知master,此时master会再启动一个worker
- TERM:worker/master接收,stop
- QUIT:worker/master接收,表示幽雅的退出,quit
- HUP:worker/master接收,reload
- USR1:worker/master接收,reopen
- USR2:master接收,开启新进程
- WINCH:master接收,退出旧进程
reload流程
- 向master发送HUP
- master检验配置语法正确性
- master打开新的监听端口
- master用新配置启动新worker
- master向老worker发送quit信号
- 老worker进程关闭监听句柄,处理完当前连接,并结束自己(老连接出问题,worker进程发现有连接未处理,会导致worker进程一直不退出,master进程会根据配置,启用一个定时器,如果worker在超时之后,依然存活,则强制杀worker)
热升级流程
- 把旧的Nginx文件替换程新的Nginx文件,注意备份
- 向master进程发送USR2信号
- master进程修改pid文件名,加后缀.oldbin
- master进程用新Nginx文件启动新master进程
- 向老master进程发送WINCH信号,关闭老worker
- 回滚:向老master发送HUP,向新master发送QUIT
优雅关闭worker
- 设置定时器,worker_shutdown_timeout
- 关闭监听句柄
- 关闭空闲连接
- 循环等待全部连接关闭(对于TCP/UDP/websocket,无法做到判定连接是否结束,因为它们没有明确的界定,只能对http请求,才可以判定连接是否结束)
- 退出进程
用户态切换任务
- 大量减少进程间的切换,每次切换需要5ms,如果有成万以上的进程在处理,cpu大量的时间会花费在进程切换上,导致大量的浪费cpu资源,在进程内自己切换任务,可以大大的节约cpu的时间
- 把进程的优先级设置为-19以下,可以让操作系统多分配时间片给进程,以减少进程的切换
事件模型
- 使用状态机
- 异步回调
- io多路复用,非阻塞io
连接池
worker_connection的大小就是连接池的大小,里面保存了fd的相关信息,包括读/写/超时等信息
内存池
- connnection_pool_size:连接内存池
- request_pool_size:请求内存池
以上配置是内存池的初始值,如果在使用中需要更大的内存,内存池会扩大。连接内存池会在连接关闭的时候释放,请求内存池会在请求结束后释放,对于小块内存的申请,会在内存池里以链表的方式来申请内存,对于大块内存的申请还是使用系统的内除,这样做的好处是大大的减少了内存碎片
进程间通讯
基本同步工具
- 信号
- 共享内存
高级通讯方式
-
锁:自旋锁
进程必须快速的使用共享内存
Slab内存管理器
共享内存使用的模块
rbtree:
- Ngx_stream_limit_conn_module
- Ngx_http_limit_conn_module
- Ngx_stream_limit_req_module
- http cache
- ssl
单链表
- Ngx_http_upstream_zone_module
- Ngx_stream_upstream_zone_module
Ngx_http_lua_api
同时使用红黑树和单链表,lua存的是key:value的数据,使用红黑树来存储,当超出了设定给红黑树的内存大小的时候,会是使用单链表,把最早的内存给淘汰
Slab内存分配管理
通过把内存切割成不同大小的slot,例如8b/16b/32b/64b..../2048b,当红黑树需要申请内存时,根据大小从某个slot的链表中申请内存
hashmap的bucket_size
bucket_size是用于对齐作用的,因为CPU在取数据的时候是根据cache line来取的,如果不对齐,那么bucket就有可能跨了两个或者多个cache line,导致cpu访问两次或者多次,使用对齐,可以减少cpu访问cache line的次数
红黑树
动态模块
- 静态是把所有模块生成一个执行文件
- 动态是生成动态库,多个文件,通过配置载入
指令的合并
值指令可以合并
例如root/access_log/gzip
- 子配置不存在,使用父配置块
- 子配置存在,覆盖父配置块
动作类指令不能合并
例如rewrite/proxy_pass
正则表达式
server的匹配顺序
host匹配server_name
- 精确匹配
- *在前的泛域名
- *在后分泛域名
- 按文件中顺序匹配正则表达式域名
- defalut server
- 第一个
- listen指定default
HTTP请求处理时的11个阶段
- post read
- server rewrite
- find configure
- rewrite
- post rewrite
- preaccess: limit_conn, limit_req
- access: auth
- post_access
- precontent: try_files, 分发请求
- content: index, autoindex,concat,proxy_pass
- log: access_log
readip
是一个模块,需要把模块编入nginx使用,用于提取客户端的ip地址
- set_read_ip_from: 添加可信用的ip来源,例如那台反向代理是我们自己的代理,那么我们信任在经过他的traffic添加的forward ip/real ip。
- read_ip_header: 我们是从X-read-ip读取还是X-Forwarded-for读取
- read_ip_recursive:是否开启读forward for第一个ip
rewrite
return指令
用于重定向或者直接返回
用法
return code [text]/URL
return URL
返回的状态码
- 444:关闭连接(Nginx自定义)
- 301:永久重定向
- 302:临时重定向,禁止被缓存
- 303:临时重定向,允许改方法,禁止被缓存
- 307:临时重定向,不允许改方法,禁止被缓存
- 308:永久重定向,不允许改方法
error_page指令
用法
error_page code file/url/location
负载均衡
- 水平扩展
- 通过hash扩展
- 通过拆分业务扩展
upstream {
server 127.0.0.1:8080 backup
server 127.0.0.1:9090 weight=2 max_conns=1 max_fails=10 fail_timeout=10
server 127.0.0.1:8888 down
}
#默认轮询
http keepalived
proxy_http_version 1.1
proxy_set_header Connection "";
keepalive #对Server启用keepalive
resolver address #DNS解析
hash
ip_hash; #对客户端ip进行hash
hash key [consistent] #对自定义key进行hash,consistent代表是否启用一致性hash
least_conn
least_conn;#最少连接负载均衡
zone name [size] #共享最少连接在worker之间
反向代理
proxy_path url #配置上有server
proxy_method #改写http的method
proxy_http_version 1.0|1.1 #改写http版本
proxy_set_header field value #改写头部属性
proxy_pass_request_headers on|off #是否透传header
pro
xy_pass_request_body on|off #是否透传body
proxy_set_body #改写body
proxy_request_buffering on|off #是否本地缓存请求,再发送到上游
client_body_buffer_size size #用于缓存body的buffer的大小
client_max_body_sizr size #body最大长度,超出返回413
client_body_temp_path path #body临时文件存储目录
client_body_in_file_only on|clean|off #是否保存body到文件
proxy_connect_timeout time #建立三次握手超时时间
proxy_next_upstream http_502|timeout|error|invalid_header|off #如果上游返回502|...则选择下一个上游发送请求
proxy_next_upstream_timeout time #请求上游得timout
proxy_next_upstream_tries number #尝试次数
proxy_intercept_errors on|off #error_page指令是否生效
proxy_socket_keepalive on|off #是否启用TCP keeaplive,代表每隔一段时间,则发一个探测报文
proxy_bind address #修改源ip地址
proxy_send_timeout time #发送超时时间
keepalive connections #启用http keepalive
keepalive_requests number #一个socket可以发送的请求数
proxy_buffer_size size # 接收上有http响应头部得最大长度
proxy_buffers number size #接收上游http包体
-
proxy_request_buffering
-
on
客户端网速慢
上有并发能力低
适应高吞吐量
-
off
即时相应
降低nginx读写磁盘
-
浏览器缓存
etag on|off #使用文件最后修改时间和文件长度生成
cache优化
proxy_cache_lock on|off
proxy_cache_use_stale
proxy_cache_background_update
启用后台线程update缓存,暂时先返回就得缓存给客户端
slice size
通过range协议将大文件分解成多个小文件缓存