ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

HAProxy七层代理实战:从负载均衡原理到ACL动态路由配置详解

HAProxy七层代理实战:从负载均衡原理到ACL动态路由配置详解 1. 七层代理到底解决了什么问题先说个实际场景。之前帮某公司做一套内部业务系统后端就三台应用服务器一开始用的轮询DNS哪台挂了不知道流量还经常打偏一到高峰期总有那么一两台撑不住另外两台闲着看热闹。后来就是靠部署HAProxy七层代理把这些乱象一次性理顺的。HAProxy是目前生产环境里用得最多的高性能负载均衡软件之一所谓“七层代理”指的是它工作在OSI模型的第七层也就是HTTP/HTTPS应用层。跟四层代理最大的区别在于四层代理只看数据包里的IP和端口拿到连接就转发不关心你访问的是哪个域名、哪条路径、带了什么Cookie七层代理则会把HTTP请求完整拆开来看拿到URL、Header、Cookie、请求方法甚至请求体里的关键字段然后根据这些信息决定把这个请求转发给哪个后端。说白了一句四层代理是快递分拣员只看包裹上的地址七层代理是挂号导诊台会问你是哪里疼、挂哪个科把你送到对应的医生面前。那这个能力到底适合谁如果你只是两台服务器做高可用四层方案其实也够用但如果你的业务里面有多个域名共用一台入口、有不同路径要转发给不同服务、有像 /api 和 /static 这样的动静分离、需要根据请求头里的版本号做灰度路由这时候七层代理基本就是最优解。HAProxy在这块的优势一是性能极强单实例轻松扛住每秒几万请求二是配置灵活ACL规则写起来像写业务代码一样顺手三是稳定性经过大规模生产环境检验我用了这么多年还没见过HAProxy自己崩掉的场景。2. 方案选型为什么是HAProxy而不是其他负载均衡器2.1 HAProxy、Nginx、LVS三者怎么选很多刚接触负载均衡的读者都会问这个问题同样是做流量分发Nginx不是也能做七层代理吗LVS在四层领域不也很强吗为什么偏偏选HAProxy我自己的使用体会是这样的。LVS工作在四层性能确实是天花板级别的但它有个天然短板不解析HTTP层想做七层路由、域名分发、路径匹配这些业务逻辑基本无能为力。而且LVS配置多、规则多架构上还要引入额外的Director节点日常维护成本比HAProxy高不少。Nginx做七层代理当然可以很多团队也确实在用。但Nginx本身的定位是Web服务器代理能力是它的扩展技能。在负载均衡这个专项场景里HAProxy有几点是Nginx比不了的HAProxy原生支持配置热加载改完配置直接执行reload命令几乎零中断地切换配置不需要像Nginx那样小心地执行nginx -s reload还要担心worker进程的日志句柄问题。HAProxy的统计信息页面开箱即用还能通过socket接口实时调整权重、下线后端、查看连接数运维操作非常方便。健康检查类型丰富可以配置几十种检查方式从简单的TCP探测到复杂的HTTP关键字匹配、LDAP检查、Redis协议检查都能做。会话保持机制做得细基于Cookie的会话粘滞、基于来源IP的哈希、基于URL的哈希选择面远比Nginx宽。当然Nginx在缓存、静态文件处理、脚本扩展这些领域有自己的优势。我通常的建议是如果你需要的是缓存或复杂的请求重写可以考虑Nginx如果核心诉求就是高并发流量分发给后面的应用服务器HAProxy是更纯粹的“专业选手”配置更清晰排查问题也更容易。2.2 版本选择与部署方式的影响HAProxy从2.0开始引入了不少重要特性比如HTTP/2支持、PROMEX指标暴露、多线程模型优化等。到2.4、2.6、2.8这些版本七层代理能力和性能一直在增强。我跟你说句实在话对于生产环境建议直接选2.4以上的稳定版本别在老版本上纠结。一个很重要的原因是2.4之后配置里支持了纯环境变量替换可以在global段用setenv/getenv指令配合运行时环境变量来管理配置差异这让配置的复用和环境迁移方便了一大截。部署方式上最常见的两种是裸机直接装二进制包或系统包以及用容器跑HAProxy。容器化部署最大的好处是配置变更可以通过镜像版本控制回滚很直接但要注意容器里跑HAProxy时一定要把系统文件描述符限制打开很多人在容器里遇到文件句柄耗尽就是因为没做这个操作。裸机部署则更适合那种追求极致性能、网络绑定比较复杂的场景。另外一个常被忽略的点是HAProxy处理七层代理时最核心的优化点不在HAProxy进程本身而在它后面的操作系统网络栈。比如tcp_tw_reuse、tcp_fin_timeout、somaxconn这些内核参数直接决定了HAProxy能否扛住高并发短连接的压力。简单说配置层面做好还不够系统层面同样得配合这部分我会在后面的实操段落里给出具体的参数。3. 核心配置术语与参数深解先花点篇幅讲清楚HAProxy配置里的几个核心“区块”这是所有七层代理配置的基础你熟悉了之后再看任何一份HAProxy配置都能快速上手。3.1 frontend、backend、listen的关系HAProxy七层代理配置通常分成三段global段、defaults段以及frontend/backend段落。global段是进程级配置比如日志、线程数、运行用户、最大连接数。defaults段是默认参数的模板后面所有frontend和backend都会继承这里的设置适合统一设置超时时间、模式等。frontend段定义入口监听客户端连接解析HTTP然后根据ACL规则决定把请求转发到哪个backend。backend段定义后端服务器池包括服务器列表、负载均衡算法、健康检查方式等。实际配置里还有一种listen段它是frontend和backend的结合体适合端口和用途都比较单一的简单场景。但做七层代理尤其是有多个域名、多个路径、多个后端池的复杂业务我更推荐把frontend和backend分开写逻辑清晰得多。当你后面需要新增一个域名路由时只需要在frontend里加几条ACL然后加一个backend段不需要动其他配置。3.2 mode http与七层代理模式的关键设置HAProxy最核心的一句配置就是mode。默认情况下如果没写mode会继承defaults里的设置很多新手容易踩这个坑——defaults里忘了写mode结果前置的七层ACL规则完全不生效。做七层代理必须明确设置mode http。mode http会启用HTTP解析引擎这时候你可以用path、hdr、url、method这些关键字来写ACL规则。比如frontend web_front bind *:80 mode http use_backend app_backend if { path_beg /api/ }这里path_beg就是路径前缀匹配意思是请求路径以 /api/ 开头时转发到app_backend后端。没有mode http这种规则是写不出来的因为四层模式下HAProxy根本不解析HTTP报文。还有一个容易被忽略的配置option httplog。这个选项会让HAProxy按照HTTP格式输出访问日志里面包含请求方法、路径、状态码、响应时间、前后端连接信息这些信息在排查问题的时候价值极高。我见过有些部署为了省日志空间把这个关掉的真出问题时完全无从下手我强烈建议必须开着。通过log global配置把日志交给系统syslog然后用httplog格式输出排查问题时你会感谢当初开启了这个选项。3.3 超时参数与连接复用七层代理里最容易让人困惑的就是各种超时时间。HAProxy里的超时主要分三类timeout connect连接后端服务器的超时时间一般设置5秒左右比较合理。如果后端在网络层面就比较慢可以适当调大但不要超过10秒否则用户体验会很差。timeout client与客户端连接之间空闲状态的超时时间默认可以设60秒配合HTTP长连接使用。timeout server与后端服务器连接之间空闲状态的超时时间通常要跟后端的处理节奏匹配比如后端要跑大查询、导出报表这个就适当调大比如300秒。超时设置的核心原则客户端超时要比服务器超时长否则后端还在处理请求客户端这边等不及先断了后端白忙活一场。典型的问题场景是应用导出报表后端要算两分钟客户端超时设了30秒结果前端一直报网关超时后端实际还在算。这就是典型的超时配置未对齐问题。另外如果想优化连接性能可以开启option http-keep-alive并配合connection复用参数。默认情况下HAProxy每处理完一个请求就可能关闭连接如果业务里大量请求是短连接、请求频率高频繁握手会浪费大量CPU和网络资源开启连接复用之后性能提升非常明显。4. 七层代理核心玩法ACL规则与动态路由4.1 ACL到底怎么用ACL全称Access Control List在HAProxy里就是一组匹配规则用来描述“什么样的请求满足什么样的条件”。七层代理的灵魂就在这——ACL规则写得好不好直接决定你的路由逻辑是否灵活。常见的ACL类型包括基于路径匹配path_beg前缀、path_end后缀、path_reg正则基于域名匹配hdr(host) 精确匹配、hdr_beg(host) 前缀匹配、hdr_reg(host) 正则基于方法匹配method GET / POST / PUT基于来源IPsrc 匹配来源地址基于请求头hdr_user-agent、hdr_referer等等基于Cookiecookie(name) 匹配Cookie字段一个典型的场景某个业务系统要按请求路径分流前端静态资源走静态服务器后端API走应用服务器上传管理功能走单独的文件服务。配置长这样frontend web_front bind *:80 mode http option httplog acl is_static path_beg /static /images /css /js acl is_api path_beg /api/ acl is_upload path_beg /upload use_backend static_pool if is_static use_backend api_pool if is_api use_backend upload_pool if is_upload default_backend web_pool这一段配置读起来几乎跟自然语言一样维护成本极低。新同事接手也只要照着原有的ACL样式加几行就行不需要理解复杂的路由表逻辑。ACL还能组合判断比如“来源IP是内网网段并且路径是 /admin/ 的请求才允许访问管理后台”写法是acl is_admin_net src 10.0.0.0/8 acl is_admin_path path_beg /admin/ use_backend admin_pool if is_admin_net is_admin_path这里两个ACL之间是“与”关系都满足才命中。如果想要“或”关系就用or连接HAProxy的ACL组合逻辑非常灵活这也是它相比其他方案的优势所在。4.2 请求重写与Header操作七层代理不仅要会“转发”还要能“改造”。实际业务里最常见的三个改造需求改写Host头、插入客户端真实IP、添加安全头。先说Host头。当后端多个虚拟主机共用一个IP时后端服务器根据Host头来区分。如果你的前端HAProxy和后面的Nginx之间没有做Host头透传后端拿到的Host就是前端代理的地址或默认的IP业务可能直接报错。HAProxy里配置是backend app_backend server web1 10.0.1.11:8080 check http-request set-header Host myapp.example.com再就是X-Forwarded-For头。后端应用经常要记录客户端真实IP而代理转发之后默认TCP连接里看不到原始来源IP。要在HAProxy层开启option forwardfor让HAProxy在请求头中插入X-Forwarded-For后端应用取这个Header就能拿到真实IP。需要提醒的是option forwardfor默认会保留客户端已经存在的X-Forwarded-For字段如果客户端伪造了这个头后端拿到的可能不是真实IP。生产环境如果对来源IP要求比较严格建议用if-none参数强制覆盖option forwardfor except 127.0.0.1 header X-Real-IP这句的意思是除了本机访问之外统一覆盖X-Real-IP头的值避免伪造。4.3 灰度发布和AB测试的天然帮手HAProxy的ACL规则直接支持灰度发布。最常用的两种方法按来源IP的网段灰度以及按URL参数或Header标记灰度。比如要上线新版本的订单系统老版本是old_pool新版本是new_pool希望先把公司内部员工和某个测试合作方的流量导入新版本。配置是这样acl is_employee src 10.0.10.0/24 acl is_partner src 192.168.88.0/24 acl is_new_ver hdr(beta-version) -i v2 use_backend new_pool if is_employee use_backend new_pool if is_partner use_backend new_pool if is_new_ver default_backend old_pool这种做法的好处是当新版本出问题时只需要把这几条ACL注释掉执行一次reload流量就全部切回老版本。灰度发布的核心诉求就是“快上快下”HAProxy这种方式比改应用代码、改DNS都可靠得多。按比例灰度也可以用HAProxy实现最简单的方式是用random算法配合weight权重。比如新版本后端server只分配5的权重老版本分配95权重balance random server old1 10.0.1.10:8080 weight 95 server new1 10.0.1.20:8080 weight 5这种按权重的灰度方案适合那种无法用IP或Header精准圈定用户范围的场景操作直观便于随时调整。5. 完整实操一个可落地的七层代理配置5.1 场景设定与整体拓扑为了把这个技术讲透我拿一个实际项目来做示例。假设有个电商业务系统后端有三组服务静态资源服务图片、CSS、JS跑在三个Nginx节点上端口80API服务HTTP接口跑在两个Tomcat节点上端口8080管理后台独立的Web应用跑在两个节点上端口7001还有一个需求出于审计要求管理后台只能允许内网IP访问。同时需要把客户端真实IP传给后端API服务。这个场景基本把七层代理的常见需求都覆盖了域名转发、路径分流、IP限制、Header改写、健康检查、负载均衡算法。5.2 完整配置与每段含义解析直接上完整配置我每一步都加了注释和说明global log /dev/log local0 info maxconn 100000 nbthread 4 user haproxy group haproxy stats socket /run/haproxy/admin.sock mode 660 level admin defaults mode http timeout connect 5s timeout client 60s timeout server 300s option httplog option dontlognull option forwardfor frontend web_front bind *:80 bind *:443 ssl crt /etc/haproxy/cert.pem maxconn 30000 default_backend static_pool # 按Host头识别不同域名 acl api_host hdr(host) -i api.example.com acl admin_host hdr(host) -i admin.example.com acl static_host hdr(host) -i static.example.com # 按路径识别API acl api_path path_beg /api/ # 管理后台限制内网 acl admin_net src 10.0.0.0/8 192.168.0.0/16 # 路由决策 use_backend api_pool if api_host OR api_path use_backend admin_pool if admin_host admin_net use_backend static_pool if static_host backend api_pool balance roundrobin option httpchk GET /healthz server api1 10.0.2.11:8080 check inter 3s fall 2 rise 3 server api2 10.0.2.12:8080 check inter 3s fall 2 rise 3 backend admin_pool balance leastconn option httpchk GET /admin/login server admin1 10.0.3.11:7001 check inter 5s fall 3 rise 2 weight 1 server admin2 10.0.3.12:7001 check inter 5s fall 3 rise 2 weight 1 backend static_pool balance source hash-type consistent option httpchk GET / server static1 10.0.4.11:80 check inter 2s fall 2 rise 2 server static2 10.0.4.12:80 check inter 2s fall 2 rise 2 server static3 10.0.4.13:80 check inter 2s fall 2 rise 2 listen stats bind 127.0.0.1:8404 stats enable stats uri /stats stats refresh 5s stats auth admin:yourpassword这个配置里几个关键点需要展开讲一下。首先是global段的nbthread 4指的是启动4个线程来处理请求。注意这个值不是越大越好建议跟机器的物理核数对齐或者略微小于核心数。之前在生产上遇到过一个案例一台32核机器把nbthread设置成32结果CPU跑满但吞吐率反而下降因为线程切换开销过高了后来调整到16才恢复正常。然后是defaults里的option dontlognull这个选项很有用它会让HAProxy不记录“健康检查”之类的空连接日志减少日志噪音。如果不加这个健康检查产生的刷屏日志会淹没真正有价值的访问日志查问题时特别烦。再说到frontend里的bind *:443 ssl crt这是HTTPS终止。HAProxy可以直接终止SSL然后以HTTP方式转发给后端这样后端的应用就只需要处理HTTP请求SSL证书的管理集中在前端一个入口省事很多。正式环境证书需要注意定期续期我用的是脚本配合定时任务检查证书过期时间过期前自动重新加载HAProxy配置。5.3 负载均衡算法的选择逻辑配置里三个后端池我用了三种不同的算法这不是随便选的背后各有道理。api_pool用的是roundrobin也就是轮询每个请求按顺序轮流分发到后端节点。这个算法适合后端各节点性能相近、接口耗时相对平均的场景实现简单、分布均匀度好。admin_pool用的是leastconn最小连接数。管理后台有个特点用户登录后长时间保持HTTP连接会话停留在某台节点上。如果还沿用轮询新建连接会固定散到不同节点上但旧用户的连接全集中在一台机器上就会造成负载不均。leastconn会优先把新连接分配到当前活跃连接数最少的节点对长连接场景非常友好。这里管理员用户量不算大用leastconn基本是最佳选择。static_pool用的是source算法加一致性哈希。source算法是按客户端IP哈希同一个IP的请求始终落到同一台后端节点这对静态资源来说能充分利用节点本地缓存缓存命中率明显上升。加hash-type consistent是为了避免节点增减时大量请求重新映射。静态资源场景下缓存命中率直接影响响应速度和后端压力所以这个选择是从实战出发的。如果你拿不准该用哪种算法默认从roundrobin开始是比较稳妥的。等观察一段时间访问日志和节点负载分布后再根据实际情况调整成leastconn或source。5.4 健康检查参数详解健康检查是负载均衡里绝对不能省略的环节。没有健康检查某台后端宕机了流量照样发过去用户的请求直接超时等到你发现线上问题业务早就受了损失。配置里我写了option httpchk GET /healthz意思是HAProxy定期以GET方式请求这个路径只要返回状态码在2xx—3xx范围就认为节点健康。这个健康检查路径很有讲究建议后端专门实现一个轻量级健康检查接口这个接口不仅要检查进程还活着还要检查依赖的数据库连接池、缓存连接是否正常。有些团队直接用首页当作健康检查路径这其实隐患很大——进程还在但数据库连接池满了首页还能返回健康检查却误判为健康流量照样灌进去直到用户侧真正报错才发现问题。再说inter、fall、rise这三个参数。inter是健康检查间隔我API池设了3秒。间隔太短会增加后端不必要的压力一个健康检查请求虽然轻量但节点多的时候累计起来也很可观间隔太长又会让故障感知变慢。生产经验是2~5秒之间比较合理。fall是连续几次失败就判定节点故障rise是连续几次成功就判定恢复。这两个参数需要平衡设得太小容易误判比如节点一次GC停顿时间稍长触发了超时就立刻被摘除影响稳定性设得太大又会让故障转移变慢。常规推荐是fall 2~3rise 2~3。5.5 reload与平滑切换HAProxy做大版本配置修改后不需要重启进程只需要执行reload命令。这是HAProxy相比其他同类型工具很省心的地方之一。在systemd环境下执行haproxy -f /etc/haproxy/haproxy.cfg -c systemctl reload haproxy第一行是检查配置语法如果配置有问题会直接报错此时不能执行第二行。实际生产操作中我通常把这两句放在一个脚本里先检查配置语法通过后再执行reload。这样无论谁去操作服务器都不会因为手误把错误配置加载上去导致服务中断。reload过程的原理是HAProxy主进程会启动一个新的子进程加载新配置老的子进程继续处理已有连接等所有老连接处理完毕后才退出。这意味着reload操作对用户几乎是无感知的不会造成在线连接的闪断。这里有个细节要注意如果老的子进程有大量长连接一直不关闭它就会一直不退出导致系统里堆积大量残留进程。这种场景下建议配合timeout server http-keep-alive设置一个合理的超时避免连接无限期占用。6. 高级功能与常见问题排查6.1 会话保持的三种方式HTTP业务里经常需要把同一个用户的请求固定分发到同一台后端服务器特别是登录状态存在本地内存里的老系统。HAProxy实现会话保持有几种方式我按推荐程度排序介绍。第一种是基于Cookie插入。HAProxy会在响应里给客户端种一个带路由信息的Cookie后续请求带上这个Cookie时HAProxy就根据Cookie里的路由标记把请求转发到最初处理会话的那台后端。配置是这样的backend api_pool cookie SERVERID insert indirect nocache server api1 10.0.2.11:8080 check cookie s1 server api2 10.0.2.12:8080 check cookie s2这种方式的优势是精准不受IP变化影响劣势是需要后端应用配合Cookie处理有些前后端分离的应用会自己管理Cookie需要沟通排除冲突。第二种是IP哈希就是前面static_pool用过的source算法。只需要配置balance source一键生效。缺点是客户端出口IP如果变化比如4G网络切换基站导致IP变化会话就会漂移。所以这种方案适合局域网内的B端业务不太适合移动互联网场景。第三种是基于Cookie的值做哈希比如按用户ID字段做哈希。这种方式不需要后端显式管理路由Cookie但要求请求里有可用的标识字段比如通过hdr(cookie)提取用户ID。如果用户清掉了Cookie哈希值就没了会话也就保不住了。生产里怎么选核心看业务对“会话丢失”的容忍度。如果登录状态丢失会造成明确损失建议优先用Cookie插入如果只是希望同一用户的静态请求尽量落在同一台节点上IP哈希就够用了。6.2 后端获取不到客户端真实IP怎么办这个坑我在排查线上问题时遇到太多次了。现象是后端应用查看访问日志时REMOTE_ADDR全是HAProxy节点的内网IP看不到真实用户IP导致风控和用户行为分析的数据全部失效。原因很简单HAProxy做完代理转发之后和后端建立TCP连接的是HAProxy自己的IP不是客户端IP。要解决这个问题有三个层次的做法。最标准的做法是在HAProxy里开启option forwardfor让HAProxy在转发HTTP请求时插入X-Forwarded-For头。后端应用需要配置信任这个头比如Tomcat的RemoteIpValve、Nginx的set_real_ip_from real_ip_headerSpring Boot也可以通过server.forward-headers-strategyNATIVE开启。这里有个安全小细节X-Forwarded-For客户端是可以伪造的。如果后端不加区分直接信任会带来IP伪造风险。所以更稳妥的做法是在HAProxy层对源IP做一次过滤只信任从前端代理过来的请求也就是配置option forwardfor except 127.0.0.1或者设定trusted proxies的白名单。我在前面配置示例里用到了header X-Real-IP的写法就是给指定Header赋值并把原有内容覆盖掉从源头上杜绝伪造。6.3 504/502错误排查七层代理环境下最常见的两类错误是502和504。502 Bad Gateway代表HAProxy成功接收了客户端请求但无法从后端服务器获得有效响应。可能是后端没有进程在监听端口、网络不通、后端服务器直接挂了也可能是健康检查已经标记该节点宕机但仍有请求被转发到一个已经被摘除的节点这种情况极少见往往是健康检查配置异常。排查思路一般是这样先看stats页面里后端节点的状态是否全部DOWN如果是直接用curl测试后端curl -v http://后端IP:端口/healthz看后端本身能不能通。如果后端本身一切正常再查HAProxy到后端服务器之间是否有防火墙拦截。504 Gateway Timeout则代表后端响应超时也就是说HAProxy已经连上后端服务器、也发出了请求但后端在timeout server设置的时间内没返回。这种问题一要检查后端是否真的有慢查询或外部接口超时二要看timeout server是不是设置得太短。有个经典案例后端处理图片上传大图片压缩需要一分多钟前端界面一直报504后端明明还在正常处理。处理方式是把timeout server从60秒调到300秒问题立即消失。我在生产环境里还遇到过一个比较隐蔽的问题后端应用在压测中出现周期性的504排查了很久发现是数据库连接池在预热阶段连接建立过慢导致个别请求首次处理超过了3秒的connect timeout。后来把timeout connect稍微调大并让后端应用启动时做一次连接池预热彻底解决了。6.4 统计页面的正确用法HAProxy自带的统计页面是个非常好用的线上诊断工具配置也简单listen stats bind *:8404 stats enable stats uri /stats stats refresh 3s stats admin if LOCALHOST要注意的是stats页面必须做访问控制。不要把8404端口暴露到公网至少要把它绑到内网或本机然后用防火墙限制访问来源。如果确实需要远程访问给stats auth设置强密码是底线。页面上最有价值的几个字段每个后端的Status状态UP/DOWN、Sessions Current当前连接数、Response Time响应时间、Session Rate连接速率。排查问题时我一般先看Status字段是不是全UP如果有DOWN的节点再看是主动下线还是被动检查失败然后回到第六节说的健康检查逻辑去分析原因。Sessions Current字段如果长时间逼近maxconn上限说明后端扩容已经迫在眉睫或者是负载均衡算法选择不合理导致节点分配不均需要结合连接数分布和响应时间一起判断。7. 性能与安全调优心得7.1 内核参数、连接队列与文件描述符配置层面的调优做完了还差系统层面的调优。这里我整理了一份常用的内核参数参考清单注意这是基于常见实践的补充生产环境还是要先在测试环境验证再上线net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 30 net.ipv4.tcp_max_syn_backlog 65535 net.core.somaxconn 65535 net.core.netdev_max_backlog 65535 fs.file-max 65536000tcp_tw_reuse和tcp_fin_timeout解决的是高并发短连接场景下TIME_WAIT堆积的问题。HAProxy做七层代理时每个普通请求都会消耗一个端口和连接请求处理完毕后连接立即关闭会留下大量TIME_WAIT状态的连接。如果等待时间去到默认的60秒大量连接资源被占据后续新连接就会受影响。开启tcp_tw_reuse后内核可以安全地复用这些TIME_WAIT连接效果非常显著。somaxconn和tcp_max_syn_backlog则决定了系统在请求风暴下能承载多少未处理的连接请求。HAProxy的maxconn是一个全局限制超出了这个数字的请求会被拒绝这其实是一种保护机制——宁可排不上队也不能拖着大量连接拖垮整个进程。之前给一个高并发项目压测一开始没有调somaxconn压测刚开始阶段就出现大量连接失败操作系统的半连接队列直接满了。调大之后压测曲线立即变得平滑。另外必须提到ulimit。HAProxy进程能打开的文件描述符数量直接受系统硬限制约束。在systemd服务里可以通过LimitNOFILE设置[Service] LimitNOFILE1048576这是高并发环境下HAProxy启动之后“莫名”报too many open files时最常见的解法。注意不止systemd的unit文件要改还要同步检查一下/etc/security/limits.conf里的nofile设置两边要一致。7.2 安全加固IP黑白名单与其他防护措施七层代理天然处在一个可以介入安全策略的位置。我这边至少保留了以下几类措施。最简单的是IP封禁。比如某个恶意IP持续扫描或高频请求直接在frontend里加一条ACL拦截acl banned_ip src 1.2.3.4 http-request deny if banned_ip比直接在防火墙封禁更灵活的地方在于你不需要动系统防火墙改配置reload一下就生效了还可以配合stats页面观察被拦截的请求有没有降下来。更精细的防护手段包括限制请求速率。HAProxy自带stick table可以做速率统计backend rate_limit stick-table type ip size 100k expire 30m store http_req_rate(10s) backend api_pool http-request track-sc0 src table rate_limit acl too_fast sc_http_req_rate(0) ge 50 http-request deny if too_fast这段配置的意思是为每个来源IP维护一个10秒窗口内的HTTP请求计数如果超过50次直接拒绝。这个机制特别适合在恶意爬虫、刷接口攻击来临时做快速止血。带宽防护、单IP并发数限制也可以通过类似方式实现。当然要注意的是一旦启用了这些规则误杀的可能性也存在。比如公司出口IP可能是公网NAT共享的几十个人共享一个IP出口如果把阈值设得太低正常同事的请求也会被拦截引发“上不了系统”的工单轰炸。所以阈值的设置一定要结合业务实际情况统计一段时间内的访问分布后再定别拍脑袋。7.3 配置规范与变更发布的经验关于HAProxy配置本身我最后分享几条实践经验。每次做变更前一定要用-c参数做语法检查这个习惯能拦截掉90%的低级错误。配置文件的版本管理要用Git这是最基本的底线这样任何一次变更都可以追溯是谁改的、为什么改、改了什么。reload之前把当前生效配置备份一次出问题时能用最快的速度回滚。还有一个容易忽略的环节HAProxy的知识库和社区非常成熟遇到没见过的报错先把报错信息原样搜索一遍通常都能找到遇到过同样问题的人。我自己比较偏爱的排查顺序是先看stats页面、再看日志、然后看后端节点状态、最后才看配置和代码这样能最大化缩小排查范围。8. 一条实战链路从压测到上线最后讲一个完整案例。某套电商促销系统上线前我负责整个入口的流量验证。当时用压测工具模拟了1万并发客户端请求直接怼到HAProxy七层代理入口。第一轮压测的结果很不理想节点2的负载明显高于节点1响应时间也不稳定。通过stats页面看到节点2的Sessions Current长期高于节点1于是判断负载均衡算法可能不均衡但配置里用的是roundrobin啊。仔细检查后发现健康检查里配置的权重没有对齐节点2回头查配置发现它的server行多了一个weight 2导致流量分配比重是2:1轮询被权重干扰了。把权重统一改为1之后第二轮压测负载曲线基本重合。接着又出现了一个新问题压测过程中大量请求报504。通过查看后端应用日志发现后端节点有慢SQL单接口耗时最长的到了8秒。临时调大timeout server到10秒后504消失但整条链路的响应时间依然偏高。最后通过优化SQL索引和缓存方案后端耗时降到了100毫秒左右压测数据才算真正合格。整个过程下来的经验是性能瓶颈往往不是单一因素造成的代理层、网络层、后端应用、数据库可能同时存在隐患。而七层代理作为流量入口恰好是一个天然的“观测点”通过它你能像看实时交通路况一样看到每条链路的健康状况然后再顺着线索一层层往下查。这也是我一直觉得HAProxy七层代理值得认真对待的原因——它不仅能帮你把流量分发好更能在关键时刻帮你快速定位问题到底出在哪一环。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表