Celery-4.1 用户指南: Optimizing (优化)
简介
默认的配置做了很多折中考虑。它不是针对某个情况优化的,但是大多数情况下都工作的非常好。
基于一个特殊的使用场景,有很多优化可以做。
优化可以应用到运行环境的不同属性,可以是任务执行的时间,使用的总内存数,或者是高负载时的响应时间。
Ensuring操作
在Programming Pearl
这本书中,Jon Bentley 通过 一天有多少水从密西西比河流出?
这个问题提出了back-of-the-envelope
的概念。
这个练习的重点是要说明一个系统能及时处理的数据量有一个极限。Back of the envelope
计算能够被用来预先做这个计划。
在 Celery 中;如果一个任务需要10分钟完成处理,并且有10个任务每分钟进来一个,那么队列将永远不会空。这就是为什么监控队列长度非常重要的原因!
有一种方案是使用Munin
。你应该设置告警,使得一旦任意队列达到不可接受的长度你会收到告警。此时,你可以采取合理的措施,添加新的工作节点或者取消不必要的任务。
通用设置
librabbitmq
如果你使用 RabbitMQ(AMQP) 作为消息中间件,那么你可以安装 librabbitmq
模块这个 C 实现的优化过的客户端。
$ pip install librabbitmq
如果 librabbitmq
模块已经安装,amqp
传输将自动使用它,或者你也可以直接指定你想要的传输模块,使用 pyamqp://
或者 librabbitmq://
前缀。
消息中间件连接池
从2.5版本开始,消息中间件连接池被自动启用。
你可调整 broker_pool_limit
设置来减少竞争,并且这个值应该基于使用消息中间件的激活状态的thread/green-thread
数量。
使用临时队列
Celery 创建的队列默认是持久化的。这意味着即使消息中间会将消息写到硬盘使得即使重启任务也会被执行。
但是,一些情况下,消息丢失也没关系,所以并非所有的任务都需要持久化。你可以为这类任务消息创建一个临时队列来提高性能:
from kombu import Exchange, Queue task_queues = (
Queue('celery', routing_key='celery'),
Queue('transient', Exchange('transient', delivery_mode=1),
routing_key='transient', durable=False),
)
或者可以配置 task_routes
:
task_routes = {
'proj.tasks.add': {'queue': 'celery', 'delivery_mode': 'transient'}
}
delivery_mode
修改发送到队列的消息的递送方式。one
值代表消息不会写到硬盘,而two
值(默认)代表消息可被写到硬盘。
将你的任务导向新的临时队列,你可以通过声明queue
参数(或者使用task_routes设置
):
task.apply_async(args, queue='transient')
获取更多的信息,请查看 routing guide
。
工作单元设置
Prefetch 限制
Prefetch
是一个继承自 AMQP 的术语,它经常被用户错误理解。
prefetch
限制是一个工作单元可以预留的任务的数量。如果他为0,工作单元将继续消费消息,并不是说可能存储其他可用节点能更快的处理任务,或者消息可能不适合保留在内容中。
工作单元的默认 prefetch
值是worker_prefetch_multiplier
值乘以并行的数量(进程/线程/green-threads)。
如果你有许多长时间运行的任务,你可能会想将乘数值设置为1:意思是每个工作单元进程每次只预留一个任务。
但是 - 如果你有许多短时间运行任务,并且吞吐量/往返延迟对你又很重要,这个值应该大。如果消息已经被预先获取,且在内存中可用,工作单元每秒可以处理更多的任务。你可以通过实验来找到针对你场景的最佳值。值 50 或者 150 可能在这些环境中有意义。
如果你既有长时间任务又有短时间任务,最佳的方式是使用两个单独配置的工作单元节点,并且根据运行时间路由任务到相应的队列(查看路由任务这一节)。
每次预留一个任务
任务消息只有在被确认之后才会从队列中删除,所以如果工作单元在确认任务消息之前崩溃了,任务消息会重新递送到另一个工作单元(或者等当前工作单元恢复后又发送到这)
当使用默认的早确认机制,prefetch
乘数设置为 1,意味着每个工作单元将为每个进程最多预留一个额外的任务消息:或者,换而言之,如果工作单元使用 -c 10
参数启动,工作单元任意时刻最多预留20个任务(10个未确认的正在执行的任务,10个未确认的预留的任务)。
通常用户问禁用 prefetching of tasks
是否可能,但是他们实际意思是一个工作单元只预留工作单元进程数量的任务(对-c 10
来说,10个未确认的任务)
这是能实现的,但是必须启用延迟确认。使用这个选项而不是默认行为意味着已经开始的任务在由于电源失败或者工作单元实例被意外杀死而失败时会被重试,所以这也要求任务的幂等的。
(感觉这里延迟确认和早确认说反了)
另见:
Should I use retry or acks_late?
你可以通过如下配置使能这个行为:
task_acks_late = True
worker_prefetch_multiplier = 1
Prefork 池的 prefetch 设置
prefork
池会异步发送尽可能多的任务给工作进程,从效果上,这意味着进程在预先获取任务。
这可以提高性能,不过它也意味着任务可能阻塞在等待长时间任务运行完成:
-> send task T1 to process A
# A executes T1
-> send task T2 to process B
# B executes T2
<- T2 complete sent by process B -> send task T3 to process A
# A still executing T1, T3 stuck in local buffer and won't start until
# T1 returns, and other queued tasks won't be sent to idle processes
<- T1 complete sent by process A
# A executes T3
只要管道缓冲可写,工作单元将发送任务给工作进程。管道缓冲的大小与操作系统相关:一些可能只有 64K 大小,但是在近期的一些Linux发行版中这个缓冲大小是1MB(只能在系统层面上修改)。
你可以通过使用 -0fair
工作单元选项禁用这个预获取行为:
$ celery -A proj worker -l info -Ofair
使用这个选项,工作单元将只给当前可用的进程发送任务,禁用预获取行为:
-> send task T1 to process A
# A executes T1
-> send task T2 to process B
# B executes T2
<- T2 complete sent by process B -> send T3 to process B
# B executes T3 <- T3 complete sent by process B
<- T1 complete sent by process A
Footnotes
[*] 可以免费读这里: The back of the envelope. 这本书很经典,建议阅读。
[†] RabbitMQ 以及其他消息中间件轮询的方式发送消息,所以这对于一个激活的系统没有作用。如果没有 prefetch
限制并且你想重启集群,节点启动之间可能会有延迟。如果有3个离线节点和一个在线节点,所有的消息都会被递送到这个在线节点。
[‡] 这是一个并行设置; worker_concurrency
设置或者 celery 工作单元的-c
选项。
转自:https://blog.csdn.net/libing_thinking/article/details/78602736
Celery-4.1 用户指南: Optimizing (优化)的更多相关文章
- scons用户指南翻译(附gcc/g++参数详解)
scons用户指南 翻译 http://blog.csdn.net/andyelvis/article/category/948141 官网文档 http://www.scons.org/docume ...
- Android官方技术文档翻译——Gradle 插件用户指南(1-3)
不知道是什么网络问题,上午一直发不了博客,其它页面基本正常,就是在写博客这里,每次打开都是响应超时.刚才用了VPN,顺便试了一下,竟然能够编辑.想是CDN之类的问题吧. 这次翻译的是Gradle 插件 ...
- Android官方技术文档翻译——Gradle 插件用户指南(7)
本文译自Android官方技术文档<Gradle Plugin User Guide>,原文地址:http://tools.android.com/tech-docs/new-build- ...
- netty用户指南
Netty用户指南 一.前言 1.问题 当今世界我们需要使用通用的软件或库与其他组件进行通信,例如使用HTTP客户端从服务器中获取信息,或通过网络服务调用一个远程的方法.然而通用的协议及其实现通常不具 ...
- dubbo用户指南
用户指南 入门 背景 需求 架构 用法 快速启动 服务提供者 服务消费者 依赖 必需依赖 缺省依赖 可选依赖 成熟度 功能成熟度 策略成熟度 配置 Xml配置 属性配置 注解配置 API配置 示例 启 ...
- dubbo用户指南-总结
dubbo用户指南-总结 入门 背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用 ...
- Celery-4.1 用户指南: Calling Tasks(调用任务)
基础 本文档描述 Celery 中任务实例和 Canvas 使用的统一 “Calling API”. API 中定义了一个执行选项的标准集,以及三个方法: - apply_async(args[, k ...
- CVAT 用户指南
用户指南 计算机视觉标注工具(CVAT)是基于 Web 为计算机视觉算法标注视频和图像的在线工具. 它的灵感来自Vatic免费的.在线的.交互式的视频注释工具. CVAT有许多强大的功能: 在关键帧之 ...
- Gradle用户指南(1)-Gradle安装
前置条件 Gradle 需要 Java JDK 或者 JRE,版本是 6 及以上.Gradle 将会装载自己的 Groovy 库,因此,Groovy 不需要被安装.任何存在的 Groovy 安装都会被 ...
随机推荐
- linux下bwa和samtools的安装与使用
bwa的安装流程安装本软体总共需要完成以下两个软体的安装工作:1) BWA2) Samtools 1.BWA的安装a.下载BWA (download from BWA Source Forge ) h ...
- VC读取文件内容
// chopper.cpp : Defines the entry point for the console application. // #include "stdafx.h&quo ...
- C/C++输入数组
; printf("please enter the number:\n"); scanf("%d",&n); int *number=new int[ ...
- RocketMQ原理讲解系列文章
[RocketMQ原理解析][http://blog.csdn.net/quhongwei_zhanqiu/article/category/2548637] [消息的可靠性.顺序和重复][https ...
- 分享知识-快乐自己:Java中的经典算法之冒泡排序(Bubble Sort)
原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将 ...
- CSS高度自适应 height:100%;
在初次尝试高度自适应时都会遇到这样的问题: 对象的heith:100%; 并不能直接产生实际效果 为什么呢?之所以没有效果,与浏览器的解析方式有一定关系,查看下面代码 <!DOCTYPE htm ...
- LSM树——LSM 将B+树等结构昂贵的随机IO变的更快,而代价就是读操作要处理大量的索引文件(sstable)而不是一个,另外还是一些IO被合并操作消耗。
Basic Compaction 为了保持LSM的读操作相对较快,维护并减少sstable文件的个数是很重要的,所以让我们更深入的看一下合并操作.这个过程有一点儿像一般垃圾回收算法. 当一定数量的ss ...
- java快捷键大全
存盘 Ctrl+s(肯定知道) 注释代码 Ctrl+/ 取消注释 Ctrl+(Eclipse3已经都合并到Ctrl+/了) 代码辅助 Alt+/ 快速修复 Ctrl+1 代码格式化 Ctrl+Shif ...
- Linux_总结_01_VMware14虚拟机下安装CentOS7.x
一.前言 本文是采用最小安装方式 二.下载 1.官网 https://www.centos.org/download/ 在此页面下,选择 Minimal ISO 进行下载. 三.VMWare中新建虚拟 ...
- SpringMVC_总结_03_SpringMVC相关注解
一.前言 在前面的小节中,我们配置了注解驱动和自动扫描包,然后就可以使用SpringMVC相关注解了. 二.@Controller @Controller用来修饰类,源码如下: package org ...