Nginx

nginx 作为近年来最火的中间件之一,很有必要学习 nginx 优势

  1. 采用 IO 多路复用epoll模型,epoll驱动的就是在操作系统下的系统内核来进行工作,实现 IO 复用的处理方式
  • 多进程多线程处理,但一个线程只能处理一个 IO 流
  • 多路 IO 复用,采用的是一个线程并实现 IO 流非阻塞模式
while true {
  for i in stream[]; {
    // 查看有无数据,无数据就进行循环
    if i has data
    read until unavailable
  }
}

所以当没有数据时,就会白白浪费 cpu,此时我们可以使用内核模型来进行循环,一般使用的是 epoll 模型, epoll 模型相当于是一个代理,获取有数据的循环再进行遍历 epoll 优势 - 解决 SELECT 模型对于文件句柄 FD 打开限制 - 采用 callback 函数回调机制优化模型效率 2. 利用了 cpu 亲和 affinity 来提高 cpu 的并发处理能力减少不必要的性能损耗。cpu 亲和就是把 cpu 核心和 Nginx 工作进程绑定方式,把每个 worker 进程固定在一个 cpu 上执行,减少切换 cpu 的 cache miss,获得更好地性能 3. sendfile ,在没有 nginx 时,用户发送一个请求获取文件的时候,会经过内核空间和用户空间,最终到达 socket 并传递给用户,而 sendfile 只会进过内核空间传递给用户

安装

这里查看

安装目录

  • /etc/logrotate.d/nginxNginx 日志轮转,用于logrotate服务的日志切割,也就是可以按天进行输出
  • /etc/nginx | /etc/nginx/nginx.conf | /etc/nginx/conf.d | /etc/nginx/conf.d/default.confNginx 主要配置文件
  • /etc/nginx/fastcgi_params | /etc/nginx/uwsgi_params | /etc/nginx/scgi_paramscgi配置和fastcgi配置
  • /etc/nginx/koi-utf | /etc/nginx/koi-win | /etc/nginx/win-utf编码转换映射转换文件
  • /etc/nginx/mime.types设置 http 协议的Content-Type与扩展名对应关系
  • /usr/lib/systemd/system/nginx-debug.service | /usr/lib/systemd/system/nginx.service | /etc/sysconfig/nginx | /etc/sysconfig/nginx-debug用于配制出系统守护进程管理器管理方式
  • /usr/lib64/nginx/modules | /etc/nginx/modulesNginx 模块目录
  • /usr/sbin/nginx | /usr/sbin/nginx-debugNginx 命令
  • /usr/share/doc/nginx-1.12.0 | /usr/share/doc/nginx-1.12.0/COPYRIGHT | /usr/share/man/man8/nginx.8.gzNginx 的手册和帮助文件
  • /var/cache/nginxNginx 的缓存目录
  • /var/log/nginxNginx 的日志目录

命令

  • nginx -t -c:查看配置是否正确
  • nginx -s reload -c:重新加载配置

配置语法

默认配置语法

  • user:设置 nginx 服务的系统使用用户

  • worker_processes:工作进程数,一般和 cpu 核心一致

  • error_log:nginx 的错误日志

  • pidnginx服务启动时候pid

  • events:事件模块

    • worker_connections:每个进程允许最大连接数
    • use:设置 nginx 使用的内核模型
  • http: 包含所有 http 的服务

    • server:配置虚拟或是独立的站点

      • listen:监听的端口
      • server_name:监听的 host
      • location:控制每一层路径的访问
        • 可以接一个路径,然后有一个模块
      • error_page: 可以接状态码,之后再接页面

`

server {
  listen 80;
  server_name localhost;

  location / {
    root /usr/share/nginx/html;
    // 如果在 root 路径下没有找到 index.html 回去找 index.htm
    index index.html index.htm;
  }

  error_page 500 502 /50x.html;
  location = /50x.html {
    // 在这个路径下寻找对应的 html 文件
    root /usr/share/nginx/html;
  }
}
  • include:包含所有的Content-Type
  • default_type:默认的Content-Type
  • log_format:日志类型
  • keepalive_timeout <时间长度>:客户端和服务端超时的时间
  • gzip:打开gzip

虚拟主机

当我们希望一个 Nginx 来运行多套单独服务时,可以配置多个虚拟主机。有三种方式

  1. 基于主机的多 IP 的方式
  • 多网卡多 IP 的方式,网卡 1 -> IP1 网卡 2 -> IP2,对主机配置要求高
  • 单网卡多 IP 的方式,网卡 1 -> IP1 -> IP2,对网卡设置别名。通过ip a add <Ip>/<掩码> dev <设备名>的方式来增加 IP 地址,在增加之前使用ping <IP>的方式来判断这个域名是否存在服务,如果有服务就不能增加
  1. 基于端口的配置方式
  • 端口其实和上面类似,只不过不用设置多 IP,listen监听的是不同端口号即可。需要处理的是端口冲突,需要先用命令查看,然后避开对应的端口
  1. 基于多个 host 名称方式,常见的方式,也就是多域名方式。它只需要一个 IP 和一个端 虚拟主机的配置放在 nginx 的配置文件 /etc/nginx/nginx.confincludes 属性中包括的路径中,之后通过 listen 属性配置到具体的 IP 地址 首先需要修改本地的 host 文件,增加 IP 对应的 host 地址,但需要配置的 host 地址对应同一个 IP 地址,同时需要配置 server_name

`


server {
listen 80;
server_name 2.imooc.com;
}

日志

日志类型包括 error.logaccess_log

  • error.log:主要用于处理 http 请求的状态,以及 nginx 服务的状态,会按照不同的级别记录到error.log
    • error_log <log 位置> <error 级别(比如 warn)>:在服务配置中增加字段
  • access_log:依赖于log_format的配置,每一个信息都是对应一个变量,log_format就是将所有变量组装到一起
    • access_log <log 位置> <log_format 的 name>:在服务配置中增加字段
    • Nginx 变量:可在log_format中进行组合format输出日志信息
      • HTTP 请求变量
        • arg_<变量名>:输出信息
        • http_<HEADER>request中的head
        • sent_http_<HEADER>response中的head
      • 内置变量:比较多,进入官网了解
      • 自定义变量

模块

使用 nginx -V ,以 --with 开头的就是开启的模块

  • Nginx 官方模块,官方支持的模块
    • --with-http_stub-status_module:Nginx 的客户端状态,此时可以使用浏览器访问<地址>/mystatus查看 nginx 当前活跃的连接数
      • Syntax: stub_status
      • Default: --
      • Context: serverlocation
location /mystatus {
  stub_status;
}
  • --with-http_random_index_module:目录中选择一个随机主页,也就是随机选择一个主页,给用户不同的感觉。但不会选择路径下的隐藏文件
    • Syntaxrandom_index on | off
    • Defaultrandom_index off
    • Contextlocation
location / {
  random_index on;
}
  • --with-http_sub_module:HTTP 内容替换
    • Syntaxsub_filter <要替换的内容> <替换的内容>

    • Default:--

    • Contexthttpserverlocation 或是,每次请求校验服务器内容是是否更新,如果更新返回的是新的

    • Syntaxsub_filter_last_modified on | off

    • Defaultsub_filter_last_modified off

    • Contexthttpserverlocation 或是,匹配所有 html 代码里的第一个,还是匹配所有指定的字符串

    • Syntaxsub_filter_once on | off

    • Defaultsub_filter_once on

    • Contexthttpserverlocation

  • 第三方模块

请求限制

HTTP 协议的连接与请求

  • HTTP1.0:TCP 不能复用
  • HTTP1.1:顺序性 TCP 复用
  • HTTP2.0:多路复用 TCP 复用
  • -limit_conn_module:连接限制 调用空间进行限制, key 就是对什么进行限制,比如 IPname 就是这个 zone 的名字, size 就是大小
    • Syntaxlimit_conn_zone key zone=name:size

    • Default:--

    • Contexthttp 以及, zone 表示申请的 zone 名, number 就是同一时间只能允许多少个

    • Syntaxlimit_conn zone number

    • Default:--

    • Contexthttp,server, location

  • -limit_req_module:请求限制 也是调用空间进行限制, name 就是 zone 名, size 就是空间大小, rate 就是对速率进行限制,通常以秒为单位
    • Syntaxlimit_req_zone key zone=name:size rate=rate;
    • Default:--
    • Contexthttp
  # $binary_remote_addr 表示的是客户端的地址
  limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s

以及, burst 表示是超过指定速率以后,遗留的三个请求放到下一秒请求,其他的会直接返回

  • Syntaxlimit_req zone=name burst=number] [nodelay]
  • Default:--
  • Contexthttp,server, location

访问控制

  • http_access_module:基于 IP 的访问控制,但是它只是对代理层进行限制,而对真正的客户端没有进行限制。

    • http_x_forwarded_for:常用的 http 变量,会显示代理以及发起连接的客户端 IP,可以一定程度的解决限制真正客户端问题 - http_x_forwarded_for = Client IP, Proxy(1) IP, Proxy(2) IP - 局限性 - 它是通过头HTTP_X_FORWARD_FOR来进行控制的,可能有厂商不使用这个头,或是传递一个别的值 - 结合geo模块 - 通过 HTTP 自定义变量传递,可以在 HTTP 头定义一个我们规定的变量,在联系上一级时把自己的remote_addr信息携带到上一级上,从而得到客户端信息

address IP 地址, CIDR 网段, unix 就是 linux 或是 unix 使用 socket 的方式的访问, all 就是允许所有的

  • Syntaxallow address | CIDR | unix: | all

  • Default:--

  • Contexthttp,server, location, limit_except 或是,也就是不允许访问的

  • Syntaxdeny address | CIDR | unix: | all

  • Default:--

  • Contexthttp,server, location, limit_except

  • http_auth_basic_module:基于用户的信任登录

    • Syntaxauth_basic string | off

    • Default:auth_basic off`

    • Contexthttp,server, limit_except 以及, file 就是用来存储用户名和密码信息的文件,需要按照 nginx 规定的格式。可以使用 htpasswd 来生成密码文件, htpasswd -c <生成文件名> <用户名>

    • Syntaxauth_basic_user_file file

    • `Default:--

    • Contexthttp, location,server, limit_except 局限性

    1. 用户信息依赖文件方式

    2. 操作管理机械,效率低下 解决方案

    3. nginx 结合LUA实现高效验证

    4. nginx 和 LDAP打通,利用nginx-auth-ldap模块

静态资源 web 服务

静态资源类型,静态资源就是那些不需要动态生成的资源

  • 浏览器渲染:HTMLCSSJS

  • 图片:JPEGGIFPNG

  • 视频:FLVMPEG

  • 文件:TXT等任意下载文件 静态资源服务场景 CDN ,其实就是把资源存储中心的资源分发给不同地区,各存一份。之后在不同地区的用户,通过智能 DNS 技术,动态定位到北京的代理上进行请求,就不需要请求资源中心,也就是传输时延的最小化

  • 文件读取

    • Syntaxsendfile on | off
    • Defaultsendfile off
    • Contexthttp, server, location, if in location
  • tcp_nopushsendfile开启的情况下,提高网络包的传输效率。把包进行整合,之后一次性发送出去。处理大文件会跟有利

    • Syntaxtcp_nopush on | off
    • Defaulttcp_nopush off
    • Contexthttp, server, location
  • tcp_nodelay不会对包进行整合,在keepalive连接下,提高网络包的传输实时性

    • Syntaxtcp_nodelay on | off
    • Defaulttcp_nodelay on
    • Contexthttp, server, location
  • 压缩,减少不必要的网络资源消耗

    • Syntaxgzip on | off

    • Defaultgzip off

    • Contexthttp, server, location, if in location 压缩比

    • Syntaxgzip_comp_level level

    • Defaultgzip_comp_level off

    • Contexthttp, server, location 协议版本

    • Syntaxgzip_http_version 1.0 | 1.1

    • Defaultgzip_http_version 1.1

    • Contexthttp, server, location

http_gzip_static_module :默认的模块,可以预读 gzip 功能,当读取静态文件比如 html 文件时,会先去找 .gz 结尾的文件 http_gunzip_module :当不支持 gzip 时,应用支持 gunzip 的压缩方式,现实很少用到

  • 缓存:expires用于添加Cache-ControlExpires
    • Syntaxexpires [modified] time;expores epoch | max | off;
    • Default: expores off
    • Context: http, server, location, if in location
  • 跨域
    • Syntax: add_header name value [always]
    • Default: --
    • Context: http, server, location, if in location
  • 防盗链:防止资源被盗用,希望是一些合法用户来访问网站,防止爬取。首要方式:区别那些请求是非正常的用户请求 基于 http_refer 防盗链配置模块,同时 http_refer 也是一个变量。它会记录上次请求的域名
    • Syntax: valid_referers none | blocked | server_names | string...;如果none表示只允许不带refer的请求blocked表示不带协议信息的请求是不被允许的
    • Default: --
    • Context: server, location
  valid_referers none blocked 116.62.103.228
  if ($invalid_referer) {
    return 403
  }

代理服务

按应用场景模式来分类有两种,正向代理和反向代理

  • 正向代理: 即通过代理访问其他代理
  • 反向代理: 针对性地访问某个站点的时候,为服务端提供服务 常见的反向代理模式和 Nginx 代理模块 |反向代理模式|Nginx 配置模块| | ---------------------- | |http、websocket、https| ngx_http_proxy_module| |fastcgi| ngx_http_fastcgi_module| |uwsgi| ngx_http_uwsgi_module| |grpc| ngx_http_v2_module|
  • 常见的代理语法
    • Syntax: proxy_pass URL
    • Default: --
    • Context: location, if in location, limit_except
  • 缓冲区,后端可能发送的只是小部分头信息,这里可以在数据全部存在时,才会返回数据,但会占用内存资源
    • Syntax: proxy_buffering on | off;
    • Default: proxy_buffering on;
    • Context: http, server, location
  • 跳转重定向
    • Syntax: proxy_redirect default; | proxy_direct off; | proxy_redirect redirect replacement;
    • Default: proxy_buffering default;
    • Context: http, server, location
  • 头信息,把头信息从代理带到后端
    • Syntax: proxy_set_header field value;
    • Default: proxy_set_header Host $proxy_host; | proxy_set_header Connection close;
    • Context: http, server, location
  • 超时,连接超时
    • Syntax: proxy_connect_timeout time;
    • Default: proxy_connect_timeout 60s;
    • Context: http, server, location

缓存

缓存分为服务端缓存,代理(Nginx)缓存,客户端缓存 代理缓存就是在请求的时候直接从代理中获取缓存

  • proxy_cache配置语法,定义pathpath就是存放缓存文件的地址

    • Syntax: proxy_cache_path path;
    • Default: --
    • Context: http

proxy_zone 其中的 zone 就是定义的 path

  • Syntax: proxy_cache zone | off;

  • Default: proxy_cache off

  • Context: http, server, location 缓存过期周期, code 就是状态码

  • Syntax: proxy_cache_valid [code ...] time;

  • Default: --

  • Context: http, server, location 如何清理指定缓存

  • rm -rf缓存目录内容

  • 第三方模块ngx_cache_purge 如何让部分页面不缓存, url 为参数

    • Syntax: proxy_no_cache string ...

    • Default: --

    • Context: http, server, location 缓存命中分析

    • add_header Nginx-Cache "$upstream_cache_status";response添加头信息

    • 通过设置log_format打印日志分析,也是使用$upstream_cache_status这个变量

    • $upstream_cache_status有以下状态

      • MISS:未命中,请求被传送到后台处理
      • HIT:缓存命中
      • EXPIRED:缓存已经过期,请求被传送到后台处理
      • UPDATING:正在更新缓存,经使用旧的应答
      • STALE:后端得到过期的应答 缓存命中率 = HIT 次数 / 总请求次数,通过分析 Nginx 里的 Acess 日志可以分析得到命中率
log_format main '"$upstream_cache_status"';

对大文件的分片请求,前端请求到达之后,根据定义的分片,将文件进行切片再分为多个不同的小的请求同时请求后端

  • Syntax: slice size;
  • Default: slice 0;
  • Context: http, server, location 优势:每个子请求收到的数据会形成一个独立文件,一个请求断了,其他请求不受影响 缺点:当文件很大或 slice 很小的时候,可能会导致文件描述符耗尽等情况