当前位置: 首页 > 科技观察

看看ServerlessTask是如何解决任务调度&可观察性问题的

时间:2023-03-18 01:03:07 科技观察

1.任务调度任务调度主要是指系统根据当前的负载情况,将不同的任务放在合适的计算资源中执行的相关操作。一个完善的调度系统往往需要平衡不同特性任务之间的隔离和效率最优这两个需求。函数计算异步任务采用独立队列模型和自动负载均衡策略,具备在不影响处理性能的情况下进行多租户隔离的能力。ServerlessTask任务调度模型当用户提交任务时,系统将任务转化为消息异步发送到内部队列。一条消息的处理流程如下图所示:图1整个系统的多租户隔离在任务调度和消息积压控制上主要依赖于Scheduler对队列的消费和控制。我们会预先为每个用户分配一个账户级别的队列,所有用户函数的异步调用(包括任务调用)都会共享这个队列。这样的模型结构会保证每个用户的异步执行请求(包括任务调用)不会被其他用户的调用影响。但是在一些大规模的应用场景中,比如一个用户的功能比较多,每个功能的调用次数都比较多,所有的异步消息共享一个队列,必然会造成调用之间的相互影响。一些长尾调用可能会消耗过多的队列资源,导致其他函数执行时饿死。为了避免这种情况影响到重要函数的执行,函数计算提供了一个更细粒度的队列——函数级队列。您可以为每个不同的函数设置一个单独的队列,以保证高优先级函数的消费不会受到同一账户下其他函数执行的影响。队列之间的关系如下图所示:图2典型应用场景假设某用户A有两个不同的任务功能。其中一个任务A由于下游服务的限制,需要一次一条消息执行;而另一个任务B是一个大并发任务,希望尽快执行。默认模式下,任务A和B共享同一个用户队列;此时会出现以下场景:因为任务A有并发限制,函数计算端会控制整个任务队列的出队率。这导致任务B的任务长时间无法出队。任务A执行后,任务B有机会出队。此时并发度增加,任务B的消息抢占资源池执行。任务A变得难以出队,长时间无法启动一次。实施。结果是A和B都被对方的生意严重干扰了。队列调整后,任务A和B分别占用队列。在这种情况下,任务A和B的消费速度不受对方的影响,都可以满足自己的需求。目前,ServerlessTask提供了一个任务积压仪表板。可以在任务界面获取已积压的任务数,综合分析是否需要开启该功能的独占队列。上面的ServerlessTask任务队列负载均衡模型描述了如何通过函数级队列来避免“吵闹的邻居”问题。但是在某些场景下,如果任务的并发级别过大,即使为任务分配了单个队列,也会造成任务的积压。解决这个问题需要引入serverless任务负载均衡策略。函数计算的任务处理模块有Partition的概念。每个用户默认属于一个Partition,负责该Partition的Scheduler会监听用户对应的任务队列。当积压严重时,我们会根据负载情况给用户分配多个Partition,分配不同的Scheduler负责消费,从而提高任务的整体消费速度。如图3所示,阿里云函数计算在任务队列管理上默认实现了多租户和隔离能力,可以适用于大部分场景。针对负载大、执行时间长、并发量大的场景,函数计算还支持横向扩展,加速消费。在任务隔离方面,函数计算支持对不同优先级的函数进行单独隔离,避免NoisyNeighbor问题。2.可观测性任务的可观测性是任务系统必不可少的能力之一。强大的可观察性将帮助业务方减少任务运行每个阶段所需的额外工作量。开发阶段:任务的在线调试能力和运行结果的调试能力,将直接影响业务上线的进度;常规业务运营阶段:各种监控、流量统计和运行日志,帮助用户快速了解业务发展变化,快速定位和处理故障;阶段性审计:任务历史记录的存储和留存,为用户提供良好的可追溯性,可以根据历史信息进行后续业务规划。ServerlessTask可观测性支持-开发测试阶段业务开发阶段的主要需求是快速调试和定位问题。为了支持这个阶段,ServerlessTask提供了登录实例和实时登录的能力。代码开发上传后,测试-调试-修改代码-复测的过程都可以在控制台完成,大大提高了研发效率。如果需要进行性能调试,第三方Binary调试(如音视频处理领域的FFmpeg调试)等,可以使用登录实例功能来完成。操作流程如下图所示:选择您要登录实例的任务,点击实例链接。您将进入实例监控页面,点击右上角的登录实例功能,即可登录对应的实例。ServerlessTaskObservabilitySupport-业务上线后的运行阶段业务上线后,往往容易因为容量预估不足导致下游系统无法承受压力,导致故障。因此ServerlessTask提供了运行时指标,即一段时间内任务的提交次数、完成次数、执行状态。用户可以根据这个指标图快速了解当前的业务负载情况。当用户任务下游消费缓慢时,可能会造成任务积压。这种情况也很容易反映在指标图表上,然后可以快速做出相应的反应。目前ServerlessTask提供的相关指标如下:任务监控仪表盘提供如下任务监控数据:监控指标表示提交的任务数过去1分钟内提交的任务总数,包括运行数,已完成且未排队。TasksCompleted过去1分钟提交的任务完成的任务数,包括执行成功和失败的任务。Thenumberoftasksinthequeue在过去1分钟内提交并仍在队列中的任务数。如果数量不为0,则任务有积压。正在运行的任务过去1分钟内提交的正在运行的任务数。FailedTasks过去1分钟内提交但运行失败的任务数。RunningOccupiedInstances在过去1分钟内提交并成功运行的任务数。在快速定位问题方面,函数计算支持实时查看函数日志和实例指标。可以到任务列表页查找实际执行失败的任务,到日志页和实例页定位问题:ServerlessTaskObservabilitySupport-PeriodicAudit当一个在线任务运行一段时间后,它经常需要进行一系列的Periodic审计工作,比如前一周执行的任务总数,失败的任务数,失败执行的时间等。目前,除了控制台,函数计算还提供了丰富的API能力来审计任务。主要包括以下能力:根据状态过滤,只查询某个状态的执行情况;根据触发时间进行过滤,比如查询过去某个时间段内发起的任务;根据任务名称查询。如果您的任务有上下游业务的TraceID,您可以在触发任务时指定一个有意义的任务ID。可以根据ID前缀进行后续范围查询;以上过滤方式可以组合使用,以满足更方便的需求。控制台支持的过滤条件如下图所示:更多参数请参考:ListStatefulAsyncInvocation。ServerlessTask可观察性支持——死信队列与业务补偿在消息领域,有一个非常重要的概念——死信队列。当某些消息无法被消费时,往往需要将这些消息存储在一处,以供后续人为干预,避免未处理造成业务损失。ServerlessTask也支持这样的功能。您可以为ServerlessTasks设置目标函数;当任务执行失败时,函数计算支持自动将失败的上下文信息推送到消息队列等消息服务进行后续处理。如果你的处理逻辑支持自动化,函数计算还支持将失败任务的上下文信息推送回函数计算,执行你自定义的一段业务逻辑,实现业务补偿。您可以在异步调用配置页面配置成功和失败目标。更多配置内容请参考:PutFunctionAsyncInvokeConfig。综上所述,ServerlessTask提供的可观察性可以有效支持任务全生命周期的监控需求。所有控制台功能都可以使用开放的API进行定制,以满足更多需求。ServerlessTask的目标函数除了可以补偿任务失败外,还可以作为Event-Driven模式下的数据源,自动将处理后的事件传递给下游服务。