使用libvirt-java采集KVM虚拟机状态信息

弦隙代码
• 阅读 1922

虚拟化开发相较于普通开发是一个冷门的方向,大多数是使用Python开发,其中使用Java来做虚拟化的更是少之又少,资料更是少的可怜,为了实现需求我也是踩了不少坑,今天就为大家分享一下如何使用 libvirt-java 来采集KVM虚拟机的资源使用信息。

CPU使用率

libvirt并没有直接提供获取虚拟机CPU使用率的接口,需要我们自己来计算,网上分享的代码或者公式五花八门,大部分都是错误的,经过我的测试,找到了一个相对准确的计算公式。

cpu_usage = (cpu_time_now - cpu_time_t_second_ago) * 100 / (t * vCpus * 10^9)

Java代码如下

// t秒前的CPU时间
long c1 = domain.getInfo().cpuTime;
Thread.sleep(1000);
// 当前CPU时间
long c2 = domain.getInfo().cpuTime;

// 虚拟CPU数量
int vCpus = domain.getMaxVcpus();
// t 为1秒
Double cpuUsage = 100 * (c2 - c1) / (1 * vCpus * Math.pow(10, 9));
log.debug("虚拟机[{}]CPU使用率为: {}", uuid, cpuUsage);

内存使用率

不要使用domain.getInfo()返回的 memory字段,虽然它注释写的是the memory in KBytes used by the domain,但它的意思真的不是虚拟机内部进程已使用的内存大小,而是从宿主机器的角度来看分配给这个虚拟机的内存它使用了多少,如果没有特殊配置,它会和maxMem字段的值是相同的。

正确做法是使用domain.memoryStats(10)来获取,那为什么参数要输入一个10呢?这是因为10代表的是要返回的信息数量,经过我手动执行virsh dommemstat uuid 测试发现有10个参数返回,所以需要填入10。另外命令返回的unused 字段值与数组中tag=8的数据一致,最终我们获取到了未使用的内存大小,计算内存使用率更是轻轻松松。

Java代码如下

MemoryStatistic[] memoryStatistics = domain.memoryStats(10);
Optional<MemoryStatistic> first = Arrays.stream(memoryStatistics).filter(x -> x.getTag() == 8).findFirst();
if (first.isPresent()) {
  MemoryStatistic memoryStatistic = first.get();
  long unusedMemory = memoryStatistic.getValue();
  long maxMemory = domain.getMaxMemory();
  double memoryUsage = (maxMemory - unusedMemory) * 100.0 / maxMemory;
  log.debug("虚拟机[{}]内存使用率为: {}", uuid, memoryUsage);
}

网卡数据包信息

同样libvirt并没有提供获取虚拟机网卡的接口,因此需要获取虚拟机的xml文件来查询。

此处没有什么坑,解析xml是使用了html解析库Jsoupxml算是html的亲戚吧,比html书写严格很多,解析数据更为方便。

获取到网卡名称之后再获取统计信息,可以获取的数据有:

字段含义
rx_bytes接收数据包大小
rx_packets接收数据包数量
rx_errs接收错误数据包数量
rx_drop接收丢弃数据包数量
tx_bytes发送数据包大小
tx_packets发送数据包数量
tx_errs发送错误数据包数量
tx_drop发送丢弃数据包数量

Java代码如下

String xmlDesc = domain.getXMLDesc(0);
Document document = Jsoup.parse(xmlDesc);

// 网卡
Elements interfaces = document.getElementsByTag("devices").get(0).getElementsByTag("interface");
for (Element inter : interfaces) {
  String interName = inter.getElementsByTag("target").get(0).attr("dev");
  DomainInterfaceStats domainInterfaceStats = domain.interfaceStats(interName);
  log.debug("dev {} stats {}", interName, Json.toJsonString(domainInterfaceStats));
}

磁盘IO信息

和网卡同样,libvirt也没有提供获取虚拟机磁盘的接口,还是需要获取虚拟机的xml文件来查询,获取到磁盘名称之后再获取统计信息,可以获取的数据有:

字段含义
rd_req读取请求总数
rd_bytes读取的数据大小
wr_req写入请求总数
wr_bytes写入的数据大小
errs失败次数

Java代码如下

String xmlDesc = domain.getXMLDesc(0);
Document document = Jsoup.parse(xmlDesc);
// 磁盘
Elements disks = document.getElementsByTag("devices").get(0).getElementsByTag("disk");
for (Element disk : disks) {
  String dev = disk.getElementsByTag("target").get(0).attr("dev");
  DomainBlockStats domainBlockStats = domain.blockStats(dev);
  log.debug("dev {} stats {}", dev, Json.toJsonString(domainBlockStats));
}

至此采集虚拟机状态信息算是告一段落,学的越多才发现不会的越多...

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
VBox 启动虚拟机失败
在Vbox(5.0.8版本)启动Ubuntu的虚拟机时,遇到错误信息:NtCreateFile(\\Device\\VBoxDrvStub)failed:0xc000000034STATUS\_OBJECT\_NAME\_NOT\_FOUND(0retries) (rc101)Makesurethekern
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这