【博文目录>>>】
计算资源整合模式
将多个任务或操作整合到一个计算单元中。这种模式可以提高计算资源利用率,并减少与在云托管应用程序中执行计算处理相关的成本和管理开销。
背景与问题
云应用程序经常实现各种操作。在某些解决方案中,最初可能会遵循关注点分离的设计原则,并将这些操作划分为单独托管和部署的离散计算单元(例如,作为Microsoft Azure Cloud Service中的单独角色,单独的Azure网站,或单独的虚拟机)。但是,尽管此策略可以帮助简化解决方案的逻辑设计,但是将大量计算单元部署为同一应用程序的一部分可能会增加运行时托管成本,并使系统的管理更加复杂
作为示例,图1显示了使用多个计算单元实现的云托管解决方案的简化结构。每个计算单元都在其自己的虚拟环境中运行。每个功能已实现为在其自己的计算单元中运行的单独任务(标记为任务A至任务E)
图1-使用一组专用计算单元在云环境中运行任务
每个计算单元即使在空闲或轻度使用时也会消耗可计费的资源。因此,这种方法可能并不总是最经济高效的解决方案。
在Azure中,此问题适用于云服务、网站和虚拟机中的角色。这些东西在它们自己的虚拟环境中执行。运行一组单独的角色、网站或虚拟机,这些操作旨在执行一组定义良好的操作,但这些操作需要作为单个解决方案的一部分进行通信和协作,这可能会导致资源利用效率低下。
解决方案
为了帮助降低成本、提高利用率、提高通信速度和简化管理工作,可以将多个任务或操作合并到一个计算单元中。
任务可以根据各种标准进行分组,分组标准是基于环境提供的功能以及与这些功能相关的成本。一种常见的方法是查找在可伸缩性、生存期和处理需求方面具有类似配置文件的任务。将这些项目组合在一起可以使它们作为一个单位进行扩展。许多云环境提供的弹性使计算单元的其他实例能够根据工作负载启动和停止。例如Azure提供了自动缩放功能,可以应用于云服务、网站和虚拟机中的角色。有关更多信息,请参见自动缩放指导.
作为说明如何使用可伸缩性来确定哪些操作不应该组合在一起的反例,请考虑以下两个任务:
- 任务1轮询发送到队列的不频繁、时间不敏感的消息.
- 任务2处理大量的网络通信.
第二个任务需要弹性,这可能涉及启动和停止大量的计算单元实例。将相同的缩放比例应用于第一个任务只会导致更多任务监听同一队列上的不频繁消息,并且浪费资源。
在许多云环境中,可以根据CPU核的数量、内存、磁盘空间等来指定计算单元可用的资源。一般来说,指定的资源越多,成本就越高。为了提高财务效率,重要的是最大限度地提高昂贵的计算单元执行的工作量,并且不要让其长时间处于闲置状态。
如果有任务在短时间内需要大量CPU能力,请考虑将这些任务合并到一个提供必要能力的单个计算单元中。但是,重要的是要平衡这种需求,以使昂贵的资源繁忙,避免因压力过大而发生争用。例如,长时间运行的计算密集型任务可能不应共享相同的计算单元。
问题和思考
在实现此模式时,请考虑以下几点:
- 可扩展性和弹性。许多云解决方案通过启动和停止单元实例在计算单元级别实现可伸缩性和弹性。避免在同一计算单元中对具有可伸缩性要求冲突的任务进行分组。
- 生命周期。云基础设施可以定期回收承载计算单元的虚拟环境。在计算单元内执行许多长期运行的任务时,可能需要配置该单元,以防止其在这些任务完成之前被回收。或者,使用检查点方法设计任务,使它们能够干净地停止,并在计算单元重新启动时被中断时继续执行。
- 释放节奏。如果任务的实现或配置经常更改,则可能需要停止托管更新代码的计算单元,重新配置和重新部署该单元,然后重新启动它。此过程还需要停止、重新部署和重新启动同一计算单元中的所有其他任务。
- 安全。同一计算单元中的任务可以共享相同的安全上下文,并且能够访问相同的资源。任务之间必须高度信任,并确信一个任务不会损坏或对另一个任务产生不利影响。此外,增加在计算单元中运行的任务数量可能会增加计算单元的攻击面;每个任务仅与漏洞最多的任务一样安全。
- 容错能力。如果计算单元中的一项任务失败或行为异常,则可能会影响同一单元中运行的其他任务。例如,如果一项任务无法正确启动,则可能导致计算单元的整个启动逻辑失败,并阻止同一单元中的其他任务运行。
- 争用。避免在争用同一计算单元中的资源的任务之间引入竞争。理想情况下,共享相同计算单元的任务应表现出不同的资源利用特征。例如,两个计算密集型任务可能不应该驻留在同一计算单元中,并且两个消耗大量内存的任务也不应驻留在同一计算单元中。但是,将计算密集型任务与需要大量内存的任务混合在一起可能是可行的组合。
注
您应该考虑仅为已投入生产一段时间的系统整合计算资源,以便操作员和开发人员可以监视系统并创建热图,该热图可以标识每个任务如何利用不同的资源。该映射可用于确定哪些任务是共享计算资源的理想选择。
- 复杂性。将多个任务组合到一个计算单元中会增加该单元中代码的复杂性,可能使测试,调试和维护更加困难。
- 稳定的逻辑体系结构。设计并实现每个任务中的代码,以便即使运行任务的物理环境发生了变化,也无需更改代码。
- 其他策略。整合计算资源只是帮助减少与同时运行多个任务相关的成本的一种方法。它需要仔细的计划和监视,以确保它仍然是一种有效的方法。其他策略可能更合适,具体取决于正在执行的工作的性质以及代表这些任务运行的用户的位置。例如,工作负载的功能分解(如计算分区指南)也许是一个更好的选择。
何时使用此模式
如果任务以自己的计算单位运行,则对成本不高的任务使用此模式。如果任务花费大量时间空闲,则在专用单元中运行此任务可能会很昂贵。
这种模式可能不适合执行关键容错操作的任务,也不适合处理高度敏感或私有数据并需要自己的安全上下文的任务。这些任务应该在自己独立的环境中运行,在一个单独的计算单元中运行。
示例
在Azure上构建云服务时,可以将多个任务执行的处理整合到一个角色中。通常,这是一个执行后台或异步处理任务的工作人员角色。
注
在某些情况下,可以在web角色中包括后台或异步处理任务。这种技术可以帮助降低成本和简化部署,尽管它会影响Web角色提供的面向公共接口的可伸缩性和响应性。将多个Azure工作者角色组合为Azure Web角色的文章包含有关在Web角色中实现后台或异步处理任务的详细说明。
该角色负责启动和停止任务。当Azure构造控制器加载角色时,它将引发该角色的Start事件。您可以重写WebRole或WorkerRole类的OnStart方法来处理此事件,也许可以初始化此方法中的任务所依赖的数据和其他资源。
当OnStart方法完成时,角色可以开始响应请求。您可以在模式和实践指南将应用程序迁移到云端的应用程序启动过程部分中找到有关角色使用OnStart和Run方法的更多信息和指南。
注
保持OnStart方法中的代码尽可能简洁。Azure对该方法完成所花费的时间没有施加任何限制,但是在此方法完成之前,该角色将无法开始响应发送给它的网络请求。
OnStart方法完成后,角色将执行Run方法。此时,结构控制器可以开始向角色发送请求。
将实际创建任务的代码放在Run方法中。请注意,Run方法有效地定义了角色实例的生存期。此方法完成后,结构控制器将安排角色关闭。
当角色关闭或被回收时,结构控制器将阻止从负载均衡器接收到更多传入请求,并引发Stop事件。您可以通过重写角色的OnStop方法来捕获此事件,并在角色终止之前执行所有必要的整理工作。
注
必须在五分钟内(如果您在本地计算机上使用Azure模拟器,则必须在30秒内)完成在OnStop方法中执行的所有操作;否则,Azure结构控制器将假定角色已停止并强制其停止。
图2说明了角色的生命周期以及它所承载的任务和资源。任务由Run方法启动,然后等待任务完成。任务本身实现了云服务的业务逻辑,可以响应通过Azure负载均衡器发布到角色的消息。
图2-Azure云服务中角色中的任务和资源的生命周期
ComputeResourceConsolidation.Worker项目中的WorkerRole.cs文件显示了如何在Azure云服务中实现此模式的示例。
注
Worker项目是ComputeResourceCombination解决方案的一部分,该解决方案可与本指南一起下载。
在工作角色中,初始化角色时运行的代码将创建所需的取消令牌和要运行的任务列表。
public class WorkerRole: RoleEntryPoint{
// The cancellation token source used to cooperatively cancel running tasks.
private readonly CancellationTokenSource cts = new CancellationTokenSource ();
// List of tasks running on the role instance.
private readonly List<Task> tasks = new List<Task>();
// List of worker tasks to run on this role.
private readonly List<Func<CancellationToken, Task>> workerTasks
= new List<Func<CancellationToken, Task>>{ MyWorkerTask1, MyWorkerTask2};
...
}
提供MyWorkerTask1和MyWorkerTask2方法是为了说明如何在同一辅助角色中执行不同的任务。以下代码显示MyWorkerTask1。这是一个简单的任务,它休眠30秒钟,然后输出跟踪消息。它无限期地重复此过程,直到任务被取消。 MyWorkerTask2中的代码非常相似。
// A sample worker role task.private static async Task
MyWorkerTask1(CancellationToken ct){
// Fixed interval to wake up and check for work and/or do work.
var interval = TimeSpan.FromSeconds(30);
try {
while (!ct.IsCancellationRequested) {
// Wake up and do some background processing if not canceled.
// TASK PROCESSING CODE HERE
Trace.TraceInformation("Doing Worker Task 1 Work");
// Go back to sleep for a period of time unless asked to cancel.
// Task.Delay will throw an OperationCanceledException when canceled. await Task.Delay(interval, ct);
}
} catch (OperationCanceledException) {
// Expect this exception to be thrown in normal circumstances or check
// the cancellation token. If the role instances are shutting down, a
// cancellation request will be signaled.
Trace.TraceInformation("Stopping service, cancellation requested");
// Re-throw the exception.
throw;
}
}
注
示例代码显示的方法是后台进程的常见实现。在现实世界中的应用程序中,您可以遵循相同的结构,只是您应将自己的处理逻辑放在等待取消请求的循环主体中。
在工作角色初始化其使用的资源后,Run方法将同时启动两个任务,如下所示。。
// RoleEntry Run() is called after OnStart().
// Returning from Run() will cause a role instance to recycle.
public override void Run(){
// Start worker tasks and add them to the task list.
foreach (var worker in workerTasks)
tasks.Add(worker(cts.Token));
Trace.TraceInformation("Worker host tasks started");
// The assumption is that all tasks should remain running and not return,
// similar to role entry Run() behavior.
try {
Task.WaitAny(tasks.ToArray());
} catch (AggregateException ex) {
Trace.TraceError(ex.Message);
// If any of the inner exceptions in the aggregate exception
// are not cancellation exceptions then re-throw the exception. ex.Handle(innerEx => (innerEx is OperationCanceledException));
}
// If there was not a cancellation request, stop all tasks and return from Run()
// An alternative to cancelling and returning when a task exits would be to
// restart the task.
if (!cts.IsCancellationRequested) {
Trace.TraceInformation("Task returned without cancellation request"); Stop(TimeSpan.FromMinutes(5));
}
}
...
在此示例中,Run方法等待任务完成。如果取消了任务,则Run方法将假定该角色已关闭,并等待剩余的任务在完成之前被取消(它最多等待五分钟才能终止)。 如果任务由于预期的异常而失败,则Run方法将取消该任务。
注
请注意,您可以在Run方法中实施更全面的监视和异常处理策略,例如重新启动失败的任务,或包括使角色停止和启动单个任务的代码。
当结构控制器关闭角色实例时,将调用以下代码中所示的Stop方法(从OnStop方法调用)。该代码通过取消它来优雅地停止每个任务。如果完成任何任务需要五分钟以上的时间,则Stop方法中的取消处理将停止等待并终止该角色。
// Stop running tasks and wait for tasks to complete before returning
// unless the timeout expires.
private void Stop(TimeSpan timeout){
Trace.TraceInformation("Stop called. Canceling tasks.");
// Cancel running tasks.
cts.Cancel();
Trace.TraceInformation("Waiting for canceled tasks to finish and return");
// Wait for all the tasks to complete before returning. Note that the
// emulator currently allows 30 seconds and Azure allows five
// minutes for processing to complete.
try {
Task.WaitAll(tasks.ToArray(), timeout);
} catch (AggregateException ex) {
Trace.TraceError(ex.Message);
// If any of the inner exceptions in the aggregate exception
// are not cancellation exceptions then re-throw the exception. ex.Handle(innerEx => (innerEx is OperationCanceledException));
}
}
相关模式和指导
在实施这一模式时,下列模式和指导也可能相关:
- 自动缩放指导。根据预期的处理需求,可以使用自动缩放来启动和停止托管计算资源的服务实例。
- 计算分区指南。本指南介绍了如何在保持服务的可伸缩性,性能,可用性和安全性的同时,帮助您将云服务中的服务和组件分配到最小的方式,以最大程度地降低运行成本。
更多信息
- 博客文章将多个Azure工作者角色组合为Azure Web角色.
- 在MSDN上,模式和实践指南中章节的应用程序启动过程部分介绍了将应用程序迁移到云中。
该模式具有与之关联的示例应用程序。您可以从Microsoft下载中心下载:http://aka.ms/cloud-design-patterns-sample
原文链接
https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589778%28v%3dpandp.10%29
来源:CSDN
作者:DERRANTCM
链接:https://blog.csdn.net/DERRANTCM/article/details/104727269