云平台监听及性能优化

云平台监听及性能优化

关于oVirt云平台的介绍可以参考我的另一篇文章’oVirt架构’


Monitoring

对象:
  • 虚拟机,主机,存储域
资源:
  • 内存,CPU,磁盘…
意义:
  • 以此来观察平台的运行状态,提高平台的稳定性,给某些操作提供必要的数据,例如高可用,负载均衡…
目前大规模部署下遇到的问题:
  • 在大规模的情况下,会有很多的数据,监听这些数据包括对数据的搜集,处理,存储起来,这是一个很耗时的过程
  • 监听必须是要持续不断的进行,运行在后端,牵动着engine和nodes

优化方案

虚拟机的监听
  • 包含的属性:虚拟机状态,异步数据,设备信息,静态数据
3.6以前版本的监听机制
  • 基于定时任务polling机制的
  • 每三秒钟向每一台主机拉取运行着的虚拟机的信息,然后engine再在获取数据库内保存的信息,对比两者的信息,找出改变的虚拟机,然后保存到数据库,这样静态的数据也是每次都更新,就会多耗资源
  • 每5个周期才统计改变的数据, 虚拟机devices另外操作当他们的hash值改变了
  • 基于这种机制大规模部署会出现的问题,虚拟机不经常变的属性还是有很多的,这就会导致CPU高消耗和数据库的高负载
针对上面的问题,目前的解决方案:
  • 添加一个全局的缓存层(可以减少和数据库的互动操作,但是CPU高消耗没有解决)
  • 分发监控流程(解决了CPU的高消耗问题,但是没有减少数据库的高负载问题)
    NOTE:以上这两种方案都太复杂了
改进监测程序
频繁的写数据库情形

静态数据不监听

devices很少的改变,通过hash值判断
每一个周期内都统计改变的数据
异步数据脱离出来进行判断,例如虚拟机的IP就是需要实时报告的,但是虚拟机关机reason就不需要了
处理方法:
减少往数据库里面写的属性,引入了@UnchangeableByVdsm装饰器,用来标志属性不需要从后端返回。在文件VmDynamic.java内

@UnchangeableByVdsm
private String vmHost;
@UnchangeableByVdsm
private Date lastStartTime;
@UnchangeableByVdsm
private Guid runOnVds;
@UnchangeableByVdsm
private String stopReason; //等一系列的属性

将频繁更改的字段移动到统计数据

例如虚拟机的内存cached/buffered/free,频繁改变的属性分到另一个表里面的保存

分离虚拟机devices监听

vdsm层会返回Hash值和engine数据库内保存的上一次的匹配,这样只要保存hash就可以了,当Hash值变了才会去更新表vm_device

大批量读取数据库的数据
  • 会导致大量的数据库连接
  • 长时间的数据库查询
  • 即使没有数据改变也会读数据库
处理方法:

优化代码消除不需要的数据进程
例如根据虚拟机获取numa节点上的cpu,这个就不用通过每台虚拟机都去获取下
Memorization
提供memorization机制反复查询

启用较轻的专用查询

1: narrow down ‘vms’ view
explain analyze select * from vms where …
Planning time: 2.947 ms
Execution time: 765.774 ms
explain analyze select * from vms_monitoring_view where …
Planning time: 0.387 ms
Execution time: 275.600 ms

2: query only dynamic data
explain analyze select * from vms_monitoring_view where …
Planning time: 0.405 ms
Execution time: 275.850 ms
explain analyze select * from vm_dynamic where …
Planning time: 0.109 ms
Execution time: 2.703 ms

不同属性分表保存,分表查询

平台代码流程

平台初始化过程
  • 创建数据中心->集群->添加主机(创建网络)->附加存储->创建虚拟机
  • 这一套动作下来生成了一个资源池,ResourceManager.java,里面包含HostMonistoring/VmMonistoring
  • 当往平台加入一台主机的时候,就会建立和这台主机相关的监听机制(主机和主机上虚拟机的监听),在VdsManager.java里面实现的

    vmsRefresher = getRefresherFactory().create(this);
    vmsRefresher.startMonitoring();

  • RefresherFactory.java

    private VmStatsRefresher getRefresherForVds(VdsManager vdsManager) {
        Version version = vdsManager.getCompatibilityVersion();
        VDS vds = vdsManager.getCopyVds();
        if (FeatureSupported.jsonProtocol(version)
                && VdsProtocol.STOMP == vds.getProtocol()
                && FeatureSupported.vmStatsEvents(version)
                && FeatureSupported.events(version)) {
            return new EventVmStatsRefresher(vdsManager);
        }
        return new PollListAndAllVmStatsRefresher(vdsManager);
    }
  • EventVmStatsRefresher.java
public void startMonitoring()里面有allVmStatsOnlyRefresher.startMonitoring(); //文件PollVmStatsRefresher.java
    public void startMonitoring() {  //启动定时任务poll,
        vmsMonitoringJobId =
                scheduler.scheduleAFixedDelayJob(
                        this,
                        "poll",
                        new Class[0],
                        new Object[0],
                        0,
                        refreshRate,
                        TimeUnit.MILLISECONDS);
    }

    @OnTimerMethodAnnotation("poll")
    public void poll() {  //定时的去后台获取主机上的虚拟机的信息
        if (vdsManager.isMonitoringNeeded()) {
            VmsListFetcher fetcher = getVmsFetcher();

            long fetchTime = System.nanoTime();
            if (fetcher.fetch()) {
                getVmsMonitoring(fetcher, fetchTime).perform();
            } else {
                log.info("Failed to fetch vms info for host '{}' - skipping VMs monitoring.", vdsManager.getVdsName());
            }
        }

    public boolean fetch() {
        VDSReturnValue getList =
                getResourceManager().runVdsCommand(
                        VDSCommandType.List,
                        new VdsIdAndVdsVDSCommandParametersBase(vdsManager.getCopyVds()));
        if (getList.getSucceeded()) {
            vdsmVms = (Map<Guid, VmInternalData>) getList.getReturnValue();
            onFetchVms();  //里面会有filterVms();函数过滤出符合的虚拟机
            return true;
        } else {
            onError();
            return false;
        }
    }

    protected void filterVms() {
        for (VmInternalData vdsmVm : vdsmVms.values()) {
            VM dbVm = dbVms.get(vdsmVm.getVmDynamic().getId());

            gatherChangedVms(dbVm, vdsmVm); //通过状态来判断是否更新虚拟机信息 if (statusChanged(dbVm, vdsmVm.getVmDynamic()))
            gatherVmsWithChangedDevices(dbVm, vdsmVm);  根据返回的devices相关的信息来判断是否更新虚拟机isDevicesChanged()
        }

    //这里面的Hash值设置很巧妙
    public static boolean isDevicesChanged(VM dbVm, VmInternalData vdsmVm) {
        // Update only running VMs
        VmDynamic vdsmVmDynamic = vdsmVm.getVmDynamic();
        return
                vdsmVmDynamic != null &&
                vdsmVmDynamic.getStatus() != VMStatus.MigratingTo &&
                vdsmVmDynamic.getHash() != null &&
                dbVm != null &&
                !Objects.equals(dbVm.getHash(), vdsmVmDynamic.getHash());
    }

    final String hostname = vdsManager.getVdsHostname();
    resourceManager.subscribe(new EventSubscriber(hostname + "|*|VM_status|*") {   //VM_status和vdsm里面的字段一致,在这里订阅这个消息,当遇到虚拟机属性或状态发生改变时,vdsm层就会发布相关的消息出来,这里就能接受到消息然后进行相关的操作
        @Override
        public void onSubscribe(Subscription sub) {
            subscription = sub;
            subscription.request(1);
        }

        @Override
        public void onNext(Map<String, Object> map) {
            try {
                printEventInDebug(map);

                List<Pair<VM, VmInternalData>> changedVms = new ArrayList<>();
                List<Pair<VM, VmInternalData>> devicesChangedVms = new ArrayList<>();
                convertEvent(changedVms, devicesChangedVms, map);

                if (!changedVms.isEmpty() || !devicesChangedVms.isEmpty()) {
                    getVmsMonitoring(changedVms, devicesChangedVms).perform();
                }
            } finally {
                subscription.request(1);
            }
        }
}
  • 平台已经在大力推广使用STOMP传输协议,
  • 当添加主机的时候会创建一系列的相关监听事件
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值