NGINX随笔

90 阅读7分钟

简介

Nginx 官网是一个轻量级的、高性能反向代理服务器。并可实现缓存,认证及负载均衡等功能。还可充当静态WEB服务器。

命令

command-line

单位说明

  • nginx -h:查看帮助
  • nginx -v:查看版本信息
  • nginx -tq:测试配置文件,q只显示错误信息
  • ngxin -s stop:强制停止nginx
  • nginx -s quit:优雅停止nginx,使当前的工作进程完成后停止
  • nginx -s reload:平滑重启,重新加载配置文件
  • nginx -c xx.conf:以指定配置文件启动nginx
配置

文件结构:

指令分为简单指令和块指令。

  • 简单指令:名称与参数通过空格分隔,以分号结尾
  • 块指令:名称与{}结构。{}里面有其他指令的称之为容器(context)。例如events,http,server,location等。

配置文件中在任意容器之外的指令认为存在main容器中。

  1. 全局模块

    • work_processes number | auto :默认值为1,指定nginx 的工作进程数量。该数值不仅仅取决于cpu内核数量,还与存储数据硬盘数量和负载均衡模式有关,不确定时候可以设置为可用cpu内核数量(即auto)。
    • worker_rlimit_core size:为工作线程改变core(rlimit_core)文件的最大尺寸限制。
    • worker_rlimit_nofile number:为工作线程改变可打开文件的最大数量的限制。
    • worker_shutdown_timeout time:为工作线程的优雅关闭设置一个超时时间,当时间过期,nginx会尝试关闭所有连接促进关闭。
  2. events模块

    • accept_mutex on | off :

      • on:默认值(1.11.3以前),表示当新连接到来时,那些没有处于工作状态的worker将以串行的方式来处理。
      • off:默认,当新连接到来时,所有的worker都会被唤醒,不过只有一个worker能获取连接。其它的woker会重新进入阻塞状态,这会引起惊群现象。如果新连接数量较少,会浪费系统资源。
      • 在支持epollexclusive标识或使用reuseport的系统没必要开启。
    • accept_mutex_delay time:当accept_mutex开启时,设置队首worker尝试获取互斥锁的时间间隔。默认为500ms。

    • multi_accept on | off

      • off:默认,一个工作线程一次接收一个新连接。
      • on:一个工作线程一次接收所有的新连接。
      • 如果使用kqueue连接处理时,此指令会被忽略。
    • use method:设置worker与客户端连接的处理方式。通常没有必要显示的指定,nginx会自动选择适合当前系统最高效的方式。

    • worker_connections number:设置一个worker进程可以并发处理的最大连接数。默认是512,不能超过worker_rlimit_nofile的数量。这个数量包含所有的连接(代理服务等),不仅仅是与客户端的连接。

  3. http模块

    • include file | mask:可设置在任意位置。把指定的文件包含到配置文件中,文件应当包含语法的指令。

    • default_type mimie-type:默认为text/plain。定义响应的MIME类型。映射文件名扩展到MIME类型可以使用types指令设置。

    • sendfile on | off:默认为off。指定是否使用sendfile()方法。

    • keepalive_time time:默认1h。1.19.10以后。限制通过一个连接处理请求的最大时间。时间过期后,连接会被关闭。

    • keepalive_timeout timeout [header_timeout]:默认75s。第一个参数设置超时时间内活跃的客户端连接会在服务端存活。0禁止keep-alive客户端连接。第二个可选的参数设置响应头属性Keep-Alive:timeout=time。两个值可以不同。

    • keepalive_requests number:默认1000。设置一个长连接最多可以发送的请求数。在到达最大请求数后连接会关闭。在1.19.10以前默认100。周期性的关闭连接对每个连接的内存释放是有必要的。因此,使用太高的请求限制数量会导致过多的内存使用,不推荐。

    • client_body_timeout time:默认60s。定义读取客户端请求体的超时时间。两个成功读取操作的间隔,并不是整个请求体的传输。如果客户端在此时间范围没有传输内容,请求会被中断。

    • location [ = | ~ | * | ^ ] uri { ... }

    • location @name { ... }:基于请求的URI设置。

      关于root与alias

      alias:为指定路径定义一个替代路径,在location内设置。

      root:设置请求的根目录,返回路径为目录加上请求的uri。可在http, server, location内设置。

      • 通过前缀或者正则表达式匹配

        • 正则表达式以~*修饰符开头,大小写不敏感。或者~,大小写敏感。
      • 路径匹配优先级规则:首先使用prefix location来匹配,选择匹配最长的配置。然后检查正则表达式,以配置文件中出现的顺序匹配。一旦匹配到就中止继续匹配。如果没有正则表达式匹配到,就使用之前选择的prefix location。

        = 路径 > ^~匹配 > 正则匹配(文件顺序) > 长路径匹配 > 短路径匹配

      • 使用=匹配一个确定的URI。匹配到就终止查找。

      • ^~匹配 存在正则匹配时不可设置与其一致

      • 当定义路径以斜杠结尾,请求被proxy_pass,*_pass处理时,会有特殊的处理。如果请求的路径相同没有带斜杠,则会永久的重定向到带斜杠的URI上。

  4. location模块

    • proxy_pass url:设置代理服务的协议和地址。可指定http和https。地址可以指定为域名或者IP地址和可选的端口号,例

      proxy_pass http://localhost:8000/uri/;

      如果域名可以处理成多个地址,则会轮询调用。此外,地址可以指定为服务组。

      参数可以包含变量,这种情况下,如果地址指定为一个域名,在服务组中查找其域名,如果没有找到则使用resolver来决定。

      • proxy_pass指定一个URI,当请求传递到服务时,普通URI匹配location的部分被指令中指定的URI所替代。即

        location /query {
            porxy_pass http://example.com/user
        }
        # http://localhost/query/info -> http://example.com/user/info
        

        请求URI中location部分被截取后追加到proxy_pass后

      • 如果proxy_pass没有URI则请求会以原来的路径传递给代理服务。或者当处理变化的URI时传递请求的URI。

    • rewrite regex replacement [flag]:指定的正则表达式匹配到了uri,这个uri就会更改成replacement字符。rewrite指令以他们配置的顺序执行。可以使用flag参数来中止指令的处理。如果replacement以http://,https://,$scheme开头,处理停止并返回给客户端重定向。

      flag可以是:

      • last:停止ngx_http_rewrite_module指令的处理,开始寻找一个匹配新的URI的location。

      • break:使用break指令停止当前ngx_http_rewrite_module指令的处理。

      • redirect:返回临时重定向的302码。当replacement字符没有以http://,https://,$scheme开头时。

      • permanent:返回一个永久的301码的重定向。

      location / {
          ...
          default_type application/json;
          rewrite /hello/(.*) http://www.$1.com;
          return 200 "hello";
          ...
      }
      #重定向 localhost/hello/baidu -> http://www.baidu.com
      location / {
          ...
          default_type application/json;
          rewrite /hello/(.*) www.$1.com;
          return 200 "hello";
          ...
      }
      #响应 localhost/hello/baidu -> hello
      

      last与break都会中止其他rewrite模块指令的执行,但是last会立即发起新一轮的location匹配而break不会。

      server {
          ...
          location / {
              rewrite /path /path2;
              rewrite /path2 /path3;
          }
      ​
          location = /path2 {
              default_type application/json;
              return 200 "path2";
          }
      ​
          location = /path3 {
              default_type application/json;
              return 200 "path3";
          }
          # localhost/path/hello -> path3
          ...
      }
      

      rewrite根据匹配发起内部跳转,此循环最多执行10次

      # 500 rewrite or internal redirection cycle
      location / {
          rewrite ^/path1 /path2;
          rewrite ^/path2 /path3;
          rewrite ^/path3 /path1;
      }
      # break中止rewrite指令
      location / {
          rewrite ^/path1 /path2;
          rewrite ^/path2 /more/index.html break;
          rewrite /more/index.html /path3;
          proxy_pass http://www.baidu.com;
      }
      # localhost/path1 -> http://www.baidu.com/more/index.html
      
    • return code [text] | return code URL | return URL:

      停止处理,返回给客户端指定的code。临时跳转的URL可以指定为唯一的参数,这个参数应该以http://,https://,$scheme开头。URL可以包含变量。

  5. 缓存配置

    nginx有很强大的缓存功能,可以对请求的response进行缓存,起到类似CDN的作用。同时,nginx缓存还可以用来数据托底,即当后台web服务器宕机后,nginx可以直接将缓存中的托底数据返回给用户。这也是nginx实现服务降级的体现。

    nginx缓存功能功能配置由两部分构成:

    全局定义与局部定义。在http模块的全局部分中进行缓存全局定义,在server模块中的各个location中进行缓存局部定义。

    • http的缓存全局定义

      • proxy_cache_path:用于指定nginx缓存的存放路径及相关配置
      • proxy_temp_path:指定nginx缓存的临时存放路径,若proxy_cache_path中的use_temp_path设置了off则该属性不可指定
    • location的缓存局部定义

      • proxy_cache cacheZone:指定用于存放缓存key内存区域名称。其值为http模块中proxy_cache_path中的keys_zone值。
      • proxy_cache_key $host$request_uri$arg_age:指定nginx生成的缓存的key的组成。
      • proxy_cache_bypass $arg_age:指定是否越过缓存
      • proxy_cache_methods GET HEAD:指定请求方法会被缓存,默认是GET与HEAD,不缓存POST。
      • proxy_no_cache aab$c:指定对本次请求是否不做缓存。只要一个不为0,就不缓存该请求。
      • proxy_cache_purge aab$c:指定是否清楚缓存key。
      • proxy_cache_lock on:指定是否采用互斥方式回源。
      • proxy_cache_lock_timeout 5s:指定再次生成回源互斥锁的实限。
      • proxy_cache_valid 5s:对指定的HTTP状态码的响应数据进行缓存,并指定缓存时间。默认指定的状态码是200,301,302。
      • proxy_cache_use_stale:设置启用托底缓存的条件。一旦这里指定了相应的状态码,则proxy_cache_valid中指定的相应状态所生成的缓存就变为了拖底缓存。
      • expires:为请求的静态资源开启浏览器端的缓存。
  6. nginx变量

    • 自定义变量:nginx配置文件是perl脚本。设置方式为set $a "a"

    • 内置变量:

      $args 请求中的参数;
      $binary_remote_addr 远程地址的二进制表示;
      $body_bytes_sent 已发送的消息体字节数;
      $content_length http请求信息里的“Content-Length”;
      $content_type 请求信息里的“Content-Type”;
      $document_root 针对当前请求得根路径设置值;
      $document_uri$uri相同;
      $host 请求信息中的“Host”,如果请求中没有Host则等于设置的服务器名;
      $http_cookie cookie信息
      $http_referer 来源地址
      $http_user_agent 客户端代理信息
      $http_via 最后一个访问服务其的IP地址
      $http_x_forwarded_for 相当于网络访问路径
      $limit_rate 对连接速率的限制
      $remote_addr 客户端地址
      $remote_port 客户端端口号
      $remote_user 客户端用户名,认证用
      $request 用户请求信息
      $request_body 用户请求主体
      $request_body_file 发往后端的本地文件名称
      $request_filename 当前请求的文件路径名
      $request_method 请求方法
      $request_uri 请求的uri,带参数
      $server_addr 服务器地址
      $server_name 请求的服务器名
      $server_port 请求的服务器端口
      $server_protocol 请求的协议版本,如“HTTP/1.0“ 
      $uri 请求的uri
      
  7. 日志管理

    日志的相关属性可以配置在任意模块。不用的模块,记录的是不同请求的日志信息。nginx日志一般可以指定三个范围:http模块范围,server模块范围,location模块范围。

    • http模块范围

      只要有请求通过http协议访问该nginx,就会有日志信息写入到这个的日志文件。

      http{
          ...
          log_format main '[$remote_addr]=[$remote_user]=[time_local]=[$request]'
          '[$status]=[$body_bytes_sent]=[$http_referer]'
          '[$http_user_agent]=[$http_x_forwarded_for]';
          
          # 第一个参数 日志的存放路径与日志文件名
          # 第二个参数 日志格式名
          # 第三个参数 日志文件所使用的缓存。不过,即使不指定buffer,其也会存在默认日志缓存
          # access_log还可跟参数off,用于关闭访问日志
          access_log logs/access.log main buffer=64k;
          # 不能指定格式,因为有默认的格式
          # 可以使用自己指定的错误日志文件,不过,将来的访问异常日志就不会写入到默认的logs/error.log文件中了。所以关于错误日志,一般使用默认的即可。
          # 错误日志级别由低到高有:[debug|info|notice|warn|error|crit|alert|emerg],默认为error,级别越高记录的信息越少
          # 错误日志默认是开启的,关闭错误日志 error_log /dev/null;
          error_log logs/error.log;
          ...
      }
      
    • server模块

      只要有请求访问当前server,就会有日志写入到这里的日志文件。

      server{
          ...
          access_log logs/host.access.log main;
          error_log logs/host.error.log;
          
          ...
      }
      
    • location模块

      只要有请求访问当前location,就会有日志信息写入到这个日志文件。

      location / {
          ...
          access_log logs/location.access.log main;
          error_log logs/location.error.log;
      }
      
    • 日志管理指令

      日志分为两类:访问日志与错误日志。nginx整个系统的默认日志在生成预编译文件makefile时就已经配置好了。当然,无论是访问日志还是错误日志,其默认路径与名称在nginx.conf中都是可以修改的。在配置文件中不仅定义了日志文件的路径及名称,还定义日志格式。

      • log_format:用于设置访问日志的格式。

      • access_log:用于设置访问日志。

      • error_log:用于设置错误日志的路径与文件名。

      • open_log_file_cache:该指令用于打开日志文件读缓存,将日志信息读取到缓存中,以加快对日志的访问。该功能默认为off,即open_log_file_cache off;

      客户端对服务端页面会自动提交一个/favicon.ico请求,若没有favicon.ico文件则会在日志文件中报出404。

      可以添加其文件并设置路径

      location / {
          root html;
          index index.html index.htm;
      }
      location /favicon.ico {
          root html;
      }
      
  8. 日志切割

    a. 先创建shell脚本文件

    b. 为该文件添加可执行权限

    c. 向crontab中添加一个定时任务

    例:

    root ~:crontab -e
    89 23 * * * /usr/local/nginx/logs/cut_nginx_log.sh
    
  9. 页面压缩

    常见的压缩协议:

    • deflate:过时的压缩算法,是huffman编码的一种加强。

    • gzip:是目前大多数浏览器都支持的一种压缩算法,是对deflate的改进。

    • sdch:谷歌开发的一种压缩算法。与gzip(修改传输数据的编码格式以达到减少体量的目的)不同的是,其让冗余的数据仅出现一次,其最终传输的数据减少了。

    • zopfli:谷歌开发的一种压缩算法。deflate压缩算法的改进。比标准的gzip-9要小3%-8%,但压缩用时是gzip-9的80多倍。

    • br:Brotli,谷歌开发的一种压缩算法。是一种全新的数据格式。与Zopfli相比,压缩率能够降低20%-26%。Brotli-1有着与Gzip-9相近的压缩比和更快的压缩解压速度。

    • 常用设置

      # 开启压缩
      gzip on;
      # 指定最小启用压缩的文件大小
      gzip_min_length 5k;
      # 指定压缩级别,取值1-9,数字越大,压缩比越高,但压缩所用时间会越长。默认为1,建议为4
      gzip_comp_level 4;
      # 4表示缓存颗粒数量 16k表示缓存颗粒大小
      gzip_buffers 4 16k;
      # 开启动态压缩,默认off。
      gzip_vary on;
      # 通过MIME类型指定要压缩的文件类型。默认为text/html
      gzip_types text/html text/css text/xml application/x-javascriptg;
      
负载均衡

处理负载

  • 硬件负载均衡:性能稳定,成本很高。例:F5,深信服等。

  • 软件负载均衡:成本较低

  • 工作分类:

    • 七层负载均衡:应用层,基于HTTP协议,通过虚拟URL将请求分配到真实服务器。一般应用于B/S架构系统。Nginx就是七层负载均衡。
    • 四层负载均衡:传输层,基于TCP协议,通过虚拟IP+端口号将请求分配到真实服务器。一般应用于C/S架构系统。LVS,F5都属于四层负载均衡
    • 三层负载均衡:网络层,基于IP协议,通过虚拟IP将请求分配到真实服务器。
    • 二层负载均衡:链路层,基于虚拟MAC地址将请求分配到真实服务器。
  1. 负载均衡策略

    • 轮询:默认的负载均衡策略,按照各个主机的权重比例依次进行请求分配的。

      upstream myserver {
          server server1 weight=2 fail_timeout=20 max_fail=3;
          server server2 weight=1 fail_timeout=20 max_fail=3;
          server server3 backup;
          server server4 down;
      }
      # backup:表示当前服务器为备用服务器
      # down:表示当前服务器永久停机
      # fail_timeout:表示当前主机被nginx认定为停机的最长失联时间,默认为10s。常与max_fails联合使用
      # max_fails:表示在fail_timeout时间内最多允许的失败次数
      
    • IP哈希:指定负载均衡器基于客户端IP进行分配。

      upstream myserver {
          ip_hash;
          server server1 weight=2 fail_timeout=20 max_fail=3;
          server server2 weight=2 fail_timeout=20 max_fail=3;
          server server3 weight=2 fail_timeout=20 max_fail=3;
      }
      # 该策略不能与backup同时使用
      # 此策略适合有状态服务,比如session
      # 当有服务器宕机,必须手动指定down属性,否则请求仍会落到该服务器
      
    • least_conn:把请求转发给连接数最少的服务器。

      upstream myserver {
          least_conn;
          server server1;
          server server2;
          server server3;
      }
      

默认配置文件

nginx-1.18.0

#user  nobody;
# 默认为1 建议不修改 若调整推荐为核心数量
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;#监听网络事件和定时器事件
events {
    #单个工作进程可以允许同时建立外部连接的数量。与两个指标有关:一是内存,二是操作系统级别的“进程最大可打开文件数”
    worker_connections  1024;
}
​
​
http {
    include       mime.types;
    default_type  application/octet-stream;
​
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
​
    #access_log  logs/access.log  main;
​
    sendfile        on;
    #tcp_nopush     on;
​
    #keepalive_timeout  0;
    keepalive_timeout  65;
​
    #gzip  on;
​
    server {
        listen       80;
        server_name  localhost;
​
        #charset koi8-r;
​
        #access_log  logs/host.access.log  main;
​
        location / {
            root   html;
            index  index.html index.htm;
        }
​
​
        #error_page  404              /404.html;
​
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
​
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ .php$ {
        #    proxy_pass   http://127.0.0.1;
        #}
​
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ .php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}
​
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /.ht {
        #    deny  all;
        #}
    }
​
​
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;
​
    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
​
​
    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;
​
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;
​
    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;
​
    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;
​
    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
​
}

参考

  1. nginx核心模块帮助文档

补充

多路复用

nginx处理方式