初识Nginx

使用场景

nginx-use

特性

IO多路复用

使用epoll模型,高并发处理客户端的请求

CPU亲和

把working进程与CPU绑定,避免working进程不必要的在CPU之间切换

sendfile

nginx-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;
}
nginx-status

下载站点

可以配置在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

正则表达式

nginx-pcre

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
nginx-11

readip

是一个模块,需要把模块编入nginx使用,用于提取客户端的ip地址

nginx-readip
  • 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之间

反向代理

nginx-upstream
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读写磁盘

浏览器缓存

nginx-brower-cache
etag on|off #使用文件最后修改时间和文件长度生成

cache优化

proxy_cache_lock on|off

nginx-cache-lock

proxy_cache_use_stale

nginx-cache-stale

proxy_cache_background_update

启用后台线程update缓存,暂时先返回就得缓存给客户端

slice size

通过range协议将大文件分解成多个小文件缓存

nginx-slice

你可能感兴趣的:(初识Nginx)