记一次线上问题定位过程

技术记一次线上问题定位过程 记一次线上问题定位过程出现问题,但不能快速修复系统在高峰期突然出现了大面积的core dump,通过gdbcore文件发现,是core在发送数据到另一个服务的地方,打开堆栈对

记住在线问题定位过程。

出现问题,但不能快速修复

在系统的高峰期,突然出现了大面积的堆芯。通过gdbcore文件,发现核心正在向另一个服务发送数据,打开栈对应的代码,这是公司的一个基本库文件,只是一个protobufmessage对象的简单声明。然而,核心一般不太可能出现在这个地方,否则程序中到处都会有类似的做法。为什么核心不在其他地方?是不是服务的其他线程使用gdb的线程应用所有bt来检查每个线程的堆栈造成的?大部分线程处于睡眠或等待状态信号(在线服务正在等待处理请求),这似乎不是问题,而且有点混乱。

Gdb打开其他机器实例的核心文件,发现线程1仍然有相同的堆栈信息,表明核心在protobufmessage对象中。稍微看一下protobuf声明对象的过程,无非是申请内存。没什么好怀疑的。如果这里有问题,服务中有很多使用pb对象的地方。为什么核心在同一个地方?

降级止损

我不知道该怎么办。查找服务日志,发现下游服务有大量请求超时。查这个下游服务的负载,发现负载很高。会不会是这种下游服务造成的?仔细想想,由于大量的实例同时存在,也会触发在线监控进程再次拉起服务,这样短时间内就会有大量的请求集中请求到一个下游服务的ip上(下游服务的实例有很多,但是由于服务本身无法在数据准备好之前注册到注册表中, 或者名称会暴露给上游,所以此时只能通过ip访问下游),所以下游服务的高负载不是核心的原因,批量重启请求被降级。 不幸的是,重启后,进程被服务了一小段时间,然后内核又回来了。

降级没用,继续找原因止损

看来要先找出核心的原因。既然都在线程1的同一个地方,这个地方应该有问题,所以我们可以从这里开始。查看当前请求中的数据,发现不同核心文件中字段的值是相同的。你能猜到一个特殊的请求会导致核心立即打电话给产品运营商,并首先阻塞这个流量吗?十分钟后发现核心真的不在了,观察半小时后服务正常。这时,已经是凌晨4点了。目前只能先这样止损,等第二天才能找出核心原因。

找到潜在原因,并修复

第二天上班仔细定位问题,或者就像昨晚一样,打开核心文件,查看堆栈信息,对比源代码,发现核心所在位置的源代码下面几行调用了一个序列化函数,这个函数是内联的,因为内联函数在编译的时候只把内容嵌入编译器,不做函数调用,所以如果核心在这里,就不会有堆栈信息。为了验证这种猜测,当gdb调试核心文件时,我有意打印了当前内联函数中的变量,结果确实如此。(反证:如果程序在这里执行之前是核心,是不可能打印出变量信息的),所以在序列化的过程中就断定是核心。然后关注序列化。实现系列化是公司2005年的代码,到现在已经16年了,不太可能出现什么问题。乍一看,序列化非常复杂,涉及内存设计和序列化编码过程。仔细看看,这可能意味着要将C的每个基本类型写入队列。迭代器先写元素的数量,然后写元素。没什么问题。继续挖掘,找到一个关键消息:序列化字符串时,它会决定大小,如果超过一定的大小,就会抛出异常。与这种特殊流量的某个字符串的长度相比,真的很长,这应该是问题所在。查了相关资料,发现是gcc的低版本。如果在底部抛出异常,就会被抓住然后直接退出,栈就不打印了。后来,有人报告了这个错误,并在gcc8中修复了它。难怪我看核心文件的时候从来没有看到核心的真正位置。对于这种情况的core,解决方案也很简单。修改旧代码(当然,如果更一般,只需hook __cxa_throw并打印出堆栈即可)。到目前为止,问题已经找到,解决方案已经找到。

在__cxa_throw中,底层是捕获异常,然后退出:

void * execute _ native _ thread _ routine(){ 0

尝试{

.

}catch(.){

STD : terminate();

}

}

查看代码

核心转储后,这样看核心文件。

方案

Hook__cxa_throw()在堆栈上生成每个coredump。

#包含iostream

#包括标准除外

#包含线程

Extern 'C' {//加上这三行代码,就可以通过hook __cxa_throw避免栈展开而直接中止。

void __cxa_throw(void* ex,void* info,void(* dest)(void *)){ : abort();}

}

void func(){ 0

引发STD : runtime _ error(' die ');

}

int main(){ 0

STD : thread t(func);

t . join();

返回0;

}

查看代码

影响

代码

https://github.com/longbo Zhan/sample/tree/master/hook _ exception

参考

https://byronhe.com/post/cpp-throw-coredump-with-backtrace/

https://abcdabcd987.com/libstdc-臭虫/

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/116874.html

(0)

相关推荐

  • 8-Java类与对象

    技术8-Java类与对象 8-Java类与对象类与对象引入类// 类与对象
    // 一个程序就是一个世界,有很多事物(对象[属性, 行为])public class Object01{public sta

    礼包 2021年12月17日
  • 怎么解决mybatis一对多查询resultMap只返回了一条记录问题

    技术怎么解决mybatis一对多查询resultMap只返回了一条记录问题本篇内容介绍了“怎么解决mybatis一对多查询resultMap只返回了一条记录问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困

    攻略 2021年11月29日
  • java socket如何接收保证能读完数据

    技术java socket如何接收保证能读完数据这篇文章主要介绍java socket如何接收保证能读完数据,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!socket接收保证能读完数据//

    攻略 2021年10月31日
  • 抖音刷双击在线秒刷,怎么在平台刷抖音赞呢

    技术抖音刷双击在线秒刷,怎么在平台刷抖音赞呢增加抖音点赞量,我们最快速的方法就是去抖音刷赞双击网站,在该网站上可以刷抖音作品点赞量双击量,从而快速的增加抖音作品点赞。那有些抖音用户就纳闷了,花钱买抖音赞,抖音点赞多有什么

    测评 2021年10月21日
  • 春联由来,春联的习俗是如何流传开的

    技术春联由来,春联的习俗是如何流传开的春联二三事实在没有想到春联由来,我家的春联成了他人过目不忘的风景!前年,因为东面邻家华栋殿宇欣喜落成,我家的围墙、地皮被拉裂扯破,主房也受到了一些损伤,被迫重砌围墙、装修房屋,我们的

    生活 2021年10月23日
  • rocketmq如何实现事务消息(rocketmq事务消息失败处理)

    技术RocketMQ事务消息如何实现这篇文章主要介绍了RocketMQ事务消息如何实现,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。根据上文的描述,发送事

    攻略 2021年12月17日