热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Linux】接口机磁盘读写极度不均衡的原因分析

接口机磁盘读写极度不均衡的原因分析背景正文数据写入磁盘的过程NIFI使用本地磁盘的特性PageFaults带出的缓存使用问题的最终定论背景在进行服务器接口机的资源梳理时ÿ

接口机磁盘读写极度不均衡的原因分析


  • 背景
  • 正文
    • 数据写入磁盘的过程
    • NIFI使用本地磁盘的特性
    • PageFaults带出的缓存使用
    • 问题的最终定论



背景

在进行服务器接口机的资源梳理时,发现一个现象——接口服务器的磁盘IO中,数据写入的流量远大于读取流量,实时的监控图表如下:
在这里插入图片描述

实时在服务器使用iotop命令查看读写情况,也能看到差异是非常大的:

Total DISK READ : 75.31 K/s | Total DISK WRITE : 77.38 M/s
Actual DISK READ: 96.82 K/s | Actual DISK WRITE: 1117.56 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
19969 be/3 root 0.00 B/s 1061.48 K/s 0.00 % 78.56 % [jbd2/sdb1-8]
104428 be/4 root 39.45 K/s 0.00 B/s 0.00 % 75.63 % [kworker/u449:0]
158908 be/4 user 35.86 K/s 0.00 B/s 0.00 % 64.11 % sshd: user@internal-sftp
350 be/4 root 0.00 B/s 25.73 M/s 0.00 % 57.42 % [kswapd0]
178091 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.03 % [kworker/35:2]
226695 be/4 user 0.00 B/s 3.59 K/s 0.00 % 0.01 % java -Dzookeeper.log.dir=/data1/app/zookeeper~/zookeeper/zookeeper-3.5.9/bin/../conf/zoo.cfg
18862 be/4 user 0.00 B/s 50.55 M/s 0.00 % 0.01 % java -classpath /data1/app/nifi/nifi-1.16.3/.~app/nifi/nifi-1.16.3/logs org.apache.nifi.NiFi
19999 be/3 root 0.00 B/s 39.45 K/s 0.00 % 0.00 % auditd
138967 be/4 root 0.00 B/s 3.59 K/s 0.00 % 0.00 % rsyslogd -n

基于此问题,还是需要进行一下分析,理解一下为什么会出现这个现象。

正文

数据写入磁盘的过程

针对这个现象,第一个切入点其实不是进程的io占用,因为监控和iotop的表现基本一致,说明实际是有这么高的数据写入需求;

然后另一个需要注意的特征点是,在这样巨大差异的场景下,业务数据也是正常传输的,因此,首先要去想清楚,写入的数据和读取得数据是怎么发生的;

根据iotop的信息显示,发现pid为18862的进程会长期占用大量的Write资源:

[root@hostname ~]# ps -ef|grep 18862
user 18862 18785 99 2022 ? 660-04:39:50 /usr/jdk64/jdk1.8.0_112/bin/java -classpath /data1/app/nifi/nifi-1.16.3/./conf:/data1/app/nifi/nifi-1.16.3/./lib/logback-core-1.2.11.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-properties-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/logback-classic-1.2.11.jar:/data1/app/nifi/nifi-1.16.3/./lib/jetty-schemas-5.2.jar:/data1/app/nifi/nifi-1.16.3/./lib/log4j-over-slf4j-1.7.36.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-framework-api-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-nar-utils-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-runtime-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/jcl-over-slf4j-1.7.36.jar:/data1/app/nifi/nifi-1.16.3/./lib/slf4j-api-1.7.36.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-property-utils-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/javax.servlet-api-3.1.0.jar:/data1/app/nifi/nifi-1.16.3/./lib/jul-to-slf4j-1.7.36.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-server-api-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-api-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-stateless-bootstrap-1.16.3.jar:/data1/app/nifi/nifi-1.16.3/./lib/nifi-stateless-api-1.16.3.jar -Dorg.apache.jasper.compiler.disablejsr199=true -Xmx48g -Xms48g -Dcurator-log-only-first-connection-issue-as-error-level=true -Djavax.security.auth.useSubjectCredsOnly=true -Djava.security.egd=file:/dev/urandom -Dzookeeper.admin.enableServer=false -Dsun.net.http.allowRestrictedHeaders=true -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true -XX:+UseG1GC -Djava.protocol.handler.pkgs=com.dtsw -Dnifi.properties.file.path=/data1/app/nifi/nifi-1.16.3/./conf/nifi.properties -Dnifi.bootstrap.listen.port=22995 -Dapp=NiFi -Dorg.apache.nifi.bootstrap.config.log.dir=/data1/app/nifi/nifi-1.16.3/logs org.apache.nifi.NiFi

根据ps查询的结果,这是一个nifi进程, 那么它应该就是产生数据流向的主要进程了;

接下来从这个进程出发,我们继续探寻IO差异的原因;

在这里,我们首先要知道Linux进行数据读写时的流程,这将有助于我们进一步定位这个问题,首先,让我们思考一个问题:

当我们在Linux写入一个文件的时候,文件是直接写入磁盘的吗?

既然我问出来这个问题,那么你一定会回答“不是”,既然不是的话,这个流程应该是怎样的?

实际上,对于操作系统的操作而言,提高文件写入性能的一个简单方法是让操作系统缓存数据,这个时候会告诉应用程序文件是写入了的,然后再异步的执行写入操作;

这样如果同时有其他磁盘活动将会非常高效,操作系统可以优先读取并稍后执行写入操作。并且在极端情况下还可以完全消除实际写入的需要,例如,在临时文件很快被删除的情况下。

当然,像这样的缓存也有缺点,我们可以想象到,极端情况下,我还没有在终端确认保存操作,那么有些数据可能在真正保存之前就丢失了。

如果编辑器告诉用户写入成功,但文件实际上不在磁盘上,在业务逻辑上一定是不正确的。这就是为什么会有fsync()之类的系统调用,在向用户报告写入成功之前,文件操作程序可以使用它来确保数据正常。

NIFI使用本地磁盘的特性

ok,了解了文件的读写大致流程,我们现在可以顺理成章的给出一个能够和nifi特性匹配的推测:

在配置了本地磁盘作为Content Repository之后,当nifi从A服务器拉取一个数据的时候,在本地会落盘一次,于是数据会写入缓存,下游的nifi推送组件(或者别的需要使用这个文件的流程)可以直接从缓存中拿到这个文件,而不需要产生新的IO操作;

这里的大前提就是nifi的nifi.content.repository.implementation配置项使用的默认值org.apache.nifi.controller.repository.FileSystemRepository:

# Content Repository
nifi.content.repository.implementation=org.apache.nifi.controller.repository.FileSystemRepository
nifi.content.claim.max.appendable.size=50 MB
nifi.content.repository.directory.content1=/data1/app/nifi/nifi_repository/content_repository
nifi.content.repository.directory.content2=/data2/app/nifi/nifi_repository/content_repository

个别的环境可能这个值配置成了VolatileContentRepository,按照现在的推测,这种配置下不会出现write远大于read的情况,因为write本身也不会落盘,所有操作都在内存中进行;当然,如果出发了极端操作,也可能会产生上述现象,具体的需要进一步测试,暂且不提;


PageFaults带出的缓存使用

现在我们有了一个大概的推测,接下来我使用pidstat命令针对nifi的进程进行进一步的排查:

在这里插入图片描述
这里注意几个值,一个是minflt/s还有一个是kB_rd/s;

后者可以很好的理解,是从磁盘读的数据量,单位kB,和监控的情况保持一致,基本没有读,只有写(kB_wr/s);

那么minflt这个值为什么要关注呢?这个指标的含义是什么?

minfltminor page faults,通过man文档我们可以查询到这个指标的解释:

Total number of minor faults the task has made per second, those which have not required loading a memory page from disk.

直译过来就是每秒发生的次要错误总数,这些错误不需要从磁盘加载内存页;这里的错误指的就是页面错误,想要理解这个指标的含义,我们就要多了解一下页面错误是什么。

我们知道,操作系统使用分页在主存储器和辅助存储器之间传输数据(主存储器就是RAM内存,CPU可以直接访问,辅助存储器通俗来说就是我们常说的磁盘)以实现高效的内存管理;

页(内存/虚拟页)是正在运行的进程的一部分,表示一个逻辑内存单元;内存中包含单个进程页的物理部分称为帧;所有帧都是固定长度,允许非连续(非共享)分配物理内存地址空间;

而我们所说的页错误(page fault)是由内存管理单元引发的异常,当进程需要访问其地址空间内的数据时,它无法加载物理内存;

异常通常指示计算机在虚拟内存中找到该数据块,这样它就可以从存储设备发送到物理内存;page fault其实很常见,通过提高程序的内存分配,通常有助于提高性能;

minor page faults,也称为软错误,发生在内存页由多个程序共享时,其中一些程序已经将该页带到主内存中;也就是说,在访问一个地址时,与之绑定的虚拟内存空间对应的地址空间已经被内核加载到了Page Cache中,那么此时只需要把该Page映射到vma中即可;

现在,让我们回到pidstat的跟踪排查结果上来,minflt发生的非常频繁,说明需要操作的数据总是能从缓存中找到,所以,实际上并不会产生大量的磁盘io读操作。

问题的最终定论

现在,我们需要使用一些小手段,手动的介入缓存的使用,尽可能的在数据读入缓存后清理除去,我们使用sync命令调用响应的页回刷的函数,同时观察到磁盘的读操作一下变多了:
在这里插入图片描述
这样看可能并不直观,让我们结合已有的监控进行观察:

在这里插入图片描述
尽管只有很短的时间,但是我们可以看到磁盘的读写流量基本是持平了;

这就是因为我们手动介入,尽可能的在nifi将数据拉取过来时,从内存中把对应的数据刷写磁盘并清空缓存,导致下游的读取需要再走一次磁盘;由此产生了大量的read流量,并且,随着程序运行,缓存会逐渐增多,所以后续read流量越来越少,逐渐变成之前的状态了。

极端状态下,如果没有缓存机制,真正意义上read和write是持平的。






推荐阅读
  • 我正在使用sql-serverkafka-connect和debezium监视sqlserver数据库,但是当我发布并运行我的wo ... [详细]
  • 这个问题困扰了我两天,卸载Dr.COM客户端(我们学校上网要装这个客户端登陆服务器,以后只能在网页里输入用户名和密码了),问题解决了。问题的现象:在实验室机台式机上安装openfire和sp ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 本文总结了初学者在使用dubbo设计架构过程中遇到的问题,并提供了相应的解决方法。问题包括传输字节流限制、分布式事务、序列化、多点部署、zk端口冲突、服务失败请求3次机制以及启动时检查。通过解决这些问题,初学者能够更好地理解和应用dubbo设计架构。 ... [详细]
  • Hadoop2.6.0 + 云centos +伪分布式只谈部署
    3.0.3玩不好,现将2.6.0tar.gz上传到usr,chmod-Rhadoop:hadophadoop-2.6.0,rm掉3.0.32.在etcp ... [详细]
  • zabbix中文乱码的问题
    在使用zabbix时,有时候会出现中文乱码的问题,如下:因为zabbix自身对中文简体的支持不完善,需要我们手动的去上传新的字体进行替换:1、在windows获取字体库文件在Windows上的 ... [详细]
  • ZooKeeper 学习
    前言相信大家对ZooKeeper应该不算陌生。但是你真的了解ZooKeeper是个什么东西吗?如果别人面试官让你给他讲讲ZooKeeper是个什么东西, ... [详细]
  • 开发笔记:MyBatis学习之逆向工程
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了MyBatis学习之逆向工程相关的知识,希望对你有一定的参考价值。转载:http://w ... [详细]
  • 03Spring使用注解方式注入
    基于注解的DI注入1.导包环境搭建:导入aop包(spring-aop-4.1.6.RELEASE.jar)2.创建类3.创建spring.xml配置文件(必须在src目录下)该配 ... [详细]
  • zookeeper集群查看状态时报错Error contacting service. It is
    最近在搭建mq集群时候需要用到,zookeeper,可是启动的时候显示成功了,查看状态的时候却报错了:碰到这个问题也是研究好好半天才解决,这里就总结出 ... [详细]
  • 前言折腾了一段时间hadoop的部署管理,写下此系列博客记录一下。为了避免各位做部署这种重复性的劳动,我已经把部署的步骤写成脚本,各位只需要按着本文把脚本执行完,整个环境基本就部署 ... [详细]
  • Zookeeper为分布式环境提供灵活的协调基础架构。ZooKeeper框架支持许多当今最好的工业应用程序。我们将在本章中讨论ZooKeeper的一些最显着的应用。雅虎ZooKee ... [详细]
  • 本文_大数据之非常详细Sqoop安装和基本操作
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了大数据之非常详细Sqoop安装和基本操作相关的知识,希望对你有一定的参考价值。大数据大数据之 ... [详细]
author-avatar
Kermit68_629
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有