云平台监听及性能优化

云平台监听及性能优化

关于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传输协议,
  • 当添加主机的时候会创建一系列的相关监听事件
### ComfyUI 云平台使用说明与部署指南 #### 一、ComfyUI 云平台概述 ComfyUI 是一种用于生成艺术作品的人工智能工具,支持多种节点化的工作流设计方式。相较于传统 WebUI 工具,其功能更为强但也带来了较高的学习门槛和技术复杂度[^1]。为了降低开发者和用户的入门难度,一些云计算服务提供商推出了针对 ComfyUI 的优化解决方案。 通过云端一键部署的方式,用户无需手动安装复杂的环境依赖即可快速启动项目。例如,基于阿里云 PAI-EAS 提供的服务,可以通过自定义部署选项完成模型加载和服务上线过程[^2]。此外,部分教程还介绍了如何利用云主机中的 Linux 系统作为运行环境来进一步扩展应用能力[^3]。 --- #### 二、ComfyUI 云平台的部署步骤详解 以下是综合多个资料整理出来的典型云端部署方案: 1. **获取必要的资源** 用户需先申请并获得相应的计算资源权限。这通常涉及注册账号以及领取免费额度或者购买付费套餐以满足实际需求。 2. **设置运行环境** 在选定的目标服务器实例上初始化操作系统镜像之后,按照官方文档指示准备好 Python 虚拟环境以及其他必备软件包版本号匹配情况下的兼容性验证测试环节必不可少。 3. **上传所需文件至远程机器** 如果采用的是具备图形界面管理面板形式的产品,则可以直接拖拽本地磁盘内的压缩包到指定位置;而对于纯命令行交互模式下工作的虚拟机来说,则推荐借助 SCP 命令行工具来进行批量数据迁移作业处理效率更高些。 4. **执行脚本自动化构建流程** 利用 Git 版本控制系统克隆仓库地址下来后,再依据具体业务场景定制修改默认参数设定值等内容后再提交给后台调度器去排队等待被执行完毕返回结果反馈信息显示出来为止整个周期结束才算真正意义上的完成了全部准备工作阶段的任务目标达成状态确认无误才行哦! ```bash git clone https://github.com/comfyanonymous/ComfyUI.git cd ComfyUI pip install -r requirements.txt ``` 5. **启动服务监听端口对外提供访问接口调用功能支持** 当所有的前置条件都已经妥善安排妥当以后就可以正式开启 HTTP RESTful API 或者 WebSocket 实时消息推送机制之类的通信协议层面上面的东西啦! --- #### 三、注意事项及常见问题排查建议 - **性能瓶颈分析**: 若发现渲染速度过慢可能是因为 GPU 加速未启用成功或者是内存不足等原因引起卡顿现象发生频率增加的情况需要注意调整分配比例小合理规划硬件资源配置策略从而达到最佳平衡点效果最化收益回报率提升显著可见成效明显改善用户体验满意度水平提高很多倍数以上不等具体情况视实际情况而定而已矣罢了呵呵哒~ - **安全性考量因素**: 访问控制列表 ACL 设置不当容易造成敏感信息泄露风险隐患存在因此务必严格遵循最小特权原则只授予必需的操作权限范围之外的一切请求都应该被拒绝掉以免带来不必要的麻烦困扰影响正常运营秩序稳定健康发展态势良好持续向前迈进不断追求卓越成就非凡伟业共创辉煌未来前景可期值得期待哟亲们快来加入我们的行列一起携手共进吧朋友们加油干起来呀少年少女们冲鸭!!! --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值