`
izuoyan
  • 浏览: 9221036 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

一个资源管理系统的设计--基于cgroup机制

阅读更多

设计一个资源管理系统对于一个综合性的资源访问系统来说是十分必要的,而好的设计一定是不复杂的,甚至说是十分简单的,原因就是精简机构,消除冗余,或者说精兵简政在任何时候任何方面总是必要的,我们不希望管理机制本身消耗大量的资源(时间,空间,或者其它),因此在设计之前一定要有好的实体抽象,这些实体抽象不一定要多但一定要完整。我自认为自己的一个设计是比较不错的,实话说,它真的不错,如果你否认这一点的话,请看完本文,最终你会明白我为何如此自恋。首先抽象出受控进程,控制元素以及管理组的概念,在详细分析设计步骤之前,先把这些抽象的概念形象化一下:
受控进程:ssh,sshd,httpd...
控制元素:cpu占用率,内存总量,磁盘使用...
管理组:组1,组2,组3
控制粒度:基于进程和控制元素,也就是说管理组(组x)不必控制控制元素中的所有元素,只需要控制其中一个或者几个即可,当然也可以是全部。
有了以上假设,那么几种对应关系就很显然了,指出这些对应关系之前首先定义几种角色:
主体:受控进程
客体:控制元素
管理者:管理组
总体描述:主体在管理者的管理下对客体产生动作。
以上这些都是最最基本的元素了,我认为不能比这更简单了,因此我认为它是完美的,理解了角色和总的描述,它们的关系如下:
受控进程->控制元素:这是个一对多的关系,一个进程可以接受多种元素的控制
控制元素->受控进程:这是个一对多的关系,一个控制元素可以控制多个进程
受控进程<=>控制元素:因此这是个多对多的关系
控制元素->管理组:这是个一对一的关系,即某个进程的一个受控元素只能由一个管理组控制
管理组->控制元素:这是个一对多的关系,即一个管理组可以管理一组进程的多个控制元素
管理组<=>受控进程:这是个多对多的关系,即一个管理组可以可以控制多个进程,反过来一个进程的不同控制元素也能被多个管理组控制。
有了以上的关系,我想任何关系数据库的高手都能设计出表结构来的,甚至都不需要是高手,只要会一些数据库的知识应该就不成问题,这个关系结构很显然,表结构也很简单可是在不允许查询数据库或者没有数据库环境的情况下,如何实现这个方案呢?比如在一个嵌入式的小内存的设备上,如何仅仅通过c语言或者别的轻量级语言编程实现它呢?要知道数据库的查询操作实际上仅仅给外部提供一个接口,而其实现是由查询引擎完成的,在这个意义上,我们要实现的就是一个小型的查询引擎了,因此首先我们需要先设计一下数据结构,最基本的就是主体,客体,管理者的设计了:
主体:
struct task {
void *other;
List *targets;
}Task;
客体:
struct target {
void *other;
List *tasks;
Manager *man;
}Target;
管理者
struct manager {
void *other;
List *targets;
}Manager;
以上是最初步的设计,已经展现了对应关系,但是无法索引当前的客体,因此有必要将所有的客体组织成数组的形式:
Target ts[] = {cpu,memory,file,...};
主体重新设计为:
struct task {
void *other;
Target targets[N];
}Task;
但是这样的话,每一个Target的结构体中除了tasks字段之外的数据将会重复,这就浪费了内存,因此有必要将task和target进行解除耦合,于是设计一个中间结构,用于拼接这两个结构:
struct middle {
List *tasks; //所有的使用这个middle的task链表
Target targets[N]; //以上tasks这些进程的N控制元素
}Mid;
struct task {
void *other;
Mid *mid;
}Task;
struct target {
void *other;
Manager *man;
}Target;
这样,所有的被同一些控制元素控制的task就可以共享一个target了,从而节省了内存。由于task和target是多对多的关系,因此使用了一个middle来解除其耦合,达到了共享一方的效果,同样的道理,task和manager的关系也是多对多的关系,于是同样的措施必然带来同样的效果。于是重新设计:
struct manager {
void *other;
List *targets;
}Manager;
struct middle2 {
List *tasks; //所有的被这个管理者管理的task链表
List *managers; //一个task属于的所有的管理者
}Mid2;
struct task {
void *other;
Mid *mid;
Mid2 *mid2;
}Task;
仔细一想,这样不妥,原因有二,第一个原因是一个task虽然属于很多manager,但是它是基于target的,这个信息没有体现出来,第二,信息冗余,这样在修改或者同步起来非常不便,于是必然要重新设计,由于manager和target的联系已经建立了,然而这个关系是单向的,数据查询因此也只能是单向的,我们能通过一个task得到它归于哪些manager,却无法反过来从一个manager得到它都控制了哪些task,由于管理者基于一组target来分组,因此所有这些task拥有共同的有效target[N],因此必然需要建立一个反向的关系,首先在Manager中建立一个新的List字段:
struct manager {
void *other;
List *targets;
List *tasks;
}Manager;
从基于target组进行管理的前提并且task和target已经通过middle联系得知,这个manager需要和middle用类似middile的结构体进行联系,姑且将该结构体设为middle2,这个middle2对于manager来说,它代表一个middle,也就是一组task以及对应的一组target,这个middle2对于一个middle来说,它代表一个manager,为了表现manager和middle是对对多的关系,middle2的设计和middle的设计几乎一样:
struct middle2 {
List *manager; //对于一个middle来说,该链表包含所有的targets数组的manger字段的并集,当然由于一个middle对应N个target,具体哪个target对应哪个manager,需要查阅middle的targets数组来一一确定。
List *mids; //对于一个manager来说,该链表包含它所参与管理的所有的middle
Mid *mid; //一个mid2唯一对应一个mid。这是基于targets集合意义的,而不是基于单独的target的
}Mid2;
最终的设计如下:
struct middle {
List *tasks; //所有的使用这个middle的task链表
Target targets[N]; //这里使用数组而没有使用List完全是为了代码的简洁,可以直接通过enum枚举名来直接访问
}Mid;
struct middle {
List *tasks;
List *mid2; //由于下面的N个target并不一定属于一个manager,因此一个middle可能也属于多个manager,这个关系通过mid2来耦合。
Target targets[N];
}Mid;
struct middle2 {
List *manager;
List *mids;
Mid *mid;
}Mid2;
struct task {
void *other;
Mid *mid;
}Task;
struct target {
void *other;
Manager *man;
}Target;
struct manager {
void *other;
List *targets;
List *mid2;
}Manager;
这么一个设计基本就完美了,我们试一下几个查询。首先,从一个task查询一下它的各个控制元素都受哪个管理者的控制,这个很简单,从task取出mid字段,然后遍历整个targets数组,从每一个元素中取出manager字段即可;接下来根据一个manager查询一下它都控制了哪些进程,取出manager的mid2字段,遍历其中的每一个middle2元素,对于每一个middle2,取出其mid字段,然后遍历其task字段,取出所有的task即可。着重需要说明的是middle2结构,它具有两重身份,mids是作为单独的target起作用的,毕竟一个middle结构体拥有不同的target,这些target不一定有相同的manager的,而mid字段是作为一组targets起作用的,换句话说,它针对的是一个middle而不是middle中单独的target。
本设计可以使用数据库,但是却没有使用数据库,因为本设计的精髓在于设计的实现而不是关系模型,可以看出,linux内核在设计数据结构的时候和本文的方式有些类似,实际情况是:本文就是参考linux内核的cgroups做出来的,因此我才敢说它很完美(尽管linux内核并不总是很完美)!看完了本文,再去理解linux内核代码中关于cgroups的复杂代码,我相信就清晰多了。在此给出一些对应:
task--task_struct
target--cgroup_subsys_state
manager--cgroup
middle--css_set
middle2--cg_cgroup_link
其中在find_existing_css_set函数中有下面的判断:
if (root->subsys_bits & (1UL << i))
这说明,虽然你建立了一个新的cgroup,然后这个cgroup中具体哪些subsys起作用,所依据的是你mount cgroup时的-o参数,因此虽然将一个进程放入了一个cgroup,如果这个cgroup在mount的时候没有memory参数而只有cpu参数的话,该进程的内存使用情况还将受原先cgroup的限制而不受这个新的cgroup的限制。另外需要注意的是,linux内核的cgroup使用了OO的思想,cgroup_subsys_state并不提供任何信息,如果你想提供一些信息,比如想提供内存使用方面的限制,那么建立一个结构体,让cgroup_subsys_state作为第一个元素(或者第n个元素),这样cgroup_subsys_state就是一个根类对象,让所有其它的具体类继承它即可:
struct memctrl {
cgroup_subsys_state cst;
...//其它的具体字段
};
然后用container_of取出具体的结构即可!

分享到:
评论

相关推荐

    Linux下cgroup

    LXC(Linux Containers)是基于cgroups和namespaces的一个早期容器技术实现。LXC允许在单个主机上运行多个相互隔离的容器,每个容器都有自己的文件系统、网络配置和资源限制,但共享同一内核。这极大地提高了资源...

    Docker-LXC_原理与绕过1

    新的进程是父进程的一个副本,具有相同的内存空间和系统资源。 在 fork() 函数中,有一个重要的参数叫做 clone_flags。Clone_flags 是一个标志位,它可以控制新的进程如何被创建。例如,Clone_flags 可以指定新的...

    GBase-Up统一数据平台管理员手册-D.docx

    此外,C3辅助工具的介绍,为管理员提供了便捷的集群管理和监控手段,如C3简介和常用命令,以及cgroup控制组的应用,用以实现对系统资源的精细化管理。 GBase UP集群管理章节深入讲解了日常运维操作,包括系统的安装...

    cgroupfs-mount:简单(陈旧)的脚本来装入cgroupfs(v1)层次结构,尤其是针对Debian打包的结构

    控制组是一种内核机制,用于跟踪任务组上的资源使用并对其施加限制。 这些脚本在引导时设置cgroup,而无需执行任何cgroup管理或将任务分类为cgroup。 我需要这个吗? 如果您使用systemd作为初始化系统,则不需要它...

    容器技术之Docker介绍.pptx

    Docker是一个基于容器技术的应用程序部署平台,它可以提供轻量级的虚拟化解决方案。Docker可以提供以下几个方面的功能: * 应用程序部署:Docker可以快速部署应用程序,提高应用程序的部署效率。 * 容器管理:...

    基于容器的弹性云技术剖析.pptx

    总之,基于容器的弹性云技术提供了一种高效、灵活的资源管理方式,通过CPU、内存、磁盘IO和网络层面的精细控制,实现了数据中心业务的快速部署和扩展。此外,自研工具和优化策略的引入,如JD的yaRPC和brooder,...

    3 openEuler系统服务的配置和管理.pdf

    - **cgroup(Control Group)**:systemd利用cgroup来实现对服务进程及其子进程的资源管理和控制。cgroup提供了一种机制来限制、记录和隔离进程组所使用的系统资源(如CPU、内存等)。 #### 三、任务管理 除了...

    warden设计pdf

    Warden架构包括一个Ruby编写的守护进程,用于管理系统状态,以及每个容器一个C语言编写的守护进程,用于处理容器的引导、进程分发等具体操作。这样的设计保证了Warden能够在不同的容器之间进行有效隔离和资源控制。 ...

    混搭型大数据平台的统一资源管控.pdf

    3. 技术实现部分则具体阐述了如何利用Linux内核的CGroup机制来达到资源隔离管控的目的,以及如何通过Yarn框架进行资源调度和管理。Hadoop平台的资源调度管理职责由Yarn承担,而ShareNothing MPP数据库则主要基于...

    Linux Cgroups技术概述.docx

    Cgroups,全称为 Control Groups(控制组),是 Linux 内核提供的一种机制,可以根据需求把一个系列的任务以及其子任务整合或者分割到按资源分等级的不同组内,从而给系统资源管理器提供一个统一的框架。简单来说,...

    1-7.2 基于工作集冷内存回收方案1

    工作集(Working Set)基于的内存回收方案是操作系统管理内存的一种策略,特别是在Linux内核中,它被用来优化内存的使用效率,确保系统的稳定性和响应性。工作集主要关注的是在一段时间内被频繁访问的数据页集合,...

    容器安全与隔离机制.pptx

    - **SELinux**:多级安全机制,通过标签强制访问控制来限制容器对系统资源的访问。 5. **容器编排安全**: - **认证和授权**:使用RBAC(Role-Based Access Control)、TLS证书等机制控制对容器编排平台的访问。 ...

    金融行业基于容器架构的OLTP数据库技术.pdf

    自2013年起,上海富麦信息科技有限公司就开始为大型金融支付企业提供基于cgroup的DBaaS(Database as a Service)原型系统,并逐步将其迁移至Docker环境下,完善了产品的配套系统设计与实现。通过不断的微服务化改造...

    2012年中国系统架构师大会PPT-_1 低成本和高性能MySQL云架构探索.pdf

    该报告主要探讨了如何在云计算环境下构建一个既能够降低成本又能提升性能的MySQL云架构方案。 #### 二、面临的挑战 报告中提到,在传统的MySQL运维过程中存在着多个挑战: - **易用性偏差**:传统MySQL部署和维护...

    全志A13移植Linux所用的配置文件.config

    - **CONFIG_HAVE_LATENCYTOP_SUPPORT=y**:提供了对LatencyTop工具的支持,这是一个用于分析系统延迟的工具,对性能调优很有帮助。 - **CONFIG_LOCKDEP_SUPPORT=y**:启用锁依赖检查,这可以防止死锁和提高多线程...

    控制组实现初步分析

    控制组是Linux内核的一个特性,它为分配和管理系统的各种资源如CPU时间、内存使用、磁盘I/O等提供了细粒度的控制。在本文中,我们将深入探讨控制组的概念、工作原理以及如何在实际应用中使用它。 首先,控制组的...

Global site tag (gtag.js) - Google Analytics