nginx反向代理
反向代理(reverse proxy)
实现动静分离,后端交给tomcat等处理
两种代理级别:
- 7层反向代理
- 4层反向代理,也叫负载均衡
反向代理含义:
指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。Nginx除了可以在企业提供高性能的web服务之外,另外还可以将nginx本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能
5种代理模块:
| 模块 | 说明 |
|---|---|
| ngx_http_proxy_module | 将客户端的请求以http协议转发至指定服务器进行处理 |
| ngx_http_upstream_module | 用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组 |
| ngx_stream_proxy_module | 将客户端的请求以tcp协议转发至指定服务器处理 |
| ngx_http_fastcgi_module | 将客户端对php的请求以fastcgi协议转发至指定服务器助理 |
| ngx_http_uwsgi_module | 将客户端对Python的请求以uwsgi协议转发至指定服务器处理 |
nginx代理和lvs的区别:
- nginx代理主机是中间人,客户端请求代理机,代理机自己重新构建请求报文,发给服务器。服务器响应给代理主机,代理主机接收后,自己重新构建响应报文,发送给客户端。client到server之间,不会知对方真实面目
- lvs是工作在四层的,只能对ip和端口做出修改,不能处理报文的内容。且直接由客户端请求服务器,或服务器直接响应客户端,报文内容没有修改过。client到server之间,知道双方真实面目
nginx的7层反向代理:
http {
upstream name {
...
}
server {
location / {
proxy_pass name;
}
}
}
基础反向代理(仅支持http协议):
官方文档: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
配置参数:
proxy_pass [http://]代理; 设置被代理的后端服务器,可以是主机名、ip:port,主机群(upstream)
例:设置被代理主机时,没有“/”为访问:1.1.1.10:8080/web的/web目录。有带“/”时,访问/web目录为直接访问:1.1.1.10:8080
location /web {
proxy_pass http://1.1.1.10:8080;
}
proxy_timeout 秒; nginx的转发超时时间
proxy_set_header 字段名 首部字段; 修改、添加客户端发往服务端的请求头部,主要在日志中记录
代理过程有四段: 报文传递
1、 客户端-->代理主机 不可修改报文
2、 代理主机-->服务器 可修改报文
3、 服务器-->代理主机 不可修改
4、 代理主机-->客户端 可修改报文
例: 实现服务端获取客户端真实ip
location /web {
proxy_pass http://1.1.1.10:8080;
proxy_set_header X-real-IP $remote_addr;
#X-real-IP是自定义首部参数名称,存放的客户端ip
}
proxy_hide_header 响应头部字段; 隐藏服务端的响应报文字段(大小写不敏感),可设置在http、server、location中
例: 隐藏服务端的响应报文的etag字段
location /web {
proxy_pass http://1.1.1.10:8080;
proxy_hide_header etag;
}
proxy_pass_header 响应首部字段; 默认隐藏后端服务器的:Date、Server、X-Pad、X-Accel等参数,如果需要把这些自动禁用的参数显示,用此声明后传递给客户端
例: 显示服务端响应报文的server和date字段
proxy_pass_header date;
proxy_pass_request_body on|off; 向后端发送http实体部分,用在http、server、location,默认开启
proxy_pass_request_headers on|off; 将客户端请求头部转发给后端,用在http、server、location,默认开启
proxy_connect_timeout 秒; nginx与后端尝试建立连接的超时时间,默认60s。超时返回504响应码
例:
proxy_connect_timeout 15s;
proxy_read_timeout 秒; nginx发起请求读取后端响应报文的等待超时时间,如果后端服务很忙,处理不过来请求,就要排队,该参数指定nginx和后端之间,重传响应报文的间隔,默认60s
proxy_send_timeout 秒; nginx向后端发起写请求后,等待超时时间,如后端没有在时间内处理nginx发来的请求,则关闭请求连接,默认60s
注意:real和send两项取决于后端服务器的性能水平,如果后端繁忙、客户端请求的文件很大时需要等待很久。根据生产场景配置,公司内部可以大一点,提供给用户访问时用户可能没60s的耐心(已经很长了)
proxy_http_version 1.0; nginx为后端服务器提供的http协议版本,默认1.0
proxy_ignore_client_abort off|on; 当用户访问时,但因网速慢关闭了浏览器,此时请求已经发起了,默认情况下nginx会在客户端中断请求后立即中断对后端服务器的请求,并立即记录日志499响应码,默认off关闭;on为即使用户中断了请求,nginx会忽略客户端中断,一直等待后端的执行结果返回
proxy_headers_hash_bucket_size 128; 为proxy_hide_header和proxy_set_header设置缓存大小,设置nginx保存http报文头的hash表缓存上限(nginx都是开辟的一段内存空间,存放hash后的缓存,以表的形式存在)
proxy_header_hash_max_size 512; 设置proxy_header_hash_bucket_size的最大可用空间
server_names_hash_buket_size 512; 监听的每个server_name申请的hash表空间大小
server_name_hash_max_size 512; 总的服务器名称hash表最大上限
实现代理缓存功能:
缓存功能默认关闭状态,需要先动配置才能启用
定义必须在http段,其他可用于http、server、location
配置参数:
expires 时间; 缓存有效期
proxy_cache_path 定义proxy的缓存功能,用在http段
proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [purger=on|off] [purger_files=number] [purger_sleep=time] ...;
常用选项解读:
path 磁盘上的路径,写了以后nginx自动创建
keys_zone=name:size 缓存名称:内存的缓存空间大小(存hash)。存放key和元数据(如使用次数)
levels=1:1:2: 目录下有几级子目录,每个目录用多少16进制的hash字符表示。每级目录用“:”隔开。1:2:2可存放100w多的目录
inactive=time 缓存的有效时间(存多久)
max_size=size 缓存使用磁盘空间最大值,超出后就是lru算法,最近最少使用清理
purger=on|off 启用缓存修剪功能,自动清理不常用的
purger_files= 一次修剪多少个文件
purger_sleep= 每隔多久修剪一次缓存
use_temp_path 是否使用临时目录
manager_files 每次管理进程移除缓存文件的数量
manager_threshold 每次移除缓存文件后的间隔
例:
proxy_cache_path /opt/nginx/proxy_cache levels=1:1:1 keys_zone=pcache:10m max_size=2g inactive=120s;
proxy_cache zone|off; 使用哪个缓存区域名,默认没有开启。
proxy_cache_key string; 缓存记录哪些内容
例:
#缓存整个url,定义时要考虑协议版本、域名解析、url内容(默认缓存这些)
proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_methods GET HEAD; 哪些方法请求时,缓存下来
proxy_cache_min_uses 1; 请求多少次相同的内容才会缓存下来,默认是请求一次就记录
proxy_cache_valid 响应码 时间; 为不同的响应码设置缓存时间。any为所有
注意: 当成功响应码设置时间较长时,后端的代码业务升级后需要把缓存都清掉,或者时间设短,否则容易出现依然拿缓存的旧内容响应客户端,新升级代码的不会正确显示
例: 总体缓存配置,进行压测
http {
proxy_cache_path /opt/nginx/pcache
levels=2:2:2
keys_zone=pcache:128m
inactive=180s
max_size=5g;
server {
location /proxy {
proxy_cache pcache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 301 302 1h;
proxy_cache_valid 404 1m;
#proxy_cache_valid any 3m;
}
}
}
例2: 缓存压测和非缓存压测
#准备压测文件
cat /var/log/message >> /opt/web/1.txt
cat /var/log/message >> /opt/web/proxy/2.txt
#第一次压测未使用缓存,总共2000请求,200个并发连接
ab -n 2000 -c 200 http://www.hj.com/1.txt
#第二此压测,使用缓存
ab -n 2000 -c 200 http://www.hj.com/proxy/2.txt
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | off ...; 后端服务器返回哪些状态时,nginx可用本地的缓存来响应客户端。默认不允许
缓存的内容包含通用首部、web内容
选项解读:
error 与后端建立连接、发送请求、读取响应头等出错时,使用缓存
timeout 与后端建立连接、发送请求、读取响应头等超时,使用缓存
updating 缓存内容过期时,由一个请求正在访问后端,试图更新缓存时,其他请求直接使用过期内容返回客户端
invalid_header 服务器的响应首部出现非法首部
http_500 服务器响应报文是500,则使用缓存内容做响应报文发给client。其他http_...一样效果
off 关闭,默认
例: 用于服务降级,哪怕是错误的也比没有页面返回
proxy_cache_use_stale error http_502 http_503;
proxy_cache_lock 第一次请求时没有该缓存,nginx会去找后端主机,第二次以后访问同样的资源,会直接使用之前的缓存
proxy_cache_lock_timeout 秒; 缓存的存储时间,失效后nginx把来的请求直接给后端主机
proxy_no_cache 满足条件的响应不会被保存到缓存中
缓冲相关配置
缓冲区配置是基于每个请求分配空间,并不是整体的共享空间,可根据业务的每个请求平均数据大小分配
缓冲区去减少及时传输带来的带宽消耗
配置
proxy_buffering on; #启用缓冲
proxy_buffers 4 64k; #为每个请求设置缓冲区的数量和大小,默认4 4k/8k
proxy_buffer_size 16k; #设置响应头缓冲区大小
proxy_busy_buffers_size 128k; #后端数据没有完全响应完时,允许将busy状态的缓冲返回给客户端。配置busy状态的缓冲大小,默认为proxy_buffer_size*2
proxy_temp_file_write_size 128k; #设置每次写数据到临时文件的大小限制
proxy_max_temp_file_size 1M; #临时缓冲文件最大容量
添加响应报文自定义首部:
基于模块ngx_http_headers_module
实现对后端服务器响应给客户端的报文中添加指定的响应首部字段,较少使用。主要是在报文中直接显示
用于http、server、location、if
官方文档:https://nginx.org/en/docs/http/ngx_http_headers_module.html
add_header 字段名 值 [always];
add_trailer name value [always]; 添加自定义响应信息的尾部,使用较少,1.13.2以后支持
例:
location /static {
proxy_pass http://1.1.1.10:80/;
proxy_cache pcache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;
proxy_set_header clientip $remote_addr;
add_header X-via $server_addr; #生产场景不建议公开ip
add_header X-fqdn $server_name; #生产场景可以公开主机名
add_header X-cache $upstream_cache_status;
#允许从其他域名访问过来
add_header Access-Control-Allow-Origin *;
}
反向代理高级功能:
http_upstream是运行在应用层的负载均衡模块。基于ngx_http_upstream_module模块,提供服务器分组转发、权重分配、状态检测、调度算法等高级功能
stream和stream_upstream是工作于3、4层的负载均衡
会话粘性相关
session sticky(会话粘性):
- source ip: lvs的sh算法,进行ip地址绑定
- cookie: 给http协议提供cookie,每个用户一个cookie,基于cookie绑定
session replication(会话复制):
- 应用服务器做一个集群,会话经过组播通信,组播内的主机都是复制会话
session server:
- 做内存级别的缓存
配置参数:
http {
upstream 名称 { 仅用于http段
server 服务器1 [选项];
server 服务器2 [选项];
其他参数;
}
}
选项:
weight=int; 设置权重,默认轮询算法,1
max_conns=num; 当前server的最大并发连接数(这台服务器只能处理多少个请求),默认0为无限制
max_fails=int; tcp健康检测连续失败多少次,标记为不可用(非周期性的)。默认1次,0为关闭
fail_timeout=time 对后端服务器的单次监测超时时间,默认为10秒
proxy_next_upstream=状态 指定在哪些检测状态下将请求转发给其他服务器,默认error、timeout
状态:
error 与后端建立连接、向后端传递请求或阅读响应头时发生错误
timeout 与后端建立连接、向后端传递请求或阅读响应头时发生了超时
invalid_header 后端服务器返回空响应或无效响应
http_500 后端服务器返回500的响应
http_... 其他响应码
non_idempotent
off 禁用将请求传递给下一台服务器
backup 将主机标记为备用状态,所有server挂了,就启用
down 手动标记主机为下线状态,算法也不会调度该主机了
resolve 当server定义的是主机名的时候,若A记录发生变化会自动应用新IP而不用重启Nginx(自动解析)
slow_start 缓慢调度。当原主机请求4000,新加入一台主机,调度时会缓慢把a主机的4000请求分配过来,一次一点的分
其他参数:
ip_hash; 源地址hash算法(地址绑定,实现会话保持)
hash key [consistent]; 比ip_hash更强大的选项。基于指定请求报文中首部字段(cookie、变量)或者URI等key做hash计算来进行绑定
consistent为使用ketama一致性hash算法,适用于后端是cache服务器(如varnish)时使用。不加时默认为取模法
least_conn; 最少连接调度算法,lc算法,加权重后是lvs的WLC算法
keepalive num; 当做客户端请求服务器时,不开启长连接就要消耗大量的套接字,开启长连接后,可让一个连接服务于多个请求。此处设置每个worker进程与后端服务器维持的长连接个数是多少
例:
hash建议用在缓存主机上,更加方便
upstream name {
hash $remote_addr; 绑定客户端ip,可实现ip_hash一样的功能
hash $cookie_name; 绑定cookie名称
hash $cookie_sessionid; 基于cookie中的sessionid这个key进行hash调度,实现会话绑定
hash $request_uri; uri哈希后,与权重总数取模,根据取模后的数字对应哪个主机,但在一台主机失效时,就有雪崩效应,所有缓存失效。此方法叫:取模法、映射法
hash $remote_addr consistent; consistent时某服务器失效,只会丢失uri计算模的最近的两台服务器缓存,不再是全部。此方法是:一致性哈希
}
例: 基于cookie实现会话绑定
upstream web {
hash $cookie_键;
server 1.1.1.10 weight=2 max_fails=3 slow_start;
keepalive 32; #默认保持32个持久连接与1.1.1.10主机
}
server {
...
proxy_pass http://web;
}
nginx的4层反向代理:
运用stream模块,只能代理4层协议(ip、port),可以通过代理端口实现http、https
功能与lvs相似
在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于DNS的域名解析,其配置方式和指令和http代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能
编译安装要开启--with-stream,配置时是单独的配置段
官方文档:
https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html
http://nginx.org/en/docs/stream/ngx_stream_upstream_module.html
stream {
#stream模块也有upstream参数,与http的upstream模块使用方法差不多,但两者并不是同一个东西
upstream 代理名 {
...
}
}
例1: 实现ssh随机分配
stream {
upstream sshbl {
server 1.1.1.10:22;
server 1.1.1.20:22;
#hash $remote_addr consistent;
}
server {
listen 222;
proxy_pass sshsr;
proxy_timeout 60s; nginx向服务器请求、响应的超时时间。默认10s
proxy_connect_timeout 10s; nginx与服务器之间的尝试连接的超时时间。默认60s;
}
}
例2: 实现web、dns的负载均衡
stream {
upstream dns {
server dns.hj.com:53;
server 1.1.1.10:533;
}
upstream web {
server 1.1.1.20 fail_timeout=30s max_fails=3;
server 1.1.1.30 fail_timeout=30s max_fails=3;
}
server {
listen 533 reuseport;
proxy_pass dns;
}
server {
listen 81;
proxy_pass web;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
}

浙公网安备 33010602011771号