ubuntu安裝 RabbitMQ 以及 python mq 的監聽與發佈

查看 ubuntu 的版本 (ubuntu 版本無所謂 主要erlang版本和 MQ 版本要保持一致, 最好直接使用最新版erlang和 MQ)

>>> sudo lsb_release -a
	No LSB modules are available.
	Distributor ID: Ubuntu
	Description:    Ubuntu 16.04 LTS
	Release:        16.04
	Codename:       xenial

官網下載 erlang 版本

https://www.erlang-solutions.com/resources/download.html

如果以前安裝過erlang 最好先需要先進行刪除

sudo apt-get purge erlang*
rm -rf /usr/local/erlang/

上傳 erlang 的deb 包安裝 finalshell

dpkg -i esl-erlang_21.3.6-1_ubuntu_xenial_amd64.deb

上傳 erlang_21.3.6支持的 rabbitmq 的版本

sudo apt-get update
sudo apt-get -y install socat logrotate init-system-helpers adduser
sudo apt-get -y install wget
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.14/rabbitmq-server_3.7.15-1_all.deb
# or 去下載
https://www.rabbitmq.com/install-debian.html#manual-installation
sudo dpkg -i rabbitmq-server_3.7.15-1_all.deb

創建 web 的登錄用戶

>>> rabbitmqctl  add_user  {user_name}  {Password} 
>>> # 給指定用戶設置權限(最大權限)
>>> rabbitmqctl set_user_tags {user_name} administrator

設置nginx 代理端口 (沒有部署在公網環境, 這裏可以跳過)

# rabbitmq
 server {
     listen 15672;
     server_name 公網 ip;
     location / {
         proxy_pass http://127.0.0.1:15672;  # 阿里雲服務器內網ip
         proxy_set_header Host $host;
     }
 }
# 重啓 nginx
systemctl restart nginx
開啓 rabbitmq 的管理頁面 (web 端口是 15672)
sudo rabbitmq-plugins enable rabbitmq_management
# 重啓命令是
service rabbitmq-server restart
更換 mq的存儲路徑(沒有測試過)
mkdir -p /usr/local/rabbitmq/mnesia
mkdir -p /usr/local/rabbitmq/log
chmod -R 777 /usr/local/rabbitmq

# 2、創建或新增環境參數配置文件
vim /etc/rabbitmq/rabbitmq-env.conf
# 增加如下兩行內容
RABBITMQ_MNESIA_BASE=/usr/local/rabbitmq/mnesia
RABBITMQ_LOG_BASE=/usr/local/rabbitmq/log

# 用戶需要重新創建
rabbitmqctl  add_user  {user_name}  {Password}

# 給指定用戶設置權限(最大權限)
rabbitmqctl set_user_tags {user_name} administrator
# 重啓 rabbitmq 
sudo rabbitmq-plugins enable rabbitmq_management
service rabbitmq-server restart
python 的 mq 第三方庫 pika
    有使用過來 pipenv 的可以
    pipenv install pika  
    或者
    pip install pika
python mq 發佈
# -*- coding:utf-8 -*-
import pika
import json
class CustomQueueMQSender(object):
    def __init__(self, custom_queue):
        self.rabbit_host = "IP"
        self.rabbit_port = int('端口')
        self.rabbit_user = "用戶名"
        self.rabbit_pass = "密碼"
        self.channel_exchange = "虛擬機主機名稱"
        self.channel_host = "虛擬機主機名稱"
        self.channel_queue = custom_queue
        self.credentials = pika.credentials.PlainCredentials(self.rabbit_user, self.rabbit_pass)
        self.connection = pika.BlockingConnection(
            pika.ConnectionParameters(host=self.rabbit_host, port=self.rabbit_port, virtual_host=self.channel_host,
                                      connection_attempts=10, socket_timeout=20, credentials=self.credentials))
        self.success_channel = self.connection.channel()
        self.success_channel.queue_declare(queue=self.channel_queue, durable=True, exclusive=False, auto_delete=False,
                                           arguments=None)

    def re_connect(self):
        self.connection = pika.BlockingConnection(
            pika.ConnectionParameters(host=self.rabbit_host, port=self.rabbit_port, virtual_host=self.channel_host,
                                      connection_attempts=10, socket_timeout=20, credentials=self.credentials))
        self.success_channel = self.connection.channel()
        self.success_channel.queue_declare(queue=self.channel_queue, durable=True, exclusive=False, auto_delete=False,
                                           arguments=None)

    def send_regression_mq(self, message):
        """
        :param message: message is json 格式爲 json.dumps({"key":value})
        :return:
        """
        try:
            self.success_channel.basic_publish(exchange=self.channel_exchange, routing_key=self.channel_queue,
                                               body=message,
                                               properties=pika.BasicProperties(delivery_mode=2))

            print("send ok")
        except pika.exceptions.ConnectionClosed:
            print("ConnectionClosed, retrying...")
            self.re_connect()
        except pika.exceptions.AMQPChannelError as err:
            print("Caught a channel error: {}, stopping...".format(err))
            self.re_connect()
        except pika.exceptions.AMQPConnectionError:
            self.re_connect()
        # connection.close()


if __name__ == '__main__':
    CustomQueueMQSender(custom_queue='queue_name')
python MQ 監聽
# -*- coding:utf-8 -*-

"""
監聽自定義的 queue
改寫回調函數
"""

import logging, pika,json
import pika.exceptions
from time import sleep

class MQReceiver(object):
    def __init__(self, custom_queue):
        self._stopping = False
        self.rabbit_host = "IP"
        self.rabbit_port = int('端口')
        self.rabbit_user = "用戶名"
        self.rabbit_pass = "密碼"
        self.channel_exchange = "虛擬主機名稱"
        self.channel_host = "主機"
        self.channel_queue = custom_queue

    def callback(self, used_channel, basic_deliver, properties, body):
        # 獲取到消息隊列中的消息
        decoded_body = bytes.decode(body)
        decoded_body = json.loads(decoded_body)
        if decoded_body:
            # 接受 MQ 消息
            print(decoded_body)
            self.channel.basic_ack(delivery_tag=basic_deliver.delivery_tag)
        
    def stop(self):
        self._stopping = True
        logging.getLogger(__name__).info("Stopping listener...")

    def start_listener(self):
        self._listener()

    def _listener(self):
        logging.getLogger(__name__).info('Entering MQ listener loop...')
        while not self._stopping:
            try:
                self._long_poll()
            # 對一些連接錯誤進行處理,將繼續執行循環,從而完成重連
            except pika.exceptions.ConnectionClosed:
                print("ConnectionClosed, retrying...")
                sleep(3)
                continue
            # Do not recover on channel errors
            except pika.exceptions.AMQPChannelError as err:
                print("Caught a channel error: {}, stopping...".format(err))
                break
            # Recover on all other connection errors
            except pika.exceptions.AMQPConnectionError:
                print("AMQPConnectionError, retrying...")
                sleep(3)
                continue
        try:
            self.channel.stop_consuming()
        except Exception as error:
            print(error)

    def _long_poll(self):
        # 創建連接認證條件
        pika_credentials = pika.credentials.PlainCredentials(self.rabbit_user, self.rabbit_pass)
        # 創建一個Blocking的連接
        # virtual_host=self.channel_host,
        connection = pika.BlockingConnection(pika.ConnectionParameters(
            self.rabbit_host, virtual_host=self.channel_host, port=self.rabbit_port,
            credentials=pika_credentials,
            connection_attempts=10, socket_timeout=20,
            heartbeat=360))
        self.channel = connection.channel()
        # 聲明交換器,這裏應該和你消息生產者端保持一致設置
        self.channel.exchange_declare(exchange=self.channel_exchange, exchange_type='topic', durable=True,
                                      auto_delete=False)
        # 聲明隊列,這裏應該和你消息生產者端保持一致設置
        self.channel.queue_declare(queue=self.channel_queue, durable=True, exclusive=False, auto_delete=False)
        # 綁定操作
        self.channel.queue_bind(exchange=self.channel_exchange, queue=self.channel_queue,
                                routing_key=self.channel_queue)
        # 類似權重,按能力分發,如果有一個消息,就不在給你發,控制單個蜘蛛消費數量

        # 設置預取數
        self.channel.basic_qos(prefetch_count=1)
        self.channel.basic_consume(on_message_callback=self.callback,  # 如果收到消息,就調用Callback
                                   queue=self.channel_queue,  # 隊列
                                   # no_ack=True      # 一般不寫,處理完接收處理結果。宕機則發給其他消費者
                                   )

        # 開啓RabbitMQ接收模式,這代碼會阻塞運行,直到完成任務,纔會繼續
        self.channel.start_consuming()

if __name__ == '__main__':
    s = MQReceiver(custom_queue="你的隊列名稱")
    s.start_listener()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章