说到现代大型软件架构,很容易想到的就是分布式、缓存数据库、负载均衡、资源虚拟化、微服务、组件等等。然而,如果你总是和我夸夸其谈分布式、并行等各种花里胡哨的框架,却不告诉我代码怎么写,那么你一定在耍流氓。作为一个基层的软件开发人员,更关心的是 main 函数该怎么写、大量功能函数怎么分配到不同的线程上,而这才是最底层的软件架构,也是最重要的。今天,我给大家介绍一种灵活的可编程软件框架,可以说,这个框架能够满足绝大数场景下的软件功能、性能及灵活性需求。
1 一个基本的软件运行结构图
上图中,
main 函数在主线程中,子线程 1 和子线程 2 都用来处理任务,任务存放在任务队列中;
每个任务需要两个阶段才能完成,先经过阶段 1 处理,再经过阶段 2 处理;
阶段 1 需要两个函数处理,分别是函数 A 和函数 B;
阶段 2 需要一个函数处理,即函数 C.
2 函数和队列如何部署到不同的线程上?
说到底,每个线程上运行的都是一些基本的功能函数,我们可以把实现某个功能的函数划分到一个函数集合里。这个例子中,子线程 1 上运行的是函数集合 1,子线程 2 上运行的是函数集合 3.
线程、函数集合、任务队列的绑定关系图
当线程上的函数从任务队列取任务进行处理的时候,我们要明确以下几点:
同一个任务队列可以被多个线程调度
多个线程可以调度同一个任务队列
不同的函数集合可以部署在同一个线程上
同一个函数集合也可以部署在不同线程上
线程、函数集合、任务队列的具体绑定关系,我们可以灵活地写在配置文件中,比如 json、yaml 等。在进程起来之后,通过加载配置文件的方式实现资源的部署。为什么一个线程上可以挂多个任务队列呢?因为任务队列可以有不同的类型呀,比如说系统任务,用户业务等。
3 线程上的函数如何调度?
在业务线程实际运行的过程中,我们只会看到一个个函数,那如何控制函数的执行顺序呢?最简单的一种方案就是状态机。线程每执行一个循环,从初始状态开始,经过中间状态,到最终状态结束。任务到达每一种状态时,就会进行相应的动作处理(即对应了一个有序的函数集合),根据任务处理的结果,选择需要跳转的下一个状态,直到遇到最终状态,当前任务处理结束。接着,从任务队列上取下一个任务,循环调度。
状态机循环调度任务
4 线程起来之后,哪些函数集合会真正运行起来?
前文讲到,在部署框架中指定了每个线程上需要运行哪些函数集合。但是,当线程实际起来之后,我们却是根据状态机进行调度,状态机也指定了每个状态需要执行哪些动作(也就是函数集合),那我们到底是执行部署框架中定义的函数集合还是执行状态机中对应的函数集合呢?答案当然是状态机中对应的函数集合呀。
总结
这篇文章中,我尝试总结了一种基于多线程并行技术下的可灵活编排的软件架构。这个架构核心的地方有两点:一是资源部署(即队列、函数、线程的绑定关系);二是基于状态机原理进行调度,每个状态处理之后如何选择下个状态,直接关系到软件性能。朋友们,在摩尔定律失效、软件性能要求越来越高的需求下,你们有更好的软件架构,能实现 CPU 多核、多线程资源的最大化利用及高效的调度框架吗?
关键词: 可编程软件