Nginx学习

发行版本

Nginx开源版:提供基础功能

Nginx Plus商业版:提供高级功能,如对微服务整合、云原生整合

Openresty:Nginx和Lua脚本整合提供丰富的功能

Tengine:Nginx和C整合,淘宝提供的稳定的魔改版,如果没二次开发的需求可以选择使用

命令

./nginx # 启动
./nginx -s stop # 快速停止
./nginx -s quit # 优雅关闭。执行的连接请求处理完后再退出
./nginx -s reload # 加载配置文件。在处理的请求用旧配置完成,开启新的子进程加载新的配置来处理新的请求

基本使用

https://nginx.org/en/docs/

最小配置

worker_processes  12; # 工作线程

events {
    worker_connections  1024; # 连接数
}

http {
    include       mime.types; # 同级目录下的mime.types文件,其定义了浏览器应该用哪种方式解析某种后缀名的数据
    default_type  application/octet-stream; # 默认解析方式
    sendfile        on; # 零拷贝
    keepalive_timeout  65; # 长连接超时时间
    server { # 虚拟主机vhost
        listen 80; # 监听端口
        server_name localhost; # 域名、主机名
        location / { # 匹配URI
            root html; # 匹配成功后以哪个目录为根目录,相对于Nginx的主目录
            index index.html index.htm; # 默认页
        }
        error_page 500 502 503 504 /50x.html; # 哪些状态码跳转到出错页面/50x.html
        location = /50x.html {
        	root html; # 匹配URI,跳转到配置的目录下寻找对应的文件
        }
    }
}

虚拟主机与域名解析

原理:一台Nginx为多个域名提供服务,某个域名的请求过来,Nginx为其找到对应的目录以提供服务。目的是为了提高主机的CPU、内存等的利用率,因为大部分域名的流量非常小,服务器性能过剩。

本地域名解析:hosts文件。

泛域名解析:即配置通配符,可以实现多用户二级域名,如*.sj.com可以将a.sj.com/b.sj.com等所有类似的域名都解析到同一个IP地址上。

ServerName匹配规则为首次匹配到就结束,如果都没有匹配到,则以第一个作为匹配结果。有以下匹配方式:

server_name vod.sj.com vodd.sj.com ; # 匹配多个域名
server_name *.sj.com; # 通配符匹配
server_name vod.sj.*; # 通配符结束匹配
server_name ~^[0-9]+\.sj.com$; # 正则匹配

反向代理

能提供的功能:

  • URL重写,既可以隐藏真实URL,又可以方便用户记忆,还能提高搜索引擎(这用SSR更好)收录。如用户看到的是/product/100,Nginx重写为/product?id=100
  • 负载均衡

反向代理配置

upstream abc {
    server 192.168.0.11:80;
    server 192.168.0.12:80;
}
server {
    # ...
    location / {
        proxy_pass http://abc;
    }
}

动静分离

常用于中小型项目,大型网站一般是将静态资源作为独立域名。

server {
    # ...
    location / {
        proxy_pass http://192.168.0.11:80;
    }
    location ~*/(js|img|css) { # 正则匹配
        proxy_pass http://192.168.0.12:80;
    }
}

location /的优先级比较低。

URL Rewrite

rewrite <regexp> <replacement> [flag]。rewrite允许出现的位置:server、location、if。

flag说明:

  • last。本条规则匹配完成后,继续向下匹配新的location URI规则。也就是最后面的匹配会返回。
  • break。本条规则匹配完成后终止。
  • redirect。返回302重定向。
  • permanent。返回301永久重定向。
server {
    # ...
    location / {
        rewrite ^/([0-9]+).html$ /index.jsp?page=$1 break;
        proxy_pass http://192.168.0.11:80;
    }
}

防盗链

盗链定义:其他网站引用了本网站的静态资源。

防盗链:通过HTTP的referer字段。

location ~*/(js|img|css) {
    # 校验referer。none表示如果没有referer也允许访问,比如用户拿着给的链接去下载器下载,这种情况就是没有referer
    valid_referers none 192.168.0.11;
    if (!invalid_referer) {
        rewrite ^/ /img/x.png break; # 重写展现防盗链图片
        
        return 403; # 返回错误码
    }
    proxy_pass http://192.168.0.11:80;
}

HA

依赖keepalived+虚拟IP的能力

高级使用

保持会话

Nginx提供保持会话的功能:

  • ip_hash:同一个ip的请求只会在同一台服务器上被处理。优点是服务器扩容方便,缺点是访问倾斜。可用于中小型项目。
  • hash $cookie_jsessionid;:Java服务下发给客户端的cookie。
  • hash $request_uri;:适用于在不支持cookie的场景(如APP),也适用于某些资源不存在于所有服务器上的情况(如视频、音频等)。
  • sticky模块:通过类似于cookie_jsessionid的方式,在cookie中保存一个字段,值是由该模块产生的。可以设置过期时间。

对上游服务器使用keepalive

upstream配置:

upstream abc {
    keepalive 100; # 与上游服务器保持的连接数(类似连接池概念)
    keepalive_timeout 65; # 连接保留的时间
    keepalive_requests 1000; # 一个tcp连接复用中可以并发接收的请求数
}

server配置:

server {
    proxy_http_version 1.1; # http版本号。默认使用1.0版本,需要在request中增加"Connection keep-alive" header才能使用,而1.1默认支持
    proxy_set_header Connection ""; # 清除close信息,因为Nginx接收浏览器请求后会将Connection置为close
}

客户端限制

可配置位置:

  • http
  • server
  • location
client_body_buffer_size # 请求体缓冲区大小
client_header_buffer_size # 请求头缓冲区大小
client_max_body_size # 请求大小超过设定值会返回413给客户端,通过检查Content-Length实现。默认1M,设置为0可以禁用
client_body_timeout # 服务端接收request body的超时时间。比如因为网络原因,服务端接收到部分,然后在超时时间内再也没有接收到数据,会返回408
client_header_timeout # 服务端接收request header的超时时间。超时返回408
client_body_in_single_buffer # 缓冲body时尽量在内存中使用连续单一的缓冲区,常用于在二次开发中使用 $request_body 读取数据时,不二次开发不需要配置。

Gzip

一般用于文本格式数据的压缩,对于二进制文件不需要启用压缩。

# 动态压缩。即数据传输过程中压缩
gzip on; # 启用gzip。默认关闭
gzip_buffers 16 8k; # 16个缓冲块,大小8k
gzip_comp_level 6; # 压缩等级1-9,数字越大压缩率越高
gzip_http_version 1.1; # 使用gzip的最小版本
gzip_min_length 2k; # 小于该值的不压缩
gzip_proxied any; # 作为反向代理服务器时,针对上游服务器返回的头信息进行压缩,any表示无条件启用压缩。其他有expired等

# 静态压缩。动态压缩没法利用sendfile,静态压缩的意义在于通过sendfile直接将压缩文件发送
# 需要在编译时加上对应的模块。--with-http_gzip_static_module
gzip_static on; # 启用。默认off,还可选always(需搭配ngx_gunzip_module使用)

高并发系统资源静态化方案

后端取到数据后,输出到模板引擎,修改模板引擎的输出到文件(html),该文件由Nginx代理,从而实现多次访问某个同一页面时响应很快的功能。在并发量很大的情况下,可以利用该方案。

一个页面中由三部分组成:

  • 每个页面特有的内容,可由模板引擎生成
  • 页面关联的内容(如推荐、销量等)
  • 所有页面都有的固定内容(如head、footer等)

需要考虑的问题:

  • 一致性问题
  • 合并文件(Nginx提供的SSI模块可以实现)
  • Nginx集群文件同步(多台Nginx服务器同步某一台主Nginx服务器,通过rsync同步,通过inotify监控文件的变更)。rsync主动推送到其他服务器,需要将readonly改为no,默认只能通过定时的方式推送或拉取,通过引入inotify实现在有变化时才操作。

缓存

浏览器缓存

  • 强制缓存:Nginx返回资源并告知缓存时间,浏览器在缓存有效期间内不请求Nginx。Expire或者Cache-Control
  • 协商缓存:Nginx返回资源并携带Last-Modified响应头,浏览器下次请求时带上该时间到请求头,Nginx检查本地文件是否改变,未改变则返回304OK,浏览器从本地缓存中取。

GEOip

可以判断浏览器的IP属于哪个城市or哪个国家,从而实现拒绝指定之外的城市访问。

反向代理服务器缓存

将上游服务器中拿到的资源进行缓存

# 缓存路径。levels表示缓存目录的层数。keys_zone表示名称,其在内存中存储key。inactivate表示缓存多久未被访问后会删除
proxy_cache_path /nginx_tmp levels=1:2 keys_zone=test:100m inactivate=1d max_size=100g;
server {
    location / {
        proxy_pass http://abc;
        add_header Nginx-Cache "$upstream_cache_status";
        proxy_cache test; # keys_zone
        proxy_cache_valid 1h; # 缓存有效期,超时后会重新向上游服务器请求
    }
}

清理插件:proxy_cache_purge

strace

strace命令是一个集诊断、调试、统计于一体的工具,可用来追踪调试程序。

匿名location和return

error_page 404 = @666;
# 匿名location
location @666 {
    # 指定content type,从而让浏览器显示而不是去下载
    add_header Content-Type 'text/html';
    return 200 'hello world';
}

限速

请求限速

# 每个请求的地址 1s内只能请求1次,内存空间10m作为缓冲区使用。漏桶算法
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
    location / {
        # 名称为one,和上面配置的对应。burst表示桶的大小,nodelay表示桶满后,所有请求快速失败,即返回错误,而不是等待进入桶
        limit_req zone=one burst=5 nodelay;
    }
}

带宽限速

location / {
    # 令牌桶算法,限制流出速度
    limit_rate_after 1m; # 在1m之后开始限速
    limit_rate 1k; # 限速1k/s
}

并发数限制

limit_conn_zone $binary_remote_addr zone=two:10m;
server {
    location / {
        # 名称为two,只允许1个并发
        limit_conn two 1;
    }
}

upstream重试机制

被动式重试

upstream abc {
    # 10s内失败5次就下线;下线10s后给一次机会上线
    server 192.168.0.11:80 max_fails=5 fail_timeout=10s;
    server 192.168.0.12:80;
}
location / {
    proxy_next_upstream error timeout; # 指定发生error或超时时,进行重试
    proxy_next_upstream_timeout 15s; # 重试过程中的总时间,如果超过15s则这次请求失败
    proxy_next_upstream_tries 5; # 重试5个机器
    proxy_pass http://abc;
    root html;
}

主动式重试:需要使用商业版或者第三方如Tengine

一些配置项解释

http下的配置

  • keepalive_timeout:在两次请求之间保持打开状态,若在超时时间内有其他请求过来,则复用它,并重新计时。
  • send_timeout:响应请求时的超时时间,超时后关闭连接。和keepalive_timeout会有冲突,如果该值设置过小,可能导致keepalive_timeout没用,因为响应超时导致连接被关闭了。
  • keepalive_time:限制keepalive保持连接的最大时间。
  • proxy_set_header X-Forwarded-For $remote_addr;:将客户端IP写入header中,使得上游服务器能拿到客户端的真正IP

参考

AB测试

尚硅谷Nginx教程

posted @ 2023-09-02 20:49  sjmuvx  阅读(4)  评论(0编辑  收藏  举报