踩坑记:临界区内要小心

栏目: 服务器 · Nginx · 发布时间: 7年前

内容简介:这周对一个服务进行了升级,结果踩了一个不大不小的坑。先介绍下这个服务的背景:最开始的实现是会把接收到的数据保存在一个成员变量里,然后等积攒到一定数据量后,写入一个文件内。

这周对一个服务进行了升级,结果踩了一个不大不小的坑。

先介绍下这个服务的背景:

这是一个数据接收的服务,通过http协议接收到json数据之后进行解析,然后落地到本地文件;
之后再由其他服务读取这些文件,进行后续的处理。

最开始的实现是会把接收到的数据保存在一个成员变量里,然后等积攒到一定数据量后,写入一个文件内。

这样做最简单,但是有这么一个问题:

如果服务器重启,那么当前hold在内存中的这些数据,就永久的丢失了。

所以这一版呢,我就把它改成了实时append写入文件的方式,写够一定的条目数,就切换一个文件来写。

既然要实时落地,那么这里在接受数据的线程和落地文件的线程之间,就需要一个数据队列来作为缓冲。

针对这个数据队列的操作,则应该加锁避免竞态出现。

那么接受数据的伪代码如下:

// Thread receiver
ConstructContentFromJson(json_value, &content_elem);
{
  MutexLocker locker(&mutex_);
  contents_.emplace(std::move(content_elem));
}

而落地文件的伪代码则是:

// Thread writer
while(!quit_) {
  TryWriteContent();
}

//...

int TryWriteContent() {
  ContentElem content_elem;
  {
    MutexLocker locker(&mutex_);
    if (contents_.empty) {
      usleep(1000);
      return ERROR_NO_ELEM;
    }
    content_elem = contents_.pop_front();
  }
  return DoWriteContent(content_elem);
}

看上去一切都很合理:

  • 接受到数据,就在锁的保护下塞到队列中;
  • 写数据时,则在锁的保护下拿出一个数据来拷贝到局部变量,然后就可以放心写入文件了;
  • 如果队列中没数据可获取了,那就原地等待1ms。

临界区也基本控制的很小,应该也没有性能问题。

DUANG!!!

但是,当我升级完后台服务器群中的一台后,看监控,却发现请求量在更新服务器之后,暴跌了90%。

但是问题是,我这才只更新了一台服务器啊。还有好几台没更新,跑的也是旧版本程序,它们上面接收到的请求也暴跌了。

那一定不是我的锅!

于是我向前去查了nginx log,发现确实nginx接收到的请求数量就少了很多。

难道是服务的调用方也同时发了新版本?

于是赶紧电话联系千里之外的网友同事,查出来的结果是:

由于服务超时严重,所以调用方主动限流了。

那看来还是我的锅…… 是你的,总是逃不掉。 毕竟调用方看来,nginx代理屏蔽了后台所有服务器细节,所以后台一台服务器超时严重,调用方就会认为整个服务超时严重。

再回头去看上面的核心代码,问题很快就浮出水面了:

usleep放在了锁的临界区范围内!

这会导致写文件线程在没数据时,一直占据着锁。虽然这个线程在sleep,但是它却占据着锁,其他线程也没办法往队列里填充数据,等于这部分时间服务啥也干不了。多来几次,就大面积超时了。

问题找到了,解决方法也很简单,把usleep挪到锁外即可。

总结

  • 锁的临界区内,一定不能出现sleep这种阻塞操作(包括但不限于文件IO、网络IO等)。
  • 需要sleep时,可以考虑主动将线程的控制权让出,从而避免使用sleep。

转载请注明出处: http://blog.guoyb.com/2018/07/28/mutex-sleep/

欢迎使用微信扫描下方二维码,关注我的微信公众号TechTalking,技术·生活·思考:

踩坑记:临界区内要小心

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

CSS设计指南

CSS设计指南

史密斯 / 李松峰 / 人民邮电出版社 / 2013-5 / 59.00元

《图灵程序设计丛书:CSS设计指南(第3版)》是一本面向初中级读者的经典设计指南。全书共分8章,前4章分别介绍了HTML标记和文档结构、CSS工作原理、定位元素、字体和文本,对规则、声明、层叠、特指度、选择符等基本概念进行了详细解读。随后4章介绍了页面布局、界面组件,CSS3圆角、阴影、渐变、多背景等视觉设计技巧,最后还对如何实现最前沿的响应式设计进行了通俗易懂的演示。一起来看看 《CSS设计指南》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具