├── README.md ├── consumer ├── Dockerfile └── consumer.py ├── docker-compose.yml └── producer ├── Dockerfile └── producer.py /README.md: -------------------------------------------------------------------------------- 1 | # RabbitMQ implementation in Python using Docker 2 | This is a basic example to implement RabbitMQ in Python, and deploy using Docker. 3 | 4 | It uses `pika` in python to connect to RabbitMQ. 5 | 6 | Producer producer a 100 messages of text `Hello World` to the queue 7 | 8 | Consumer consumes these messages, prints them and sleeps for 2 seconds before acking each of them. 9 | 10 | We have used docker to run the program. Docker Compose has been used to spawn the multiple containers needed. We spawn one container each for RabbitMQ and producer, while 2 containers for consumer. This to exhibit parallel consumption from the same queue. 11 | 12 | ## Dependencies 13 | 14 | * [Python 3.7](https://www.python.org/downloads/release/python-370/) 15 | * [Docker](https://www.docker.com/) 16 | * [RabbitMQ 3.8.3-rc.1](https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.8.3-rc.1) 17 | * [Pika 1.1.0](https://github.com/pika/pika) 18 | 19 | ## Run the program 20 | 21 | * To run `docker-compose up` 22 | 23 | * To clean up `docker-compose down -v --rmi all --remove-orphans` 24 | 25 | * We can run separate container by `docker-compose up producer` and so on 26 | 27 | * While the containers are running, we can monitor the queue on the dashboard http://localhost:15672/ with [Username/Password] as [guest/guest] 28 | -------------------------------------------------------------------------------- /consumer/Dockerfile: -------------------------------------------------------------------------------- 1 | # basic python image 2 | FROM python:3.7 3 | 4 | # install pika to access rabbitmq 5 | RUN pip install pika 6 | 7 | # Without this setting, Python never prints anything out. 8 | ENV PYTHONUNBUFFERED=1 9 | 10 | # declare the source directory 11 | WORKDIR /usr/src/app/consumer 12 | 13 | # copy the file 14 | COPY consumer.py . 15 | 16 | # start command 17 | CMD [ "python", "consumer.py" ] 18 | -------------------------------------------------------------------------------- /consumer/consumer.py: -------------------------------------------------------------------------------- 1 | import pika 2 | import time 3 | import os 4 | 5 | # read rabbitmq connection url from environment variable 6 | amqp_url = os.environ['AMQP_URL'] 7 | url_params = pika.URLParameters(amqp_url) 8 | 9 | # connect to rabbitmq 10 | connection = pika.BlockingConnection(url_params) 11 | chan = connection.channel() 12 | 13 | # declare a new queue 14 | # durable flag is set so that messages are retained 15 | # in the rabbitmq volume even between restarts 16 | chan.queue_declare(queue='hello', durable=True) 17 | 18 | 19 | def receive_msg(ch, method, properties, body): 20 | """function to receive the message from rabbitmq 21 | print it 22 | sleep for 2 seconds 23 | ack the message""" 24 | 25 | print('received msg : ', body.decode('utf-8')) 26 | time.sleep(2) 27 | print('acking it') 28 | ch.basic_ack(delivery_tag=method.delivery_tag) 29 | 30 | 31 | # to make sure the consumer receives only one message at a time 32 | # next message is received only after acking the previous one 33 | chan.basic_qos(prefetch_count=1) 34 | 35 | # define the queue consumption 36 | chan.basic_consume(queue='hello', 37 | on_message_callback=receive_msg) 38 | 39 | print("Waiting to consume") 40 | # start consuming 41 | chan.start_consuming() 42 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.2" 2 | 3 | # list of containers to be run 4 | services: 5 | 6 | # rabbit_mq container uses the default rabbitmq image 7 | # exposes the ports 8 | # uses the specified volume 9 | rabbit_mq: 10 | 11 | # we use management image to get the 12 | # plugin for web dashboard 13 | image: rabbitmq:3.8-rc-management 14 | container_name: rabbit_mq 15 | ports: 16 | - '5672:5672' 17 | - '15672:15672' 18 | volumes: 19 | - rabbit_mqdata:/usr/share/rabbitmq/data 20 | 21 | # produces container builds the producer image 22 | # and produces message to the queue 23 | producer: 24 | build: producer 25 | depends_on: 26 | - rabbit_mq 27 | environment: 28 | AMQP_URL: 'amqp://rabbit_mq?connection_attempts=10&retry_delay=10' 29 | volumes: 30 | - ./producer:/usr/src/app/producer 31 | 32 | # consumer container builds the consumer image 33 | # and consumes messages from the queue 34 | # we spawn 2 consumer containers to run parallely 35 | # on the same queue 36 | consumer1: 37 | build: consumer 38 | depends_on: 39 | - rabbit_mq 40 | environment: 41 | AMQP_URL: 'amqp://rabbit_mq?connection_attempts=10&retry_delay=10' 42 | volumes: 43 | - ./consumer:/usr/src/app/consumer 44 | consumer2: 45 | build: consumer 46 | depends_on: 47 | - rabbit_mq 48 | environment: 49 | AMQP_URL: 'amqp://rabbit_mq?connection_attempts=10&retry_delay=10' 50 | volumes: 51 | - ./consumer:/usr/src/app/consumer 52 | volumes: 53 | rabbit_mqdata: 54 | driver: local 55 | -------------------------------------------------------------------------------- /producer/Dockerfile: -------------------------------------------------------------------------------- 1 | # basic python image 2 | FROM python:3.7 3 | 4 | # install pika to access rabbitmq 5 | RUN pip install pika 6 | 7 | # Without this setting, Python never prints anything out. 8 | ENV PYTHONUNBUFFERED=1 9 | 10 | # declare the source directory 11 | WORKDIR /usr/src/app/producer 12 | 13 | # copy the file 14 | COPY producer.py . 15 | 16 | # start command 17 | CMD [ "python", "producer.py" ] 18 | -------------------------------------------------------------------------------- /producer/producer.py: -------------------------------------------------------------------------------- 1 | import pika 2 | import os 3 | 4 | # read rabbitmq connection url from environment variable 5 | amqp_url = os.environ['AMQP_URL'] 6 | url_params = pika.URLParameters(amqp_url) 7 | 8 | # connect to rabbitmq 9 | connection = pika.BlockingConnection(url_params) 10 | chan = connection.channel() 11 | 12 | # declare a new queue 13 | # durable flag is set so that messages are retained 14 | # in the rabbitmq volume even between restarts 15 | chan.queue_declare(queue='hello', durable=True) 16 | 17 | # publish a 100 messages to the queue 18 | for i in range(100): 19 | chan.basic_publish(exchange='', routing_key='hello', 20 | body='Hello World', properties=pika.BasicProperties(delivery_mode=2)) 21 | print("Produced the message") 22 | 23 | # close the channel and connection 24 | # to avoid program from entering with any lingering 25 | # message in the queue cache 26 | chan.close() 27 | connection.close() 28 | --------------------------------------------------------------------------------