一、项目背景
需要实时监控云服务器上实例的云盘IOPS(次/s),类似于腾讯云和阿里云的监控数据
二、开发实现思路
通过Prometheus监控系统,按一定的规则采集OpenStack宿主机上各虚拟机的数据,保存在时序库中,再按照产品需求,按照一定的算法,将数据展示在对应页面上
三、测试环境准备
A、Linux服务器一台
1、在Linux服务器上搭建一个ftp服务器(可用phpstudy工具,正在研究中,后续分享)
2、在Linux机器上安装nmon,可参考:https://www.jianshu.com/p/f3282733d245
3、在本地windows机器上安装工具FlashFXP,可上传下载文件产生带宽,流量,IO和网络
四、测试方法--Linux系统
云盘IOPS(次/s),包括硬盘读次数(即硬盘平均每秒读次数)和写次数(即硬盘平均每秒写次数)
1、测试硬盘读次数:
A、用工具FlashFXP工具连接到开启了ftp服务的目录例如:/data2,对应磁盘sdb,不同磁盘对应的目录不一样

B、测试硬盘读次数,即从服务器下载文件,且限制速度为1024KB/秒(限速的目的是为了使数据稳定,便于测试)


C、在nmon中导出.nmon文件数据,硬盘读次数对应DISKXFER中的数据(单位为次数或个)

D、对比测试数据
截图为腾讯云的数据,仅供参考

2、测试硬盘写次数:
A、用工具FlashFXP工具连接到开启了ftp服务的目录例如:/data2,对应磁盘sdb,不同磁盘对应的目录不一样

B、测试硬盘写次数,即上传文件至服务器,且限制速度为1024KB/秒(限速的目的是为了使数据稳定,便于测试)


C、在nmon中导出.nmon文件数据,硬盘写次数对应DISKXFER中的数据(单位为次数或个)

D、对比测试数据
截图为腾讯云的数据,仅供参考

五、测试方法--Windows系统
云盘IOPS(次/s),包括硬盘读次数(即硬盘平均每秒读次数)和写次数(即硬盘平均每秒写次数)
1、测试硬盘读次数:
A、用工具FlashFXP工具连接到开启了ftp服务的目录例如:D:,不同磁盘对应的目录不一样

B、测试硬盘读流量,即从Windows2008机器下载文件至本机,且限制速度为1024KB/秒(限速的目的是为了使数据稳定,便于测试)


C、通过Python脚本查看读次数,在Python脚本所在目录,执行命令:python3 view.py io(或者python view.py io),打出的日志中,“read_count”即为硬盘读次数
# -*- coding: utf-8 -*-
import psutil
import collections
import time
import os,sys
def get_os_info():
#开机时间
boot_time = psutil.boot_time()
def get_cput_info():
cpu = psutil.cpu_times_percent(interval=1.00)
cpu_percent_every = psutil.cpu_percent(interval=1,percpu=True)
cpu_percent = psutil.cpu_percent(interval=1)
return "{'user':"+str(cpu.user)+",'system':"+str(cpu.system)+",'idle':"+str(cpu.idle)+"'physical_count':"+str(psutil.cpu_count(logical=False))+"'logic_count':"+str(psutil.cpu_count())+",cpu_percent:"+str(cpu_percent)+",cpu_percent_every:"+str(cpu_percent_every)+"}"
def get_mem_info():
#单位是MB
mem = psutil.virtual_memory()
return "{'total':"+str(mem.total//1024//1024)+"MB,'free':"+str(mem.free//1024//1024)+"MB,'used':"+str(mem.used//1024//1024)+"MB,'use_percent':"+str((mem.used/mem.total)*100)+"%}"
def get_disk_info():
"""
获取磁盘属性信息
:return: json样例如下
{
"total": 100, //磁盘总大小GB
"used": 20, //磁盘使用大小GB
"partitions": [{ //各分区情况
"name": "c", //分区名称
"total": "30", //分区大小GB
"free": "10" //分区还剩空间GB
}, {
"name": "d",
"total": "30",
"free": "10"
}]
}
"""
json = ""
partitions = "["
disk_total = 0
disk_free = 0
disk_used = collections.OrderedDict()
for id in psutil.disk_partitions():
if 'cdrom' in id.opts or id.fstype == '':
continue
disk_name = id.device.split(':')
s = disk_name[0]
disk_info = psutil.disk_usage(id.device)
disk_total = disk_total + (disk_info.total // 1024 // 1024 // 1024)
disk_free = disk_free + (disk_info.free // 1024 // 1024 // 1024)
partitions = partitions + "{'name':'"+s+"','total':"+str(disk_info.total // 1024 // 1024 // 1024)+",'free':"+str(disk_info.free // 1024 // 1024 // 1024)+",'perent':"+str(disk_info.percent)+"},"
partitions = partitions.rstrip(",")+ "]"
json = "{'total':"+str(disk_total)+",'free':"+str(disk_free)+",'partitions':"+partitions+"}"
return json
########
# 获取开机以来 接收/发送 的字节数
# 参数(sent): Ture--返回发送的字节数 , False--不返回
# 参数(recv): Ture--返回接收的字节数 , False--不返回
# 两个参数都为(True): 返回包含 接收/发送 字节数的列表
# 函数失败返回: None
def io_get_bytes(sent=False,recv=False):
internet = psutil.net_io_counters() # 获取与网络IO相关的信息
if internet == None: # 如果获取IO信息失败
return None
io_sent = internet.bytes_sent # 开机以来发送的所有字节数
io_recv = internet.bytes_recv # 开机以来接收的所有字节数
if sent == True and recv == True :
return [io_sent,io_recv]
elif sent == True:
return io_sent
elif recv == True:
return io_recv
else:
return None # 参数不正确, 返回None
def get_net_info():
#单位是KB
interval = 60 # 每隔 interval 秒获取一次网络IO信息, 数值越小, 测得的网速越准确
k = 1024 # 一 K 所包含的字节数
m = 1048576 # 一 M 所包含的字节数
byteSent1 = io_get_bytes(sent=True) # 获取开机以来上传的字节数
byteRecv1 = io_get_bytes(recv=True) # 获取开机以来下载的字节数
#print (byteSent1)
#print (byteRecv1)
time.sleep(interval) # 间隔 1 秒
#os.system('cls') # 执行清屏命令
byteSent2 = io_get_bytes(sent=True) # 再次获取开机以来上传的字节数
byteRecv2 = io_get_bytes(recv=True) # 再次获取开机以来下载的字节数
sent = (byteSent2-byteSent1)/1024/1024/60 # interval 秒内所获取的上传字节数 KB
recv = (byteRecv2-byteRecv1)/1024/1024/60 # interval 秒内所获取的下载字节数 KB
return "{'up_speed':"+str(sent)+"MB,'down_speed':"+str(recv)+"MB}"
def get_disk_io():
disk_io_pre = psutil.disk_io_counters()
time.sleep(1)
disk_io_now = psutil.disk_io_counters()
r_count = (disk_io_now.read_count-disk_io_pre.read_count)
w_count = (disk_io_now.write_count-disk_io_pre.write_count)
r_m =(disk_io_now.read_bytes-disk_io_pre.read_bytes)
w_m =(disk_io_now.write_bytes-disk_io_pre.write_bytes)
return ('"read_count:"%s,"write_count:"%s,"read_byte:"%s,"write_byte:"%s')%(str(r_count),str(w_count),str(r_m),str(w_m))
if __name__ == '__main__':
while True:
disk_info = get_disk_info
cpu_info = get_cput_info
mem_info = get_mem_info
net_info = get_net_info
disk_io = get_disk_io
info = {'cpu':cpu_info,'mem':mem_info,'disk':disk_info,'net':net_info,'io':disk_io}
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+': '+info[sys.argv[1]]())
try:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+': '+info[sys.argv[1]]())
time.sleep(1)
except:
print (
'''
Use:
python view.py [cpu/mem/disk/net/io]
'''
)
break

D、对比测试数据
截图为腾讯云的数据,仅供参考

2、测试硬盘写次数:
A、用工具FlashFXP工具连接到开启了ftp服务的目录例如:D:,不同磁盘对应的目录不一样

B、测试硬盘读流量,即从本机上传文件至Windows2008机器,且限制速度为1024KB/秒(限速的目的是为了使数据稳定,便于测试)


C、通过Python脚本查看写次数,在Python脚本所在目录,执行命令:python3 view.py io(或者python view.py io),打出的日志中,“write_count”即为硬盘写次数
# -*- coding: utf-8 -*-
import psutil
import collections
import time
import os,sys
def get_os_info():
#开机时间
boot_time = psutil.boot_time()
def get_cput_info():
cpu = psutil.cpu_times_percent(interval=1.00)
cpu_percent_every = psutil.cpu_percent(interval=1,percpu=True)
cpu_percent = psutil.cpu_percent(interval=1)
return "{'user':"+str(cpu.user)+",'system':"+str(cpu.system)+",'idle':"+str(cpu.idle)+"'physical_count':"+str(psutil.cpu_count(logical=False))+"'logic_count':"+str(psutil.cpu_count())+",cpu_percent:"+str(cpu_percent)+",cpu_percent_every:"+str(cpu_percent_every)+"}"
def get_mem_info():
#单位是MB
mem = psutil.virtual_memory()
return "{'total':"+str(mem.total//1024//1024)+"MB,'free':"+str(mem.free//1024//1024)+"MB,'used':"+str(mem.used//1024//1024)+"MB,'use_percent':"+str((mem.used/mem.total)*100)+"%}"
def get_disk_info():
"""
获取磁盘属性信息
:return: json样例如下
{
"total": 100, //磁盘总大小GB
"used": 20, //磁盘使用大小GB
"partitions": [{ //各分区情况
"name": "c", //分区名称
"total": "30", //分区大小GB
"free": "10" //分区还剩空间GB
}, {
"name": "d",
"total": "30",
"free": "10"
}]
}
"""
json = ""
partitions = "["
disk_total = 0
disk_free = 0
disk_used = collections.OrderedDict()
for id in psutil.disk_partitions():
if 'cdrom' in id.opts or id.fstype == '':
continue
disk_name = id.device.split(':')
s = disk_name[0]
disk_info = psutil.disk_usage(id.device)
disk_total = disk_total + (disk_info.total // 1024 // 1024 // 1024)
disk_free = disk_free + (disk_info.free // 1024 // 1024 // 1024)
partitions = partitions + "{'name':'"+s+"','total':"+str(disk_info.total // 1024 // 1024 // 1024)+",'free':"+str(disk_info.free // 1024 // 1024 // 1024)+",'perent':"+str(disk_info.percent)+"},"
partitions = partitions.rstrip(",")+ "]"
json = "{'total':"+str(disk_total)+",'free':"+str(disk_free)+",'partitions':"+partitions+"}"
return json
########
# 获取开机以来 接收/发送 的字节数
# 参数(sent): Ture--返回发送的字节数 , False--不返回
# 参数(recv): Ture--返回接收的字节数 , False--不返回
# 两个参数都为(True): 返回包含 接收/发送 字节数的列表
# 函数失败返回: None
def io_get_bytes(sent=False,recv=False):
internet = psutil.net_io_counters() # 获取与网络IO相关的信息
if internet == None: # 如果获取IO信息失败
return None
io_sent = internet.bytes_sent # 开机以来发送的所有字节数
io_recv = internet.bytes_recv # 开机以来接收的所有字节数
if sent == True and recv == True :
return [io_sent,io_recv]
elif sent == True:
return io_sent
elif recv == True:
return io_recv
else:
return None # 参数不正确, 返回None
def get_net_info():
#单位是KB
interval = 60 # 每隔 interval 秒获取一次网络IO信息, 数值越小, 测得的网速越准确
k = 1024 # 一 K 所包含的字节数
m = 1048576 # 一 M 所包含的字节数
byteSent1 = io_get_bytes(sent=True) # 获取开机以来上传的字节数
byteRecv1 = io_get_bytes(recv=True) # 获取开机以来下载的字节数
#print (byteSent1)
#print (byteRecv1)
time.sleep(interval) # 间隔 1 秒
#os.system('cls') # 执行清屏命令
byteSent2 = io_get_bytes(sent=True) # 再次获取开机以来上传的字节数
byteRecv2 = io_get_bytes(recv=True) # 再次获取开机以来下载的字节数
sent = (byteSent2-byteSent1)/1024/1024/60 # interval 秒内所获取的上传字节数 KB
recv = (byteRecv2-byteRecv1)/1024/1024/60 # interval 秒内所获取的下载字节数 KB
return "{'up_speed':"+str(sent)+"MB,'down_speed':"+str(recv)+"MB}"
def get_disk_io():
disk_io_pre = psutil.disk_io_counters()
time.sleep(1)
disk_io_now = psutil.disk_io_counters()
r_count = (disk_io_now.read_count-disk_io_pre.read_count)
w_count = (disk_io_now.write_count-disk_io_pre.write_count)
r_m =(disk_io_now.read_bytes-disk_io_pre.read_bytes)
w_m =(disk_io_now.write_bytes-disk_io_pre.write_bytes)
return ('"read_count:"%s,"write_count:"%s,"read_byte:"%s,"write_byte:"%s')%(str(r_count),str(w_count),str(r_m),str(w_m))
if __name__ == '__main__':
while True:
disk_info = get_disk_info
cpu_info = get_cput_info
mem_info = get_mem_info
net_info = get_net_info
disk_io = get_disk_io
info = {'cpu':cpu_info,'mem':mem_info,'disk':disk_info,'net':net_info,'io':disk_io}
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+': '+info[sys.argv[1]]())
try:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+': '+info[sys.argv[1]]())
time.sleep(1)
except:
print (
'''
Use:
python view.py [cpu/mem/disk/net/io]
'''
)
break

D、对比测试数据
截图为腾讯云的数据,仅供参考

网友评论