2018年5月13日星期日

Linux IO调度器


1.Linux IO体系

IO调度器系统(I/O Scheduler)是Linux I/O体系中的一个组件,其所处的体系位置如下图所示:

Linux整体I/O体系可以分为七层,它们分别是

  1. VFS虚拟文件系统:抽象出文件系统接口,其下可以对接ext4,xfs等多种具体的文件系统而上层使用者只需要使用VFS提供的统一接口即可。
  2. 文件系统缓存Page Cache/磁盘缓冲Buffer Cache:通过空闲内存将对文件读写的数据放入内存,以获取更快的IO响应。
  3. 映射层:内核通过映射层来确定数据在物理块设备上的位置。
  4. 通用块层:由于绝大多数情况的I/O操作是跟块设备打交道,所以Linux在此提供了一个类似vfs层的块设备操作抽象层。下层对接各种不同属性的块设备,对上提供统一的Block IO请求标准。
  5. I/O调度层:大多数的块设备都是磁盘设备,所以有必要根据这类设备的特点以及应用特点来设置一些不同的调度器。
  6. 块设备驱动:块设备驱动对外提供高级的设备操作接口。
  7. 物理硬盘:这层就是具体的物理设备。

以一次读操作为例:

  1. 系统调用read()触发VFS函数,参数为文件描述符与偏移量
  2. VFS确定请求的数据是否已经在内存缓冲区中;若数据不在内存中,确定如何执行读 操作。 
  3. 假设内核必须从块设备上读取数据,这样内核就必须确定数据在物理设备上的位置。 这由映射层(Mapping Layer)来完成。 
  4. 内核通过通用块设备层(Generic Block Layer)在块设备上执行读操作,启动I/O操作, 传输请求的数据。 
  5. 在通用块设备层之下是I/O调度层(I/O Scheduler Layer),根据内核的调度策略, 对等待的I/O等待队列排序。 
  6. 最后,块设备驱动(Block Device Driver)通过向磁盘控制器发送相应的命令,执行 真正的数据传输。

本文介绍图中蓝色部分Linux I/O调度层支持的策略以及比较。

2018年5月5日星期六

SMP/MPP/NUMA系统架构了解

本文涉及到如下三种常见服务器架构:

  1. SMP(Symmetric Multi-Processor,对称多处理结构)。单主机架构。
  2. NUMA(Non-Uniform Memory Access,非一致性内存访问)。单主机架构。
  3. MPP(Massive Parallel Processing,海量并行处理结构)。多主机架构。

2018年5月1日星期二

golang disk free采集不准确问题

     工作中接手的golang程序运行一段时间后,出现了采集的主机信息free不准确的问题,golang采集的程序与df看到的结果不一致。追踪源码发现核心的采集逻辑是如下这段:
func getVfsStats(path string) (total uint64, free uint64, avail uint64, inodes uint64, inodesFree uint64, err error) {
var s syscall.Statfs_t
if err = syscall.Statfs(path, &s); err != nil {
return 0, 0, 0, 0, 0, err
}
total = uint64(s.Frsize) * s.Blocks
free = uint64(s.Frsize) * s.Bfree
avail = uint64(s.Frsize) * s.Bavail
inodes = uint64(s.Files)
inodesFree = uint64(s.Ffree)
return total, free, avail, inodes, inodesFree, nil
}
这段逻辑其实沿用的是cadvisor里面的代码,上层使用的时候,用这里的free(uint64(s.Frsize) * s.Bfree)作为返回的磁盘空间可用值free。要解决这个问题,得看看syscall.Statfs这个函数调用到底返回了些什么信息,也即syscall.Statfs_t各项的含义。