LeeYzero的博客

业精于勤,行成于思

0%

之前排查了一个服务hang死的线上故障,觉得这个问题比较有代表性,本文记录故障排查的经过,并做一些总结和思考。

现象

周末线上一个比较核心的服务(以下称为X服务)出现大量5xx报警。从客户端看到的现象是客户端请求X服务时,出现大量的链接被重置(connection reset by peer)的错误。

分析

从经验来看,90%以上的问题都是上线引入的。故障出现在周末,按规范来说,非特殊情况下,周末是不允许上线,跟相关角色确认后,本次故障不是上线引入。

观察线上流量,在出现故障时间点,流量的确有大幅上涨,从宏观分析来看,有可能流量突然上涨是一个诱因。

任意找了一台有问题的机器,发现了一个比较有意思的现象:服务X出现了大量CLOSE_WAIT状态的连接。从TCP的状态转换可知,CLOSE_WAIT是被动关闭一方在收到FIN并返回ACK后进入的状态。TCP状态机如下:

img

也就是说X服务在收到客户端请求后,客户端关闭连接,还服务端进程并没有关闭连接,分析了web server的框架代码,正常情况下,一个请求处理完后会关闭这个连接,出现这种情况可能是业务逻辑出现阻塞,导致服务端请求的连接一直不能关闭

查看了一下X服务打开的socket句柄数:

1
2
$ lsof | grep `ps -ef | grep x-service | grep -v 'grep' | awk '{print $2}'` | grep sock | wc -l
10231

发现X服务打开的连接数非常多,达到10231个,看下实例的句柄数上限:

1
2
$ unlimit -n
10240

句柄数像是已经被耗尽了,用strace看了下X服务的系统调用:

1
$ strace -p `ps -ef | grep x-service | grep -v 'grep' | awk '{print $2}'`

从系统调用日志中发现了一些关键信息:

发现大量accept调用报错,从日志信息可以看出,的确是系统的文件句柄数(FD)耗尽了,导致连接被reset掉,这也能说明为什么客户端侧看到了大量connection reset by peer错误了。

X服务打开了大量socket文件句柄,且绝大多数连接状态都是CLOSE_WAIT,如果业务逻辑有阻塞的确可能会出现把句柄数数打满。

分析了一下业务逻辑,业务逻辑本身不复杂,只有一次IO网络请求,是从数据库查询数据,从日志中发现了一些端倪:

Read more »

最近排查一个线上接口耗时上涨的问题,其中用到排查思路和相关工具有一定借鉴作用,在此做个记录,同时供网友参考。由于涉及到一些敏感信息,所以本文会对一些名称进行模糊化。

现象

监控发现对外接口的整体耗时上涨了近100ms,涨了近50%,甚至有少部分接口出现超时现象,已经影响到部分业务的用户体验。

分析

宏观分析

对比故障发生的时候点,检查对应时间结点是否内部服务有上线,通常情况下,90%以上的故障都是由上线引起的。但排查后,业务侧并未上过线,排除是业务上线引入的故障。

对比不同机房,服务部署在三个机房,记为机房A,机房B和机房C,发现耗时主要发生在机房A,机房B和机房C并不存在这个问题,怀疑是机房的网络链路问题。

联系负责机房的同学一起排查,未发现网络链路问题。将某个接口所有的流量从机房A切到机房B,发该接口的耗时恢复到之前的水平,看起来的确像是出现机房A网络存在问题。但OP同学再三确认,未发现异常。

Read more »

Code Review是保障代码和产品质量的重要手段,但却被绝大部分公司所忽略。本文主要基于Google对Code Review的实践,结合自身的经验谈谈团队中该如何做Code Review。

1. 什么是Code Review

Code Review是代码评审人(Code Reviewer)对代码提交者(Code Committer)做审查(Review)的过程。

2. 为什么要做Code Review

  • 提升代码/产品质量
  • 团队工程师文化传承
  • 团队成员间知识/经验分享
Read more »

搭建环境是一件很无聊的事情,最近换了一个较新的系统,少了很多系统级的依赖环境问题。本文简单记录搭建hexo环境的步骤,以便后续查阅。

系统环境

CentOS 8.x

安装依赖环境

至少10.13,建议12.0或更高版本。建议使用二进制方式安装

1
$ sudo yum install git-core

安装Hexo

  • 使用npm安装hexo
1
$ npm install hexo
  • 添加环境变量
1
$ echo 'PATH="$PATH:/path/to/node_modules/.bin"' >> ~/.profile
  • 测试
1
$ hexo version

参考资料

[1] hexo官方文档
[2] Nodejs官方文档

周末大清早就被报警短信吵醒,故障表现为离线存储集群流量突增,集中在热点分片,而且流量越来越大,系统吞吐、稳定性均在降低。最终发现是因为实例间时区不一致触发一个隐藏的BUG导致。这个问题在分布式系统中很具有代表性,在此做个记录以备忘。

症状

  • 离线存储集群流量突增,集中在热点分片;
  • 消息系统中消息在持续积压;
  • 消息系统收到大量重复ACK;
  • 业务worker消费到大量重复的消息;
Read more »

RAII作为C++资源管理的一种惯用法,是每一位C++程序员都应该掌握的基本技能。在google上搜索关键字RAII, 有二百多万条搜索结果。说明这个话题在网上已经被讨论过无数次,也发现了一些好文章给我不少启发,这篇文章主要是做个总结并谈谈自己的理解。

什么是RAII

资源获取即初始化(Resource Acquisition Is Initialization),即RAII。RAII是一种C++编程技术。它利用栈对象在离开作用域后自动析构的语言特点,将受限资源的生命周期绑定到该对象上,当对象析构时以达到自动释放资源的目的。 这里说的资源都是指的受限资源,比如堆上分配的内存、文件句柄、线程、数据库连接、网络连接等。

Read more »

在计算机中,锁是用于解决资源竞争问题。在单机(单进程)环境下, 锁可以使用操作系统提供的同步原语实现。 但在分布式环境下,操作系统提供的同步原语就失效了, 需要一个分布式锁。其原理是需要一个分布式锁管理器[1],提供进程级别访问共享资源的互斥性。本文主要讨论基于Redis实现的分布式锁。

分布式锁的使用场景

Martin Kleppmann 在他的博客 How to do distributed locking[2] 中对分布式锁的使用场景做了非常好的概括。从一个更高层次来讲,在一个分布式应用中,使用分布式锁主要有两个原因:效率和正确性。

  • 效率:获取分布式锁可以避免相同的任务被处理两次。如果锁失败,带来的结果就是对某一个子任务多做了一次,其影响完全取决于具体业务场景。比如为了提高消息PUSH效率,需要按用户进行分片,然后每个任务获取一个锁后处理对应的分片,如果锁失败,会造成重复给用户PUSH。
  • 正确性:获取分布式锁是为了防止进程对分布式系统中的资源并发访问而导致系统的状态出现混乱。如果锁失败,两个节点并发的访问同一个共享资源,可能造成数据的不一致性,如文件损坏或数据丢失等。
Read more »

make是一个自动化构建工具,广泛应用于Unix及其类Unix系统中。make最先应用于编译C语言项目,不仅如此,只要某个文件发生变化就需要重新构建的项目都可以使用make工具进行构建。

Makefile是可以被make解析的特定格式的文本文件。其语法简单,当我们构建一个程序时,其工作原理大致为:make首先解析Makefile,查找构建应用的一系列依赖,并检查每个依赖文件是否过期(是否发生变化),如果发生过期,即重新构建变化的依赖文件。

Read more »

最近工作中使用Go开发比较多,而大部分工作都是使用vim完成,在配置vim的Go环境时,发现已经有很多现成的插件可用,对我而言,主要配置以下四个插件就够用了:

  • vim-go: go语言的vim插件。支持代码格式化、语法检查、语法高亮、调试等非常多的功能。
  • tagbar: 用于方便查看代码结构。
  • nerdtree: 用于管理和查看代码目录结构。
  • YouCompleteMe: 用于代码自动补全。

依赖环境

安装go环境

参考go官网,按步骤安装,配置好GOROOTGOPATH环境变更即可,配置go的vim IDE环境需要依赖vim和vim-go插件。

vim-go插件需要vim使用8.0以上的版本,而YouCompleteMe需要python2.7.1+或3.5.1+。如果你系统的vim和python版本满足条件,可以忽略下面两个步骤。

Read more »

相对于IDE,vim的学习成本较高,但一旦熟悉vim后,开发效率是非常高的。vim的命令非常多,但在工作中常用的却比较少,本着实用主义,参考Learn Vim Progressively,整理最有用的命令,也便自己以后查阅。下面涉及到ctrl键的组合操作,如ctrlr组合,用<C-r>表示

模式

vim有三种模式:普通(normal)模式、插入(insert)模式和命令(command)模式。刚进入vim时默认进入普通模式,下面看下各模式的转换:

普通模式下键入i进行插入模式
普通模式下键入:进入命令模式
ESC退出插入模式和命令模式

vim的文档非常全,在命令模式下,我们可以键入hhelp打开帮忙文档,也可以直接键入help <command>,查看指定命令的帮助文档,如help i

在普通模式下通过hjkl(左下上右)移动光标,插入模式下可以键入任意字符,命令模式下可以输入命令,回车键执行命令。如何退出呢,进入命令模式,键入q就可以退出了,如果有更新会提示你保存,键入w进行保存。也可以同时键入wq保存退出。

Read more »