2. Florent Rivoire
DevOps engineer
Team « Instances » (previously "Compute")
Aime le vélo, les poissons rouges et « Plus Belle La
Vie S5E17» (en VOST seulement !)
A toujours rêvé de rencontrer M. Propre en vrai !
2
18. Celery
18
• async task queue model
• similar to RPC : run a function (task) on a remote worker
• based on distributed message passing (like RabbitMQ)
• can create complex tasks graph
(sequential and/or parallel tasks, error callback, retry, etc.)
20. Worker "dispatcher"
20
• Handling allocation of instances, orchestration of tasks
• 1 logical worker
• but several "physical" copies (for HA and scaling)
• processing one « big » pool of tasks for the whole AZ
→ simple queuing: 1 queue « dispatcher »
21. [import+config of celery]
celery.start()
@celery.task()
def poweron_server(server_id, model):
physical_node = allocate(model)
prepare(server_id, physical_node)
———————————————————————————————————————————————
celery.send_task("poweron_server",
kwargs={'server_id': 12345,
'model': 'GP1-S'}
)
21
Example: simple task
Worker side
API side
27. Hypervisor’s workers
27
• Two workers per hypervisor :
1. to manage volumes (local-storage)
2. to manage VMs (start, stop, etc.)
• processing only tasks related to this HV precisely
→ not so common routing pattern
37. 37
Queue
Queue
Queue
Cluster RabbitMQ
API & worker
dispatcher
RabbitMQ routing to queues
Worker
dispatcher
Worker
« vm » HV-A
Worker
« vm » HV-B
? Queue
Worker
« storage » X
38. 38
Which
worker ?
Which
cluster ?
dispatcher storagevm
Which
cluster ?
dispatcher
vm
53-11
Which
HV ?
Which
HV ?
Which
HV ?
Which
HV ?
Which
HV ?
53 54 55 53 54
11 12
vm
53-12
Queue
Value
Criteria
vm
54-98
98 99
vm
53-99
…. …. ….
Logical routing
tree
39. Routing challenge
39
• Need routing to proper destination
• Simple to use
• Reasonable speed (msg/seconds)
• But a lot of queues/connections :
- 1000s
- growing with nb of HVs
40. Our solution
40
Use RabbitMQ features at maximum :
• « bindings »: routing-rules
• « exchange »: router, not storing msg
To route Celery messages
42. 42
Description Example
routing-key Scalar value (ASCII) celery-task [not used]
headers Key/value pairs
- daemon => storage
- cluster => 54
- hypervisor => 98
content_type Format of the body application/json
body
Free format
(never read by RabbitMQ)
{
id: "1326d7f2-fc36-4271-…",
task: "download_volume",
kwargs: {volume_id: 56789,
verify_chksum: True}
}
RabbitMQ, message structure
43. RabbitMQ, binding
43
• 1 src exchange
• some condition:
- routing-key match
- one key/value match
• 1 target (exchange / queue)
Multiple bindings possible (« many to many »)
44. RabbitMQ, binding
44
• 1 src exchange
• some condition:
- routing-key match
- one key/value match
• 1 target (exchange / queue)
Multiple bindings possible (« many to many »)
Example :
• msg in exchange « global »
• if match:
- header « daemon »
- is equal to « dispatcher »
• route to queue « dispatcher »
68. Experience (1)
68
• Tuning Celery parameters
→ nb of process, nb of tasks/process, prefetch, etc.
• Complex config (lib over-engineered at first)
→ feature removed: broadcast, namespace, versioning
• End2end tracing (1 API-call, N tasks)
→ generate a « req-id » on API
→ correlate all tasks with the req-id
69. Experience (2)
69
• Too many connections on RabbitMQ
→ enough RAM + proper limits (erlang process, file-
descriptors)
• High availability control-plane
→ clustering RabbitMQ, multiple copies of workers
• RabbitMQ management web interface
→ powerful, use it !!
71. MERCI
Suivez notre actualité, tutoriels inédits et infos cloud sur
Twitter et LinkedIn @Scaleway
71
Et retrouvez toutes les présentations du Scaleday sur Slideshare :