第十八章 使用工作队列管理器(一)
第十八章 使用工作队列管理器(一)
工作队列管理器是的一项功能,使能够通过以编程方式将工作分配给多个并发进程来提高性能。在引入工作队列管理器之前,可能已经使用 JOB
命令在应用程序中启动多个进程并使用自定义代码管理这些进程(以及任何导致的故障)。工作队列管理器提供了一个高效且直接的 API,使能够卸载流程管理。
代码在多个地方内部使用工作队列管理器。可以将它用于自己的需求,如以下部分中的高级描述。
背景
计算机硬件开发的最新创新趋向于高性能、多处理器或多核架构。与此同时,内存和网络设备的速度也只是慢慢地提高了。 开发了工作队列管理器以响应这些趋势并根据以下原则:
- 硬件资源,包括 CPU 和 I/O、内存和网络设备,都是固定的。
- 必须尽可能高效地使用硬件资源,以最大限度地提高其执行业务任务的速度。
- 为了实现最大效率,工作队列管理器必须改善在执行ObjectScript 代码时可能出现的 CPU 利用率不足的问题。
- 解决 CPU 利用率不足的方法包括排队和优先级划分。
尽管整个数据平台旨在尽可能高效地利用系统中的硬件资源,但该平台的工作队列管理器功能专门设计用于利用现代硬件配置中可用的额外 CPU 资源。工作队列管理器有两个关键用途:
- 提供一个框架,使能够将大型编程任务分解成更小的块,以便在多个并发进程中执行。通过一次使用多个 CPU,工作队列管理器显着减少了处理大型工作负载所需的时间。
- 通过管理系统任务一次处于活动状态的JOB的数量来控制系统上的总 CPU 负载。
ObjectScript CPU 利用率
通常,ObjectScript 代码在单个进程中运行并且仅使用一个处理器内核。对于处理相对较少的指令和事务之间的全局引用的事务数据库应用程序,这种方法效果很好。事实上,数据平台的一个关键特性是事务工作负载的大规模可扩展性。该平台优化处理大量用户一次请求的大量相对较小的工作单元。
一些较新类型的工作负载(例如,分析工作负载)与 最初为优化而构建的工作负载不同。例如,较新的工作负载可能涉及处理一个需要对数百万行执行各种操作的 SQL 查询。为了加快此类工作负载的处理速度,开发了工作队列管理器,它将整体工作负载分解为更小的块,并行处理这些块,并将每个块的结果中继回父进程,然后父进程可以中继结果还给你。换句话说,工作队列管理器是一种类似于Queues
的机制,它使在中构建其应用程序的开发人员能够将大型任务分解为并行处理的较小任务。
工作队列管理器的功能
工作队列管理器包括几个关键特性:
- 低延迟和开销
- 可扩展性
- 与操作系统的合作
- 灵活性
- 高水平的控制和报告
低延迟和开销
工作队列管理器专为低延迟和低开销而设计。例如,考虑一个程序化任务,系统需要 10
分钟才能按顺序处理。如果系统有 10
个内核,那么将任务拆分并在每个内核上并行处理十分之一的工作会更有效率。实际上,如果拆分任务、排队每个任务、启动工作作业和收集每个任务完成的通知所涉及的开销不需要任何额外的时间,那么可以得到结果 10快几倍。工作队列管理器被设计成开销任务导致低延迟。
可扩展性
为了最大限度地提高性能,工作队列管理器能够使用系统上的所有 CPU 资源来处理单个任务。实际上,工作队列管理器会限制给定类型的任务可以使用的核心数量,以确保系统上的所有工作负载都可以得到有效处理。
与操作系统的合作
使用用于大型事务性数据库应用程序的传统 ObjectScript 代码,操作系统可能会花费大量资源在编程任务之间切换,这有时称为上下文切换。由于工作队列管理器在每个内核上都采用了排队机制,因此对上下文切换的需求大大减少。只有当工作队列管理器管理的活动作业的数量超过可用内核的数量时,操作系统才需要进行上下文切换。这样,排队工作通常会提高性能。
灵活性
工作单元是采用一组参数并满足关于工作单元中描述的要求的类方法或子例程。可以在这些约束中表示的任何逻辑都可以由工作队列管理器处理,从而为提供极大的灵活性。
高水平的控制和报告
工作队列管理器为提供对系统上 CPU
资源使用方式的高级控制。例如,可以创建job
类别并定义分配给这些类别的工作人员job
的数量。此外,工作队列管理器提供工作负载指标,以便可以实时监控系统上的负载。
关于工作单元
工作队列管理器通过处理工作单元(也称为工作项)来发挥作用,这些工作单元是满足以下要求的 ObjectScript 类方法或子例程:
- 类方法或子程序可以独立处理。例如,一个工作单元不能依赖于不同工作单元的输出。由于工作单元可以按任何顺序处理,因此需要独立性。但是,如果需要,可以使用回调按顺序执行工作。
- 类方法或子例程的大小约为数千行 ObjectScript 代码。此要求确保框架的开销不是一个重要因素。
此外,最好使用大量(例如,100
个)较小的工作单元,而不是使用少量非常大的工作单元(例如,4
个)。以这种方式分配工作允许系统在更多 CPU
内核可用时进行扩展。
- 该代码返回一个
%Status
值来指示成功或失败,以便WaitForComplete()
方法可以返回一个%Status
值来指示整体成功或失败。或者,工作单元可以抛出异常,该异常被捕获、转换为%Status
值并在主进程中返回。 - 如果代码将相同的全局更改为不同的工作单元,则必须采用锁定策略来确保一个
work JOB
在另一个work正在读取它时不能更改全局。 - 该代码不包括
news
,kills
,unlocks
,因为这些会干扰框架。 - 如果代码包含用于存储数据的进程私有全局变量,则这些进程私有全局变量不会从主进程或任何其他块访问。这个要求是必要的,因为多个作业处理每个块。
- 作为类方法或子例程的一部分调用的任何逻辑都被正确清理,以便分区中没有变量、锁、进程专用全局变量或其他工件。此要求很重要,因为随后将使用相同的流程来处理完全独立的工作项。
要使用工作队列管理器,必须将一些程序化工作划分为工作单元。
关于 Worker Jobs
Worker jobs是为工作队列管理器完成工作单元的进程。通过使用 %SYSTEM.Process
类,可以像其他进程一样查看、管理和监视工作作业。如果需要知道给定进程是否是工作作业,可以在进程内调用 $system.WorkMgr.IsWorkerJob()
工作队列管理器使用控制器进程来指导工作job
,控制器进程是一个执行以下操作的专用进程:
- 启动worker jobs
- 管理worker jobs的数量
- 检测并报告暂停的worker jobs
- 记录工作负载指标
- 检测非活动工作队列
- 删除工作队列
worker jobs可以处于以下任何状态:
- 等待附加到工作队列
- 等待工作单位。在发布之前,worker jobs只能处于这种状态很短的时间。
- 激活。只有当它在执行一个工作单元时进行转发过程时,worker jobs才处于活动状态。
- 在处理工作单元时被锁或事件阻塞。被阻止的worker jobs未处于活动状态。如果worker jobs被阻塞并且工作队列中有额外的job,工作队列管理器可以激活不工作的woker或启动新woker。当worker jobs不再被阻塞时,活动worker jobs的数量可能会超过为工作队列指定的活动worker jobs的最大数量。如果发生这种情况,控制器进程将淘汰下一个完成工作单元的worker jobs。因此,当worker jobs的活动数量超过为给定工作队列指定的worker jobs的最大数量时,可能会有很短的时间段。
- 已停用并可快速激活
未使用的worker jobs 在短时间内仍可供其他工作队列管理器队列使用。超时期限可能会发生变化,并且故意未记录在案。超时期限到期后,worker 被移除。
如果worker jobs正在积极处理已删除或清除的队列的工作项,则系统会等待很短的时间,然后发出 EXTERNAL INTERRUPT
错误。如果worker jobs在错误后继续处理,系统会等待 DeleteTimeout
属性中指定的秒数,然后强制终止worker并启动新worker来处理工作单元。
超级服务器启动worker jobs,这意味着它们以超级服务器进程使用的操作系统用户的名称运行。此用户名可能与当前登录的操作系统用户不同。