44
one system to rule them all

RabbitMQ + CouchDB = Awesome

Embed Size (px)

DESCRIPTION

Slides from a talk I gave at erlounge Wellington about a workflow system using RabbitMQ and CouchDB.

Citation preview

Page 1: RabbitMQ + CouchDB = Awesome

one system to rule them all

Page 2: RabbitMQ + CouchDB = Awesome
Page 3: RabbitMQ + CouchDB = Awesome

the challenge

Page 4: RabbitMQ + CouchDB = Awesome

• write a backend that scales well

• handle various frontends (web, iPhone, ...)

• runs “somewhere in the cloud”

• easy to maintain and extend

Page 5: RabbitMQ + CouchDB = Awesome

the solution

Page 6: RabbitMQ + CouchDB = Awesome

RabbitMQ+CouchDB=Awesome

Page 7: RabbitMQ + CouchDB = Awesome

Part I

Page 8: RabbitMQ + CouchDB = Awesome

• AMQP based Message Queue

• lots of additional transports (XMPP, HTTP, STOMP, ...)

• erlang based

RabbitMQ

Page 9: RabbitMQ + CouchDB = Awesome

RabbitMQ

daemon

daemon

daemon daemon

frontend frontend frontend

Page 10: RabbitMQ + CouchDB = Awesome

• every functionality gets a backed daemon

• every daemon has a queue associated

• communication via a JSON message that gets passed around

Page 11: RabbitMQ + CouchDB = Awesome

the JSON message

Page 12: RabbitMQ + CouchDB = Awesome
Page 13: RabbitMQ + CouchDB = Awesome

{ "response": { "expiry": 710, "ts": "1234425918", "name": "Lenz Gschwendtner", "last4": 0, "cc_type": "master" }, "data": { "options": { "billing_id": "E16003D4-B312-BEA23D9AB789" }, "command": "billing_info" }, "meta": { "lang": "en", "reply_to": "B312-E16003D4-BEA23D9AB789", "platform": "iwmn" }}

Page 14: RabbitMQ + CouchDB = Awesome

• RPC style communication

• if the flow through the system is static

• fast transactions

works great for ...

Page 15: RabbitMQ + CouchDB = Awesome

gets fiddly when ...

• there are asynchronous callbacks from outside

• message flow can change based on various factors

• tasks can take days to complete

Page 16: RabbitMQ + CouchDB = Awesome

Part II

Page 17: RabbitMQ + CouchDB = Awesome

workflows

Page 18: RabbitMQ + CouchDB = Awesome
Page 19: RabbitMQ + CouchDB = Awesome

... again ...

Page 20: RabbitMQ + CouchDB = Awesome

• various frontends

• backend daemons

• JSON messages

what we have ...

Page 21: RabbitMQ + CouchDB = Awesome

what we need

• a way to describe message flow

• a easy flexible way to write and update it

Page 22: RabbitMQ + CouchDB = Awesome

CouchDB

Page 23: RabbitMQ + CouchDB = Awesome

... to the rescue

Page 24: RabbitMQ + CouchDB = Awesome
Page 25: RabbitMQ + CouchDB = Awesome

workflow

• really only a path definition through backends

• some sort of condition management

• a backend definition

Page 26: RabbitMQ + CouchDB = Awesome

{ "_id": "f7a4408898e5...a05b4181045", "_rev": "3-633060011", "name": "billing_info", "type": "workflow", "user": "iwmn", "path": [ "logger", "billing", "billing_iwmn_cc" ]}

Page 27: RabbitMQ + CouchDB = Awesome

... and the backend definition

Page 28: RabbitMQ + CouchDB = Awesome

{ "_id": "33adf2e3efc3...f423929f057ac", "_rev": "3-3507820969", "conn": "rpc", "type": "worker", "name": "billing_iwmn_cc", "location": "billing.cc", "description": "the CC interface", "command": "billing_verify_cc"}

Page 29: RabbitMQ + CouchDB = Awesome

now we need a workflow daemon

Page 30: RabbitMQ + CouchDB = Awesome

RabbitMQ

daemon

daemon

daemon daemon

frontend frontend frontend

workflow

Page 31: RabbitMQ + CouchDB = Awesome

where are we now?

• we can call backends as before

• we can call workflows via the workflow queue

• we can manage workflows in CouchDB

Page 32: RabbitMQ + CouchDB = Awesome

Part III

Page 33: RabbitMQ + CouchDB = Awesome

asynchronous callbacks

Page 34: RabbitMQ + CouchDB = Awesome
Page 35: RabbitMQ + CouchDB = Awesome

problem

• we start a workflow

• we call some external API

• the external API somehow notifies us (Mail, Callback URL, ...) about progress

• we need to continue in the workflow

Page 36: RabbitMQ + CouchDB = Awesome

we need a persistent message store

Page 37: RabbitMQ + CouchDB = Awesome

{ "_id": "22cd37afd06c82129adb665d3150f570", "_rev": "3-2669449653", "status": "done", "last_update": 1252296819, "name": "E16003D4-F8DB-11DD-B312-BEA23D9AB789", "message": { "response": { "expiry": 710, "name": "Lenz Gschwendtner", "last4": 0, "cc_type": "master" }, "data": { "options": { "billing_id": "E16003D4-F8DB-11DD-B312-BEA23D9AB789" }, "command": "billing_info" }, "meta": { "lang": "de", "name": "E16003D4-F8DB-11DD-B312-BEA23D9AB789", "orig_reply_to": "D234ADE8-9B64-11DE-A92C-E5EF11C6FBDB", "reply_to": "workflow", "user": "iwmn", "log": [ "logger", "billing", "billing.iwmn.info" ], "platform": "iwmn" } }, "created": 1252296815, "type": "bill"}

Page 38: RabbitMQ + CouchDB = Awesome

one more problemhow do we correlate messages

Page 39: RabbitMQ + CouchDB = Awesome

... with some CouchDB awesome ...

Page 40: RabbitMQ + CouchDB = Awesome

• the backend daemon for the callback polls a view in CouchDB

• we can search for any value in the request we sent

• all we need is a view that searches for the very value this external API uses as correlation ID

Page 41: RabbitMQ + CouchDB = Awesome

RabbitMQ

daemon

daemon

daemon daemon

frontend frontend frontend

workflow

externalcallback

Page 42: RabbitMQ + CouchDB = Awesome

Lenz Gschwendtner

CTO iWantMyName

@norbu09

me

Page 43: RabbitMQ + CouchDB = Awesome

credits

• RabbitMQ

• CouchDB

• Erlang and Perl