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()


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