2019独角兽企业重金招聘Python工程师标准>>>

HAProxy现网问题解决

1问题描述

RMI上线后,现网的接口总是报告异常。

2问题分析

通过对RMI源码的理解,这个是在RMI客户端那边没有可用的连接时,需要创建一个新的连接,但是连接失败。

网络问题一般抓包可以定位,于是通过抓包发现失败的连接有个共同的现象,就是在5秒钟被HAProxy主动关闭,考虑到HAProxy的配置有个connectTimeout参数为5秒,应该是HAProxy连接后端的RMI服务器时失败。

通过抓包也验证了这一点,因为在5秒钟内,并没有搜到从HAProxy发起的对后端的SYN报文(除了check导致的握手)。

于是大胆怀疑问题出在HAProxy这边,否则至少HAProxy应该发起主动连接才对。

此时猜测HAProxy没有拿到可用的服务器。

3 HAProxy定位

3.1 connect(...)

刚开始怀疑是HAProxy没有拿到可用的服务器,那么从哪里入手解决问题呢?

考虑到如果HAProxy如果需要对远程服务器建立连接的话,肯定需要调用connect(...)这个C语言的API,所以全文搜索connect(....)

在函数

中可以看到调用了connect(...)

3.2 tcpv4_connect_server的指定

查看tcpv4_connect_server的调用栈

上面这个代码是在event_accept函数中,也就是说在session中的client建立时,指定session的server端的connect函数,然后后面某个地方触发了tcpv4_connect_server函数。

3.3 tcpv4_connect_server的调用

到这里就很清楚了,通过调用connect_server函数,然后根据之前指定的连接函数来触发之,由于我们在3.2中指定了tcpv4_connect_server函数,所以触发它,tcpv4_connect_server函数中又调用了connect函数,所以需要跟踪connect_server函数。

3.4 connect_server的调用

查看调用栈,

通过类似的调用机制,尝试定位问题。

更详细的调用栈就不一一列出。

3.4 修改源码添加自定义日志

为了定位问题的准确性,修改HAProxy【1.4.23】源码,在每一个session创建和后续行为都添加了自己的日志,同时每个日志行都添加了session的唯一ID.

这样就可以跟踪每个会话的具体行为。

日志格式如下:

3.5 srv_dynamic_maxconn

通过日志,我们发现,其实并不是HAProxy拿不到可用的服务器,而是拿到了之后,通过这个函数动态计算这个服务器当前的动态maxconn.

跟踪下代码:

unsigned int srv_dynamic_maxconn(const struct server *s,struct session* session)

{

unsigned int max;

if (s->proxy->beconn >= s->proxy->fullconn)

{

/* no fullconn or proxy is full */

max = s->maxconn;

}

else if (s->minconn == s->maxconn)

{

/* static limit */

max = s->maxconn;

}

else

{

max = MAX(s->minconn,

s->proxy->beconn * s->maxconn / s->proxy->fullconn);

}

if ((s->state & SRV_WARMINGUP) &&

now.tv_sec < s->last_change + s->slowstart &&

now.tv_sec >= s->last_change) {

unsigned int ratio;

ratio = 100 * (now.tv_sec - s->last_change) / s->slowstart;

max = MAX(1, max * ratio / 100);

}

return max;

}

于是在此段代码中添加日志,发现在蚂蚁窝环境下,每次此函数都返回1.

于是问题就知道出在什么地方了,这里返回1,导致每次对于某个后端服务器来说,

第一个请求建立连接会被响应,而后续的2,3.。。都被拒绝。

再查看日志,完全验证了这一点。

4 解决方案

既然知道了问题所在,那么怎么解决?

必然是通过此函数的逻辑来解决。

查看srv_dynamic_maxconn函数,发现如果在配置中可以有2种方法解决

1 将minconn设置为较大的一个参数

2直接设置为minconn与maxconn一样,彻底去掉最小限制,对于并发量按照maxconn来配置。

针对第2种情况,代码中可以看到

也就是如果二者大小一样的话,max就返回s->maxconn。这样也没有问题。

5 与HAProxy作者的邮件交流

既然是开源软件,那么就可以直接跟作者交流。

下面是跟作者的邮件交流。

5.1 发送邮件描述问题

5.2 对方回复

5.3 再次发送验证答案

于是发送自己的答案过去,看对方对我们的解决方案的评价,同时不忘热情赞美对方的软件之流行度。

5.4 对方的最终回应

也就是说,作者认为直接去掉minconn参数更好,于是我们在haproxy.cfg的配置中去掉了这个参数,通过日志打印,minconn的值会等于maxconn参数,也就是走了static limit这个分支。

至此问题得以解决,对HAProxy的理解比之前更进一步。

6 后记

1 碰到问题,迎难而上,尤其是在有源码的情况下,直接debug或者看源码,肯定可以解决问题。一般在linux中c采用gdb,java采用jdb都可逐行跟踪,非常方便准确!

2 开源软件,网上有很多别人踩过的坑,可以尝试搜索是否已经有解决方案。

3 相对于所解决的问题,方法论非常重要,这个也需要经验的积累,比如本文中HAProxy问题的定位其实就在于connect(...) api的入口定位,整理出调用栈,然后添加日志逐步定位问题。

转载于:https://my.oschina.net/qiangzigege/blog/470431

HAProxy高并发问题解决相关推荐

  1. 每一个程序员都应该知道的高并发处理技巧、创业公司如何解决高并发问题、互联网高并发问题解决思路、caoz大神多年经验总结分享...

    本文来源于caoz梦呓公众号高并发专辑,以图形化.松耦合的方式,对互联网高并发问题做了详细解读与分析,"技术在短期内被高估,而在长期中又被低估",而不同的场景和人员成本又导致了巨头 ...

  2. 直播平台源码的高并发问题解决

    优秀的直播平台源码需要同样优秀的服务器相匹配,而高并发问题是直播平台开发者经常遇见的问题,如何解决呢? 本文转载自:https://baijiahao.baidu.com/s?id=163122885 ...

  3. php如何对mysql加锁_PHP+MySQL高并发加锁事务处理问题解决方法

    本文实例讲述了PHP+MySQL高并发加锁事务处理问题解决方法.分享给大家供大家参考,具体如下: 1.背景: 现在有这样的需求,插入数据时,判断test表有无username为'mraz"的 ...

  4. Java架构师,大数据架构师,高并发设计模式,机器学习知识点分享

    第一章:java精品课程目录大全 1.亿级流量电商详情页系统的大型高并发与高可用缓存架构实战 1课程介绍以及高并发高可用复杂系统中的缓存架构有哪些东西?32分钟 2基于大型电商网站中的商品详情页系统贯 ...

  5. 大型网站高并发解决方案——集群

    文章目录 大型网站高并发解决方案--集群 前言 一.集群 1.集群的分类 2.负载均衡集群(LB) (1)负载均衡集群结构 (2)负载均衡设备分类 3.高可用集群(HA) 4.高性能运算集群(HPC) ...

  6. Java多线程学习处理高并发问题

    在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结. 以下内容将 ...

  7. 淘宝服务端高并发分布式架构演进之路

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 1. 概述 本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列 ...

  8. 【高并发】高并发场景下如何优化加锁方式?看完这篇我确实明白了!!

    来自:冰河技术 写在前面 很多时候,我们在并发编程中,涉及到加锁操作时,对代码块的加锁操作真的合理吗?还有没有需要优化的地方呢? 前言 在<[高并发]优化加锁方式时竟然死锁了!!>一文中, ...

  9. 高并发场景下更新数据库报错,记录一次 MySQL 死锁问题的解决

    作者 l 会点代码的大叔(CodeDaShu) 今天隔壁项目组的开发小姐姐找到我,说她们项目正在做压力测试,更新 MySQL 数据库的一张表时,总是发生死锁,日志大概是这个样子的: org.sprin ...

最新文章

  1. 分区文件http://wenku.baidu.com/view/d839d1868762caaedd33d4b7.html
  2. OpenCvSharp_FindContours函数参数详解
  3. 给我一个兴趣点,我就能撬动一个行业
  4. Cartographor定位-shell脚本:不停拉起死掉的程序和脚本
  5. mysql周报内容范文_Mysql各种报表查询含实例,日报,周报,月报,时间差自动计算...
  6. 7-1 字母统计图 (10 分)(思路+详解)
  7. 7年老Android一次操蛋的面试经历,系列教学
  8. Mongodb最基础入门教程
  9. 利用pandas对一列/多列进行数据区间筛选
  10. 2018-04-26java实习面试记录
  11. Android---真机调试时不能识别手机的解决方案
  12. 专业五线谱作曲打谱软件Overture的常用快捷键功能大全
  13. java访问kudu,KUDU的java操作
  14. C# Winform开发人脸识别小程序 (基于百度接口)
  15. TCP Congestion性能测试分析
  16. 基于JAVA的网上图书商城参考【数据库设计、源码、开题报告】
  17. 手写一个java爬虫,获取网页信息。
  18. 【20保研】西安交通大学软件学院2019年全国优秀大学生夏令营通知
  19. Codeforces Round #715 (Div. 2) B. TMT Document——思路分析,清晰易懂
  20. Codeforces Round #369 (Div. 2) B. Chris and Magic Square【数学,模拟】

热门文章

  1. 《网络管理员考试案例梳理、真题透解与强化训练》复习重点
  2. Hacking techniques automation
  3. 通过反射获得引用程序集信息
  4. 002 前、中、后序遍历二叉树(递归迭代)
  5. 【转】转 Linux调优方案,sysctl.conf的设置
  6. EasyUI下拉框级联
  7. javascript面向对象属性函数用法(defineProperty与getOwnPropertyDescriptor)
  8. reporting services订阅
  9. C Primer Plus(第六版):C语言概述
  10. 原型链 —— 以隐式引用作为存储方式的单向链表