首届云原生编程挑战赛总决赛亚军比赛攻略(ONE PIECE团队)

关联比赛:  首届云原生编程挑战赛【复赛】实现一个 Serverless 计算服务调度系统

比赛攻略—ONE PIECE团队

代码链接:

初赛:GitHub - czy-gm/containerScheduler: 2020天池首届云原生编程挑战赛亚军-初赛赛道二(实现规模化容器静态布局和动态迁移)方案
复赛:GitHub - czy-gm/serverlessScheduler: 2020天池首届云原生编程挑战赛亚军-复赛(实现一个 Serverless 计算服务调度系统)方案

初赛(赛道二,语言Java)

1 赛题背景分析及理解

1.1赛题介绍

实现规模化容器静态布局和动态迁移:

1)规模化容器静态布局场景。我们准备了确定数量多规格机器资源,使得在满足调度约束条件下,确定数量、多种类的应用容器能在这些机器资源上满足扩容诉求,保证建站的确定性(赛题中我们会给出充足的机器,但真正建站场景我们会先通过计算预估机器)。

2)规模化容器动态迁移场景。我们会准备一个集群容器静态布局数据,此时集群是一种碎片态。然后通过容器的迁移,按照规则要求尽可能腾空机器资源,并过滤空机器,使得碎片态集群现状重新成为饱满态。

1.2赛题分析

静态布局问题可以理解为多约束的多维装箱问题,约束有资源、绑核、堆叠和打散,约束条件多,判断约束条件的时间较长。

考虑在三个方面着手:

  1. 减少判断约束条件的时间,以扩大搜索解空间的范围
  2. 选择一个好的初始解,解空间很大,在比赛给出的时间内能搜索的范围很小,这时好的初始解很重要。
  3. node的选择,对于不同规格的容器,node的选择顺序决定了node资源的使用情况。

动态迁移问题可以从两个思路解决:

  1. 先将所有容器按照静态布局的方案进行放置,再通过前后位置的差异进行迁移
  2. 使用策略判断是否需要迁移,逐渐减少node的使用数
    综上,初赛考察的是复杂的装箱问题,在有限的时间内找到较优解,动态迁移使用较少的迁移次数达到饱和态。

2 核心思路

静态布局考虑了两个方案,一是使用模拟退火,二是模拟退火+局部DP。因为使用模拟退火时,后面的node资源利用率较差,可以用DP来改进这一缺陷。首先先试验使用DP能够跑多大的数据规模,每次判断约束条件的时间大约在500ms,在调整数据结构后,时间降低至200~300ms,但DP也只能跑几个node,无法配合模拟退火。

最终方案主体采用模拟退火,pods根据cpu/ram从小到大排序,nodes根据与pod的资源不匹配分数从小到大排序。

动态迁移先将不满足约束的pod进行迁移,然后采用静态布局的方法将每个pod重新放置,根据布局前后的位置不同决定是否需要迁移。不采取任何优化时,迁移次数在8000-8300。考虑到静态布局后,PodA的原node可能存在同规格的PodB,可以交换两者位置,PodA就不用迁移,经过优化后迁移次数在4000~4200。

优化策略如图所示:
 

enter image description here


图1 优化前(PodA和PodB都需要迁移)

enter image description here


图2 优化后(PodA和PodB交换位置,PodA不需要迁移)

在迁移过程中,可能存在死锁情况,都在等待对方迁移空出位置,需要跳转到中转node解除死锁。方案如图所示:

enter image description here


图3 优化前(PodA和PodB形成死锁)

enter image description here


图4 优化后(根据迁移顺序,解除死锁)

复赛(语言Golang)

3 赛题背景分析及理解

3.1赛题介绍

一个简化的Faas系统分为APIServer,Scheduler,ResourceManager,NodeService,ContainerService 5个组件,本题目中APIServer,ResourceManager,NodeService,ContainerService由平台提供,Scheduler的AcquireContainer和ReturnContainer API由选手实现(gRPC服务,语言不限),Scheduler会以容器方式单实例运行,无需考虑分布式多实例问题。

其中测试函数由平台提供,可能包含但不局限于helloworld,CPU intensive,内存intensive,sleep等类型;调用模式包括稀疏调用,密集调用,周期调用等;执行时间包括时长基本固定,和因输入而异等。

选手对函数的实现无感知,可以通过Scheduler的AcquireContainer和ReturnContainer API的调用情况,以及NodeService.GetStats API获得一些信息,用于设计和实现调度策略。

3.2赛题分析

赛题需要完成AcquireContainer和ReturnContainer两个接口,根据请求函数分配相应的node和container,主要考察node的资源分配,以及请求的响应时间。

评分从两个方面,总的响应时间RT和资源使用时间ND,两者的权重都是0.5,分数是与基准分相比得出的,所以基准的实现策略对选手的策略有很大影响。

node的初始可用数只有10个,需要过一段时间才可以申请新的node,总的可用node数为20个。要规划好node的资源分配,避免前期请求申请超过初始node时出错,造成惩罚性分数。

内存密集型函数占用内存较大,同一container同时运行多个实例,可能会导致OOM,cpu密集型函数也尽量避免同一container运行多个实例,可能会造成超时,这两种情况也会有惩罚性分数。

有些函数(如helloworld、sleep等)占用资源很小,同一container同时运行多个实例,响应时间变化不大,可以减少创建容器的时间。

4 核心思路

由于赛题使用grpc,不限制语言的使用,对于比拼速度的比赛,语言的选择也是考虑的一方面,分别尝试使用c++,java,golang三种语言实现demo,经测试发现,c++与golang的速度差不多,java要比其他两个慢10%~20%。Golang对于并发开发具有天生的优势,再加上官方提供了demo,所以最终选择了golang作为开发语言。

官方前期没有提供评测系统,每次提交系统需要等待1到3小时才能得到结果,等待结果的同时并不能并行开发,效率极低。通过线上跑出的日志,自己使用java实现了一个评测demo,每个函数的调用频率、调用时间、首次调用时间都可以通过日志分析出。由于无法模拟真实环境,所以NodeService只是实现基本功能,无法根据负载情况做出相应的执行时间。评测demo可以检验程序的正确性,以及资源的使用情况,避免了线上等待很久才发现出错的情况,提升了开发效率。

程序的整体策略就是负载均衡和动态扩缩,负载均衡提升响应速度,动态扩缩应对调用压力的变化以及不同数据,避免出现大规模的调用失败的情况。分别从以下几点着手:

选取node的策略

  1. 如果当前请求函数的并发数大于现有的node数,且现有node不超过初始node数量(设定10个node),则获取新的node创建容器,目的是充分利用前期仅能获取的初始node,让每个node响应较少的请求,可以更快的创建容器以及更快的响应速度。
  2. 使函数均匀分布在每个node,首先按照node内该函数容器数量排序,优先数量少的node,如果数量相同,优先可用内存多的node。目的是资源分配更加平均,避免资源抢占。
  3. 当初始node数不能再满足新的请求时,申请新的node,满足高压力的请求。

选取container的策略

  1. 当容器数大于等于请求数,每个容器同时满足一个请求。如果容器数不够,则创建新的容器。
  2. 如果该函数(不包括内存密集型和cpu密集型)当前不能再创建容器,则每个容器同时满足多个请求。

函数分类

  1. 当使用内存高于分配内存的30%时,判定为内存密集型函数。
  2. 当cpu使用率大于10%时,判定为cpu密集型函数。
  3. 当函数执行时间小于50ms时,判定为短时间型函数,若再超过65ms的上限,取消判定为短时间型函数。

动态缩减

  1. 根据cpu密集型容器的数量,初步判断可以缩减的node数量,判断依据是缩减后每个node内cpu密集型容器的数量不超过一定值(更优的方案是根据cpu负载情况判断数量),防止cpu资源紧张,响应时间过长。
  2. 选择使用内存最少的node,先校验是否满足迁移条件。迁移条件是剩余node的可用内存是否满足该node所有容器的需求,重点是内存密集型函数。
  3. 当满足迁移条件后,将该node的所有容器迁移到其他node,然后释放该node。当缩减数量达到预判值或者不再满足迁移条件,则停止该轮缩减。

    enter image description here

回收资源

  1. 部分函数可能会从密集调用变为稀疏调用,或者调用一段时间后就不再调用,这样会导致一些空闲容器,导致资源浪费(尤其是内存密集型会一直占用内存)。所以,当容器超过一定时间(设5分钟)没有执行函数时,则释放该容器。若node中没有容器,则释放该node。

根据以上几个策略,程序没有设定最终使用的node数,会根据实时压力动态扩缩。程序每次分配node,都是根据node的可用内存和函数的分配内存进行选择,并且内存密集型容器只会同时执行一个请求,避免发生OOM。cpu密集型容器只会同时执行一个请求,避免出现执行超时的情况。

根据基准分来看,RT相对与ND优化空间更大,所以重点优化响应时间,根据函数的分类指定多种策略:

函数执行优先级

函数:短时间型、cpu密集型(非短时间)、内存密集型(非短时间)

分析:cpu密集型和内存密集型函数一般执行时间较长,占用资源较多,与短时间型同时执行时,会存在资源竞争,导致短时间型执行时间增加至两到三倍。

策略:短时间型优先级比cpu密集型和内存密集型高,当短时间型正在执行时,cpu密集型和内存密集型等待其执行完毕或者等待超时。由于cpu密集型和内存密集型执行时间较长,等待的时间对其影响不大。

预留容器

函数:所有函数

分析:创建容器的时间在0.4~1.0s,大大增加了请求的响应时间,要尽量避免在请求到来时创建容器。部分函数由稀疏调用逐渐变为密集调用,可以在空闲时间提前创建容器。

策略:当某函数的容器满载时,则提前申请一个空闲容器,之后并发请求数增加时,省去创建容器的时间,减少了响应时间。

资源调整

函数:cpu密集型

分析:容器规格是由内存决定的,cpu和内存成比例,每1GB内存对应0.67cpu。cpu密集型执行时,可能存在cpu满载的情况,执行时间受资源限制不能再减少。

策略:当函数执行时cpu使用率高于分配的90%,则认为当前分配的cpu资源不足,先创建新容器再删除旧容器,新容器分配的内存是旧容器的200%,对应的cpu资源也是200%,减少函数的执行时间。

5 比赛经验总结和感想

初赛动态迁移部分,一开始选择直接迁移这个方案,简单实现后发现并不理想,然后就放弃了,赛后才发现这个方案要更优,应该多做一些尝试。在比赛中,学到了很多东西,也结识了很多大佬,感谢官方举办这次比赛。

查看更多内容,欢迎访问天池技术圈官方地址:首届云原生编程挑战赛总决赛亚军比赛攻略(ONE PIECE团队)_天池技术圈-阿里云天池

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/7177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高项-案例分析万能答案(作业分享)

项目管理:每天进步一点点~ 活到老,学到老 ヾ(◍∇◍)ノ゙ 何时学习都不晚,加油 一、通用问题原因: 1.项目经理管理经验不足,没有及时发现和解决xx方面的问题。 2.项目管理计划没有得到关键干系人的评审确…

yum常用命令与lrzsz的在线安装

yum命令 yum( Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 SUSE 中的 Shell 前端软件包管理器。 基于 RPM 包管理,能够从指定的服务器自动下载 RPM 包并且安装,可以自动处理依赖性关系,并且一次安装…

php基础知识快速入门

一、PHP基本知识 1、php介绍: php是一种创建动态交互性的强有力的服务器脚本语言,PHP是开源免费的,并且使用广泛。PHP是解释性语言,按顺序从上往下执行,无需编译,直接运行。PHP脚本在服务器上运行。 2、ph…

动态规划(dp)(二)

按摩师 按摩师 1.状态表示 dp【i】表示:到i位置时,此时最长时长 继续细化:在i位置选预约,或不选预约 f【i】:到i位置时,nums【i】必选的,最长时长 g【i】:到i位置时&#xff0c…

仅为娱乐,Python中如何重定义True为False?

在Python中,True 和 False 是内建的布尔常量,分别代表逻辑上的真和假。它们是不可变的,且在Python语言规范中具有特殊地位,不能被用户直接重定义。尝试给 True 或 False 赋予新的值是违反Python语言规则的,这样的操作会…

JS基础:变量的详解

你好,我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃,大专生,一枚程序媛,感谢关注。回复 “前端基础题”,可免费获得前端基础 100 题汇总,回复 “前端基础路线”,可获取…

零基础入门学习Python第二阶01生成式(推导式),数据结构

Python语言进阶 重要知识点 生成式(推导式)的用法 prices {AAPL: 191.88,GOOG: 1186.96,IBM: 149.24,ORCL: 48.44,ACN: 166.89,FB: 208.09,SYMC: 21.29}# 用股票价格大于100元的股票构造一个新的字典prices2 {key: value for key, value in prices.i…

Java的java.util.concurrent.ExecutorService简介

在Java并发编程的璀璨星空中,ExecutorService无疑是那颗最耀眼的明星。它不仅是Java并发编程的核心组件之一,更是构建高并发、高性能应用的秘密武器。今天,我们就来一场说走就走的探索之旅,揭开它的神秘面纱! &#x1…

深度学习中的不确定性量化:技术、应用和挑战综述(一)

不确定性量化(UQ)在减少优化和决策过程中的不确定性方面起着关键作用,应用于解决各种现实世界的科学和工程应用。贝叶斯近似和集成学习技术是文献中使用最广泛的两种UQ方法。在这方面,研究人员提出了不同的UQ方法,并测试了它们在各种应用中的…

Ansible自动化运维工具单模块介绍

前言 自动化运维是指利用自动化工具和技术来简化、自动化和优化IT基础设施的管理和运维过程,从而提高效率、降低成本,并减少人为错误。在当今复杂的IT环境中,自动化运维已经成为许多组织和企业提高生产力和保证系统稳定性的重要手段。Ansibl…

动态规划算法:路径问题

例题一 解法(动态规划): 算法思路: 1. 状态表⽰: 对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式: i. 从 [i, j] 位置出发,巴拉巴拉; ii. 从起始位置出…

使用Simcenter全面评估SiC 器件的特性

内容摘要 传统的硅金属-氧化物-半导体场效应晶体管 (MOSFET) 具有成熟的技术和低廉的成本,在中压和绝缘栅双极晶体管 (IGBT) 高压功率电子器件中占主导地位。使用碳化硅等具有高电离能的新型宽带隙材料,可以制造出具有快速开关时间和超过1,000伏击穿电压…

博客网站SpringBoot+Vue项目练习

博客网站SpringBootVue简单案例 前言 学了vue后一直没用找到应用的机会,在Github上找到了一个看起来比较友好的项目(其实具体代码我还没看过)。而且这个项目作者的readme文档写的也算是比较好的了。 项目链接:https://github.c…

【LeetCode刷题】739. 每日温度(单调栈)

1. 题目链接2. 题目描述3. 解题方法4. 代码 1. 题目链接 739. 每日温度 2. 题目描述 3. 解题方法 用一个栈st保存每个数的下标,同时创建一个数组res保存结果,初始值都为0。循环遍历题目中的数组temperature。如果temperature[i] > st.top()&#x…

Linux--IIC驱动编程实验

对于 I2C 主机驱动,一旦编写完成就不需要再做修改,其他的 I2C 设备直接调用主机驱动提供的 API 函数完成读写操作即可。这个正好符合 Linux 的驱动分离与分层的思想,因此 Linux内核也将 I2C 驱动分为两部分: ①、 I2C 总…

虚拟化之---virtio通信

一、理解virtio的背景 我们知道虚拟化hypervisor大的类型分为两种,全虚拟化和半虚拟化。 在全虚拟化的解决方案中,guest VM 要使用底层 host 资源,需要 Hypervisor 来截获所有的请求指令,然后模拟出这些指令的行为,这样…

Java毕设之学院党员管理系统的设计与实现

运行环境 环境说明: 开发语言:java 框架:springboot,vue JDK版本:JDK1.8 数据库:mysql5.7(推荐5.7,8.0也可以) 数据库工具:Navicat11 开发软件:idea/eclipse(推荐idea) Maven包:Maven3.3.9 系统实现 管理员功能实现 党员管理 管理员进入指定功能操作…

算法学习:二分查找

🔥 引言 在现代计算机科学与软件工程的实践中,高效数据检索是众多应用程序的核心需求之一。二分查找算法,作为解决有序序列查询问题的高效策略,凭借其对数时间复杂度的优越性能,占据着算法领域里举足轻重的地位。本篇内…

如何使用resource-counter统计跨Amazon区域的不同类型资源数量

关于resource-counter resource-counter是一款功能强大的命令行工具,该工具基于纯Python 3开发,可以帮助广大研究人员跨Amazon区域统计不同类型资源的数量。 该工具在统计完不同区域的各类资源数量后,可以在命令行中输出并显示统计结果。res…

【driver5】调用堆栈函数,printk,动态打印,ftrace,proc,sysfs

文章目录 1.内核函数调用堆栈:4个函数2.printk:cat /proc/cmdline查看consolettyS03.动态打印:printk是全局的且只能设打印等级,动态打印可控制选择模块的打印,在内核配置打开CONFIG_DYNAMIC_DEBUG4.ftrace&#xff1a…