AWS ELB 服务的坑

默北 web应用325,9868字数 2225阅读7分25秒阅读模式

目前发现AWS ELB服务有两个大坑:

  1. 基于HTTP的负载均衡频繁504,直接是ELB返回的,后端根本就没接收到请求。
  2. 基于TCP的负载均衡没法获取到客户端IP地址。

 文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

TCP 负载均衡其实是把客户端的请求截断,然后自己发送一个请求给后端,拿到后端返回的数据之后再返回给 客户端,这样后端看到的是 负载均衡器的IP,看不到客户端的真实IP了 (如果用基于HTTP的Load Balancer,会自动在HTTP头记录 X-Forwarded-For , 后端自然很容易获取到源IP )。其实这和LVS FULLNAT 模式有点像,LVS FULLNAT的解决办法是把真实IP写在TCP option里面,然后后端用toa模块拿到。文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

对于这个问题,AWS给了一个解决办法,叫做  Proxy Protocol ,可以对TCP 负载均衡器开启Proxy Protocol,它会在请求的第一行写入 源IP、源端口等信息,以 \r\n 结尾,格式如下:文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

PROXY_STRING + single space + INET_PROTOCOL + single space + CLIENT_IP + single space + PROXY_IP + single space + CLIENT_PORT + single space + PROXY_PORT + “\r\n”文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

开启 Proxy Protocol

第一步,为集群 ProxyProtocolTest  创建一个Proxy Protocol,叫 EnableProxyProtocol文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

# aws elb create-load-balancer-policy –load-balancer-name ProxyProtocolTest –policy-name EnableProxyProtocol  –policy-type-name ProxyProtocolPolicyType –policy-attributes AttributeName=ProxyProtocol,AttributeValue=True

第二步,为 ProxyProtocolTest  激活 EnableProxyProtocol文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

# aws elb set-load-balancer-policies-for-backend-server –load-balancer-name ProxyProtocolTest –instance-port 80 –policy-names EnableProxyProtocol

然后确认开启文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

# aws elb describe-load-balancers –load-balancer-name ProxyProtocolTest

可以看到类似下面的字段:文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

 “BackendServerDescriptions”: [
                {
                    “InstancePort”: 80,
                    “PolicyNames”: [
                        “EnableProxyProtocol”
                    ]
                }
            ]

关闭Proxy Protocol

# aws elb set-load-balancer-policies-for-backend-server –load-balancer-name ProxyProtocolTest –instance-port 80 –policy-names “[]”

获取客户端IP

开启Proxy Protocol之后,看看后端如何获取到源IP,这里只看nginx文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

nginx 从1.5.12 版本开始支持Proxy Protocol ,只需要配置一下就OK了,说说怎么配。文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

第一部分,在http 里面配置如下:文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

set_real_ip_from   172.0.0.0/8;
real_ip_header     proxy_protocol;

表示把来在172.0.0.0/8 段(TCP负载均衡器的IP段)的所有请求的来源地址,都改成 $proxy_protocol_addr,并且记录在 $remote_addr 变量里。文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

log_format  main  ‘$proxy_protocol_addr $remote_addr – $remote_user [$time_local] '
                   “$request” $status $body_bytes_sent “$http_referer” ‘
                      ‘”$http_user_agent” “$http_x_forwarded_for” ‘
                      ‘”$upstream_addr” “$request_time” “$upstream_response_time” '
                      ' “$upstream_cache_status”‘;

这是日志格式。文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

第二部分,在server里面linsten的时候开启 proxy_protocol文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

 listen      80  proxy_protocol;

此时我请求的时候,日志刷出来了,这里可以看到 $proxy_protocol_addr  和 $remote_addr  都是客户端源IP。文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

202.134.72.73 202.134.72.73 – – [09/Oct/2014:08:00:12 -0400] “GET / HTTP/1.1″ 200 0 “-” “curl/7.30.0″ “-” “-” “0.000” “-” “-“文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

参考:https://gist.github.com/pablitoc/91c40d820f207879969c文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

http://docs.aws.amazon.com/zh_cn/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/ 文章源自运维生存时间-https://www.ttlsa.com/web/hang-aws-elb-services/

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
默北
  • 本文由 发表于 29/07/2015 01:00:59
  • 转载请务必保留本文链接:https://www.ttlsa.com/web/hang-aws-elb-services/
  • aws
  • ELB
  • nginx
  • proxy_protocol
评论  3  访客  3
    • 小霸
      小霸 1

      长点时间的ajax一直报504错误怎么解决?

        • 默北
          默北

          @ 小霸 查看日志,超时了

            • 小霸
              小霸 1

              @ 默北 增加keepAliveTimeOut的时间就好了,thx

        评论已关闭!