nginx 负载均衡与反向代理(upstream)
nginx
作为负载均衡器主要应用upstream
这个模块
upstream 默认使用 Round-Robin
算法进行负载均衡,即依次加权轮询每个节点。
默认有以下 4 个配置项
权重,默认 1
server 的最大并发连接数 默认是 0,表示没有限制
在 fail_timeout 时间段内,最大的失败次数。当达到失败次数时,会在 fail_timeout 秒内这台 server 不允许再次被选择。
单位为秒,默认值为 10 秒。
指定一段时间内,最大的失败次数 max_fails
到达 max_fails 后,该 server 不再提供访问的时间。
该 server 为备用服务器当主服务器无效则请求会被转发到备用服务器
该 server 永久不可访问
upstream 开启针对上游 keepalive 长连接
keepalive 32; #最多开启多少个 keepalive 长连接 keepalive_requests; 100 #每个 keepalive 长连接最多可以发送多少条请求 keepalive_timeout 60s; #多少时间没有请求断开 keepalive 连接
其他的负载均衡算法
upstream 还支持很多其他的负载均衡算法,如ip_hash
开启ip_hash
直接在 upstream 中加入就 OK,这样来自同一 ip 的用户就会被转发到同一台 server 中
upstream firstCluster{ ip_hash; ... }
不仅可以根据 ip 进行 hash 负载均衡,还可以根据自定义值进行 hash 算法负载均衡,如下
upstream firstCluster{ hash $uri; ... }
一致性 hash 算法
在 hash 后加一个consistent
就开启了一致性 hash 算法负载均衡了!
upstream firstCluster{ hash $remote_addr consistent; ... }
最少连接数算法
在所有上游服务器中,找出并发连接数最少的一个,将请求发给它
upstream firstCluster{ least_conn; ... }
开启 upstream_zone 模块
分配出共享内存,将其他 upstream 模块定义的负载均衡策略数据,运行时每个上游服务的状态数据存放在共享内存上,以对所有 nginx worker 进程生效。
upstream firstCluster{ zone zone_name 16k; ... }
upstream 提供的变量
上游服务器的 ip 地址,格式为可读的字符串,例如 127.0.0.1:8080
与上游服务器建立连接消耗的时间,单位为秒,精确到毫秒
接受上游服务发回相应中 http 头部所消耗的时间,单位为秒,精确到毫秒
接受完整的上游服务响应所消耗的时间,单位为秒,精确到毫秒
从上游服务返回的响应头的值
从上游服务接受到的响应长度,单位为字节
从上游服务返回的响应包体长度,单位为字节
上游服务返回的 http 响应中的状态码。如果未连接上,该值为 502
从上游服务发回的响应头 Set-Cookie 中取出的值
从上游服务的响应尾部取到的值
反向代理配置参考
URL 必须以 http:// 或 https:// 开头,接下来是域名,IP,unix socket 地址或 upstream 的名字,前两者可以在后面加端口,最后是可选的 uri
如果加了 uri,则转发至上游的请求路径将会替换 location 所匹配的路径为设置的 uri
proxy_path http://127.0.0.1:8000;
转发至上游时所用的请求方式,如 GET|POST
转发至上游所使用的 http 版本, 如 1.0|1.1
转发至上游服务的请求头部,如 proxy_set_header Host $proxy_host;
是否将用户的请求头部发送给上游,默认是 on 一般不设置
是否将用户的请求包体发送给上游,默认是 on 一般不设置
接受客户端请求的包体,是否 nginx 收完包体,再转发至上游
设为 on 的话客户端网速较慢,上游服务并发处理能力低,适应高吞吐量的场景
设为 off 则有更及时的响应,降低 nginx 读写磁盘的消耗,一旦开始发送,proxy_next_upstream
功能失效
存在包体时,接受包体所分配的内存,若剩余待接受包体的长度小于 client_body_buffer_size,则分配所需大小
当关闭包体缓存时,该内存上的内容及时发送给上游服务,当打开包体缓存时,该段大小内存用完时,写入临时文件,释放内存
是否将所有客户端发送的包体放入内存中,默认关闭
最大包体长度限制 默认 1m 可以适当放大;
接受包体的临时文件路径
是否保存客户端上传的包体 默认 off
读取包体超时时间默认 60s,如果超过了,则返回 408 错误
与上游服务建立 tcp 连接的时间,超时之后返回 502
如果与上游服务没有建立连接,再换一台上游服务器
指定应将请求传递到下一个服务器的情况:
error # 与服务器建立连接,向其传递请求或读取响应头时发生错误;
timeout # 在与服务器建立连接,向其传递请求或读取响应头时发生超时;
invalid_header # 服务器返回空的或无效的响应;
http_500 # 服务器返回代码为 500 的响应;
http_502 # 服务器返回代码为 502 的响应;
http_503 # 服务器返回代码为 503 的响应;
http_504 # 服务器返回代码 504 的响应;
http_403 # 服务器返回代码为 403 的响应;
http_404 # 服务器返回代码为 404 的响应;
http_429 # 服务器返回代码为 429 的响应;
non_idempotent # 通常,请求与 非幂等 方法(POST,LOCK,PATCH)不传递到请求是否已被发送到上游服务器的下一个服务器; 启用此选项显式允许重试此类请求;
off # 禁用将请求传递给下一个服务器。
可多选 如 proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
连接下一台服务的超时时间
尝试连接下一台服务的次数
与上游服务是否进行探测 默认 off
修改 tcp 连接中的 local address
当客户端 abort 了请求之后,是否忽略关闭上游的连接
转发请求的超时时间,默认 60 秒
接收上游服务的 http 头部的最大大小,建议设置大一些!
是否接收完完整的包体再发送
设置接受上游包体的内存空间,如 proxy_buffers 8 32k;
限制写入磁盘中文件的最大值 默认 1024m
每一次向磁盘中写入的字节数
写入文件的地址
及时转发包体的大小
接受上游响应的超时时间
限制读取上游的响应的速度
是否将上游响应内容存起来,做持久化,默认关闭 如果是 string 类型的,则表示文件存放的位置,如果是 on,文件则会存储在生效的 nginx root 目录下
上游响应内容存下来之后的权限
对于上游的某些 header,设置不向客户端转发
nginx 默认不转发以下响应 header:
1.Date:nginx 发送响应头部的时间
2.Server:nginx 的版本
3.X-Pad:apache 为避免浏览器 bug 生成的头部
4.X-Accel-:控制 nginx 行为的响应,不需要向客户端转发
对于已经 hide 的 header 头部,设置向客户端转发
修改 cookie 的域名
修改 cookie 的 path
如果上游有 location,则在这里进行替换,默认不替换
当上游响应的响应码大于等于 300 时,应将响应返回客户端还是按照 error_page 指令处理,默认 off,直接返回客户端,不会做 error_page 处理,如上游没有做错误重置,建议打开
对上游服务使用 ssl 连接
nginx 可以向客户端提供 ssl 访问,也可以以 ssl 访问上游服务,具体设置如下图
以上两个配置是 nginx 作为 server 端,要向下游发送的证书,只能放在 http 或 server 段中。
默认 off
以上两者为配置是否验证下游证书
以上两者是对上游使用 ssl 证书的配置,可以放入 location 段中!
如果需要对上游使用 ssl 连接,proxy_path
的 url 需要填写为https://...
ssl 模块也提供了很多变量可供使用
ssl_cipher
:本次通讯选用的安全套件,例如 ECDHE-RSA-AES128-GCM-SHA256
ssl_ciphers
:客户端支持的所有安全套件
ssl_protocol
:本次通讯所用的 tls 版本,例如 TLSv1.2
ssl_curves
:客户端支持的椭圆曲线,例如 secp384r1:secp521r1
ssl_client_raw_cert
:原始客户端证书内容
ssl_client_escaped_cert
:返回客户端证书做 urlencode 编码后的内容
ssl_client_cert
:对客户端证书每一行内容前加 tab 制表符空白,增强可读性。
ssl_client_fingerprint
:客户端证书的 sha1 指纹
ssl_server_name
:通过 TLS 插件 SNI 获取到的服务域名
ssl_client_i_dn
:依据 RFC2253 获取到证书 issuer dn 信息,例如:CN=…,O=…,L=…,C=…
ssl_client_i_dn_legacy
:依据 RFC2253 获取到证书 issuer dn 信息,例如:/CN=…/O=…/L=…/C=…
ssl_client_s_dn
:依据 RFC2253 获取到证书的 subject dn 信息,例如:CN=…,OU=….,O=….,L=….,ST=…,C=…
ssl_client_s_dn_legacy
:依据 RFC2253 获取到证书的 subject dn 信息,例如:/CN=…/OU=…./O=…./L=…./ST=…/C=…
ssl_client_v_end
:返回客户端证书的过期时间,例如:Dec 1 11:56:11 2028 GMT
ssl_client_v_remain
:返回还有多少天客户端过期,例如针对上面的 ssl_client_v_end 还有 3649
ssl_client_v_start
:客户端证书的颁发日期,例如: Dec 4 11:56:11 2018 GMT
ssl_client_serial
:返回连接上客户端证书的序列号,例如:8BE947674841BD44
ssl_early_data
:在 TLS1.3 协议中使用了 early data 且握手未完成返回 1,否则返回空字符串
ssl_client_verify
:如果验证失败为 FAILED:原因,如果没有验证证书为 NONE,验证成功则为 SUCCESS
ssl_session_id
:已建立连接的 sessionid
ssl_session_reused
:如果 session 被复用则为 r,否则为.
如果您使用 linux 则可以用 openssl 创建 ssl 证书
创建 ssl 证书