Linux开发

巧用Systemtap注入延迟模拟IO设备抖动

0

当我们的IO密集型的应用怀疑设备的IO抖动,比如说一段时间的wait时间过长导致性能或其他疑难问题的时候,这个现象处理起来就比较棘手,因为硬件的抖动有偶发性很难重现或者重现的代价比较高。

幸运的是systemtap可以拯救我们。从原理上讲,我们应用的IO都是通过文件系统来访问的,不管read/write/sync都是,而且我们的文件大部分都是以buffered方式打开的。在这个模式下,如果pagecache不命中的话,就需要访问设备。 知道了这个基本的原理以后,我们就可以用万能的systemtap往vfs的读写请求中受控的注入延迟,来达到这个目的。

要点有以下几个:
1. 受控的时间点。
2. 延迟时间可控。
3. 目标设备可控。

我写了个脚本注入IO延迟,模拟ssd/fio硬件的抖动来验证是否是IO抖动会给应用造成影响,三个步骤如下:
步骤1: 编译模块
(更多…)

ulimit限制之nproc问题

11

前两天微博上的@王关胜同学问了个问题:

#ulimit问题# 关于nproc设置:centos6,内核版本是2.6.32. 默认情况下,ulimit -u的值为1024,是/etc/security/limits.d/90-nproc.conf的值限制;注释掉这个限制后,值为95044;手工设置90-nproc.conf文件,值为新设置的值。想请 问这个95044是怎么来的?

这个问题挺有意思的,这里面有二个信息点:

1. 为什么limit配置文件是 /etc/security/limits.d/90-nproc.conf 而不是其他?
2. 为什么是nproc的值95044,而不是其他。

之前我也写了些ulimit的问题的解决,参见 这里

我们来简单的做下实验:
[shell]
$ cat /etc/security/limits.d/90-nproc.conf
* soft nproc 8933
$ ulimit -u
8933

$ cat /etc/security/limits.d/90-nproc.conf #注释掉
#* soft nproc 8933
$ ulimit -u
385962
[/shell]
我们可以看出就是说当注释掉限制的话,不同的机器值是不同的。

我们先来回答第一个问题:为什么limit配置文件是 /etc/security/limits.d/90-nproc.conf 而不是其他
这个问题早些时候 杨德华 同学碰到了,也写了篇 博文 来解释redhat6下面如何破解nproc的限制,但是文章没提到这个问题。
(更多…)

Linux下如何知道文件被那个进程写

9

晚上朔海同学问:

一个文件正在被进程写 我想查看这个进程 文件一直在增大 找不到谁在写 使用lsof也没找到

这个问题挺有普遍性的,解决方法应该很多,这里我给大家提个比较直观的方法。

linux下每个文件都会在某个块设备上存放,当然也都有相应的inode, 那么透过vfs.write我们就可以知道谁在不停的写入特定的设备上的inode。
幸运的是systemtap的安装包里带了inodewatch.stp,位于/usr/local/share/doc/systemtap/examples/io目录下,就是用来用途的。
我们来看下代码:

[shell]
$ cat inodewatch.stp
#! /usr/bin/env stap

probe vfs.write, vfs.read
{
# dev and ino are defined by vfs.write and vfs.read
if (dev == MKDEV($1,$2) # major/minor device
&& ino == $3)
printf ("%s(%d) %s 0x%x/%u\n",
execname(), pid(), probefunc(), dev, ino)
}
[/shell]
这个脚本的使用方法如下: stap inodewatch.stp major minor ino

下面我们构造个场景: dd不停的写入一个文件,查出这个文件的ino, 以及它所在设备的major, minor, 运行stap脚本就可以得到答案。

(更多…)

Tips of Linux C programming

11

1. 优雅地使用链表

        链表是编程中经常要用到的数据结构,结构体描述时分为数据域和指针域,本没有什么好讲。但有没有想过教科书上的这种方式有什么问题?通过这种方式定义和使用链表,对于不同的链表类型,都要定义各自的链表结构,繁琐的很。linux kernel中链表的用法才应该是教科书中出现的。
        基本思想:在Linux内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。
1) 链表定义:
struct list_head {
    struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }

2) 链表使用者定义:
(更多…)

linux异步IO编程实例分析

4

在Direct IO模式下,异步是非常有必要的(因为绕过了pagecache,直接和磁盘交互)。linux Native AIO正是基于这种场景设计的,具体的介绍见:KernelAsynchronousI/O (AIO) SupportforLinux。下面我们就来分析一下AIO编程的相关知识。

       阻塞模式下的IO过程如下:
(更多…)

linux后端服务程序之信号处理

7

信号就是通知某个进程发了某个事件,也称为软件中断。信号提供了一种处理异步事件的方法。信号通常是异步发生的,进程预先不知道信号准确发生的时刻。后端程序(daemon)往往需要提供7*24不间断的服务,因此,编程daemon程序时对信号的正确处理尤为重要。

下面和大家分享编写daemon程序时信号处理的注意事项,内容都来自Internet,只是进行了整理和总结。关于信号的基础只是请参考APUE。

常见的信号

SIGHUP 1 和终端的连接断开,发送该信号给控制进程。通常用此信号来通知daemon重新读取配置文件(因为daemon不会有控制终端,通常不会收到该信号)。
(更多…)

libeio源码分析 – 主流程

6


@淘宝千石

简介

This library provides fully asynchronous versions of most POSIX functions dealing with I/O. Unlike most asynchronous libraries, this not only includes read and write, but also open, stat, unlink and similar functions, as well as less rarely ones such as mknod, futime or readlink. It also offers wrappers around sendfile (Solaris, Linux, HP-UX and FreeBSD, with emulation on other platforms) and readahead (Linux, with emulation elsewhere>). The goal is to enable you to write fully non-blocking programs.

缘起

相信上面这段话已经将libeio的feature讲的足够清楚:提供全套异步文件操作的接口,让使用者能写出完全非阻塞的程序。阻塞意味着低效,但非阻塞一定要有很好的通知机制才能做到高效。
(更多…)

多存储设备混合使用raid卡配置问题

5

背景说明:

oceanbase的updateserver服务使用了SAS+SSD的混合存储方式,其中SAS盘用于存储实时记录的操作日志,SSD用于存储定期转储的内存数据。updateserver写操作日志的特点是大量的小块数据追加写,总带宽不大,但是要求1毫秒以下的写延迟,直接使用SAS或SSD都无法满足需求,因此我们为updateserver配备了一块带电池的raid卡,数据写入raid卡的缓存后即向系统返回,再由raid聚集后再写入SAS盘。在线上的配置中,SAS盘和SSD盘都接到同一块raid卡上。

问题说明:

oceanbase在sns feed index机群调高写入压力后,偶尔出现写操作日志用时超长的情况,由于updateserver机器配置了带电池的raid卡,正常情况下数据写入raid卡的buffer即可返回,用时约100us,但是在sns feed index的应用中却出现主备写操作日志用时达到几百毫秒的情况,由于updateserver使用单线程批处理写请求的技术,所以一次写操作日志的超时就会造成后续排队中的写任务延迟都相应增加,短时间内阻塞应用端很多数据的写入。

经过排查发现线上两次出现的这种写超时情况,都伴随同时在执行的updateserver转储任务,通过与内核组高阳同学的多次交流,怀疑转储写SSD的IO影响了写操作日志,造成其延迟增大,在线下部署与线上相同的压力测试环境,sas盘做raid1,2块ssd不做raid,全接到raid卡上,写入模式都为write back,在7500TPS,写操作日志速度约25MB/s,转储写SSD速度约100MB/s的情况下,稳定复现这一问题。

统计测试结果发现,出现超时的概率与ssd的碎片情况有关,在ssd没有经过全盘dd碎片比较多的情况下,写操作日志用时超过50ms的概率为万分之3.2,而对ssd进行一次全盘dd置零之后,仍然会出现写操作日志用时超过50ms的情况,但是概率降低到百万分之1.7。使用megacli将ssd设备的写入模式修改为write through之后,再进行测试连续写入500G数据的情况下,超过50ms的情况出现次数为0。

因此实验数据验证了之前的怀疑,由于写操作日志和转储数据都是write back模式,先放在raid的卡的缓存中,然后异步写到设备中去,由于转储短时间内写数据量比较大,在写满raid卡缓存的情况下,只能阻塞写入,等缓存的数据写到设备中去才能返回,这样缓存就退化成了一个fifo队列,阻塞了写操作日志的IO,特别是在SSD碎片比较多的情况,写SSD变造成raid卡缓存清理耗时变长,写操作日志用时也相应变长。

结论:

1、updateserver使用的机器,上线前需要对raid进行配置,除操作日志盘的写入模式为write back,其他盘需要改为write through

2、ssd盘上线前做一次全盘清理,使用dd即可(dd if=/dev/zero of=[ssd设备文件] bs=4194304)

Linux下pipe使用注意事项

14

Linux下的pipe使用非常广泛, shell本身就大量用pipe来粘合生产者和消费者的. 我们的服务器程序通常会用pipe来做线程间的ipc通讯. 由于unix下的任何东西都是文件,只要是文件,在读取的时候,,就会设置last access time, 所以pipe也不例外., 但是这个时间对我们没有意义 如果pipe使用的非常频繁的时候会碰到由于设置访问时间导致的性能问题. 这个开销远比pipe读写的本身开销大. 相比文件读写的开销, atime微不足道,但是对pipe来讲就不同了.
这个事情是上次和多隆同学在把玩他的网络框架的时候,无意发现的.

我们来分析下pipe的这部分代码:
(更多…)

最近文章少了一些

5

Sorry啊,近段时间全力备战1111ing,和大家的互动少了一点,结束后会有大量技术分享,期待大家的指正。

Go to Top