我在 Amazon Elastic Compute Cloud(Amazon EC2)基于 Nitro 系统的实例上运行工作负载。我想确保托管在我的实例上的 Amazon Elastic Block Store(Amazon EBS)卷获得最大的 I/O 性能。
解决方法
1.检查您的 EBS 卷是否已达到其 IOPS 配额。当您的卷达到 IOPS 配额时,延迟可能会增加,而延迟增加会影响性能。更多信息,请参阅如何优化我的 Amazon EBS 预调配 IOPS 卷的性能?
**注意:**如果您使用的是 GP2 卷,则检查并确认您的卷尚未耗尽突发点数。
2.要使用 NVMe 存储,您必须运行以下操作系统(OS)之一:
- Amazon Linux 亚马逊机器映像(AMI)或更高版本(内核 4.12 或更高版本)
- CentOS 7.0 或更高版本(内核 3.10 或更高版本)
- Red Hat 7.0 或更高版本(内核 3.10 或更高版本)
- Ubuntu 19.10(内核 5.0)或 Ubuntu 18.04.03(内核 5.0 及更高版本)
**注意:**对于这些 Ubuntu 版本,多队列默认处于开启状态。
- Ubuntu 16.04 或 16.10
**注意:**对于这些 Ubuntu 版本,多队列调度器没有经过内核编译,需要单独加载模块
- SUSE 12 或 SUSE 11(SP3 或更高版本)
- Windows Server 2008 R2、2012 R2 和 2016 年或更高版本
或者,确保内核版本支持具有多队列功能的 I/O 调度器。最常见的多队列 I/O 调度器是 kyber、mq-deadline 和 budget fair queue(bfg)。
**注意:**对于 Oracle、Linux 或 Debian 等操作系统,请使用包含或支持多队列 I/O 调度器的内核版本。CentOS 及其内核版本支持多队列 I/O 调度器。
如果您使用这些操作系统的早期版本,则可能会遇到 I/O 性能下降的问题,因为基于 Nitro 系统的实例在主机级别进行多队列处理。这会导致操作系统和主机级别的调度器不兼容。
在卷拦截提交给 EBS 卷的 I/O 读取或写入请求之前,这些请求会经过多个层。如果基于 Nitro 系统的实例使用的是没有多队列调度器的较旧内核版本,您有时会在 I/O 调度器(I2D)层看到延迟。在使用 blktrace、blkparse 和 btt 工具进行测试和基准测试时,可以在结果中看到延迟。有关这些工具的更多信息,请参阅 die.net 网站上的 blktrace、blkparse 和 btt 帮助页面。
为了提高基于 Nitro 系统的实例的 I/O 性能,CentOS 7 具有多队列块 I/O 队列机制(blk-mq),允许设备驱动程序将 I/O 请求映射到多个硬件或软件队列。为了在基于 Nitro 的系统上获得最佳性能,最佳实践是使用带有最新内核的最新操作系统。
CentOS 6 上的 I/O 调度器
$cat /sys/block/xvdf/queue/scheduler noop anticipatory deadline \[cfq\]$cat config-2.6.32-754.30.2.el6.x86\_64 | grep -i blk\_mq
**注意:**由于 CentOS 6 内核中的配置文件使用 noop 调度器,因此它不会返回 blk_mq。
Redhat 9(内核 5.14 及更高版本)上的 I/O 调度器
cat /sys/block/<EBS device name>/queue/scheduler \[none\] mq-deadline kyber bfq
在选择调度器之前,请查看每个调度器的详细信息。有关更多信息,请参阅 Red Hat 网站上的 Available disk schedulers。
要在 EC2 实例运行期间在操作系统级别更新调度器,请运行以下命令:
#sudo echo 'kyber'> /sys/block/<EBS device name>/queue/scheduler
要永久更改 I/O 调度器,请修改 grub 配置并更新 elevator 参数。以下步骤适用于 CentOS 和 Red Hat Enterprise Linux(RHEL):
1.运行下列命令:
#sudo vim /etc/default/grubGRUB\_CMDLINE\_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet elevator=kyber"
2.运行下列命令:
#sudo grub2-mkconfig -o /boot/grub2/grub.cfg
如果实例重新启动,则 I/O 调度器将保持设置。