nginx反向代理实践

来源:互联网 发布:大数据经济学 编辑:程序博客网 时间:2024/06/05 13:26

由于公司目前采用spring-boot微服务架构,每个应用会存在多个实例来保证可用性。而应用与应用之间的调用采用nginx作为桥梁来保证负载均衡。下面将生产上遇到的坑与解决方案分享出来,与大家一起讨论学习。

1、nginx模块
在http的应用中使用了:
ngx_http_upstream_module:负载均衡模块
ngx_http_proxy_module:服务向下转发模块

2、需求及初始配置
由于我们是支付系统,基本不允许交易失败。而某个实例确实会出现超时、错误的情况,在这种情况下我们可以让交易请求向下个实例转发。

upstream backend {    //当某个实例HttpResponse返回内容为proxy_next_upstream的值(下面简称为value)100次后,便将该实例    //移除出列表5s,等待5s后继续向该实例发送请求,如果返回非value,则该实例重新加入轮训列表。    //(起初我认为是在5s内有100次返回为value才移除列表)  server xxx:8080  weight=1 max_fails=100 fail_timeout=5s;   server xxx:8080  weight=1 max_fails=100 fail_timeout=5s;  server xxx:8080  weight=1 max_fails=100 fail_timeout=5s;}proxy_read_timeout 8s;//读取超时时间proxy_connect_timeout 60s;//请求连接超时时间(默认值为60s,这里是一个坑)proxy_next_upstream error invalid_header http_500 http_502 http_503 http_504;proxy_next_upstream_tries 3;//转发请求次数,包含第一次server {    location / {        proxy_pass http://backend;    }}

3、问题一

生产上有六个实例,分别部署在六台虚拟机上。某日对某台虚拟机A的配置升级,shutdown了机器。讲道理,按我最初的想法,本来该转发到A机器的六分之一请求应该会向下转发,但是并没有,导致当时几万笔交易失败。

问题分析:如果nginx在proxy_read_timeout时间内没有收到后端服务器的返回,那么按照proxy_next_upstream 的默认配置(error、timeout),超时的情况又将请求向下转发,导致重复交易。所以为了避免这种情况,我将value中的timeout去除了。又由于proxy_connect_timeout采用了默认值60s,在机器宕机的过程中,nginx在60s内是无法连接到该机器。我们系统与系统之间的调用超时一般是10s,所以上游系统调用nginx超时,而nginx根本没连接上服务器。

解决方案:
value中加上timeout,防止重复交易的机制在后端实现;
proxy_connect_timeout 2s;//nginx如果2s还没连接上后端服务器,那拜拜吧

4、问题二

某次公司网络变更,运维同事直接拔网线(这波操作我是服的),导致数据库(hbase)异常。

问题分析:我们设定后端应用连接hbase时会尝试3次,3次失败后返回。而当时很多连接都是失败的,时间超过了proxy_read_timeout,引发了向下转发功能,转发到下一台又是相同的情况。首先导致了当时资源很紧张,更要命的是产生了重复交易(与我们的防重机制有关)。

解决方案:
新增proxy_next_upstream_timeout 6s;//在一次请求中,超过6s就不转发了

待续

原创粉丝点击