AMQP异步实现aio_pika

  • AMQP aio_pika 工具类sdk
import asyncio
import aio_pika
import logging
import json


class RabbitMQConnector:

    def __init__(
        self,
        rabbitmq_ip,
        rabbitmq_port,
        ttl=21600000,
        username="guest",
        password="guest",
        exchange_name="eason_exchange",
        exchange_type="topic",
        queue_name="example_queue",
        routing_key=["eason_routing"],
        heartbeat=60,
    ):
        self.rabbitmq_ip = rabbitmq_ip
        self.rabbitmq_port = rabbitmq_port
        self.ttl = ttl
        self.username = username
        self.password = password
        self.exchange_name = exchange_name
        self.exchange_type = exchange_type
        self.queue_name = queue_name
        self.routing_key = routing_key
        self.heartbeat = heartbeat
        self.receive_message_queue = asyncio.Queue()
        self.connection = None
        self.channel = None
        self.exchange = None
        self.queue = None
        self.consumer_task = None

    async def on_connection_blocked(self):
        logging.warning("Connection to RabbitMQ was blocked")

    async def on_connection_unblocked(self):
        logging.info("Connection to RabbitMQ was unblocked")

    # 创建连接
    async def connect(self):
        while not self.channel:
            try:
                # 创建Connection
                self.connection = await aio_pika.connect_robust(
                    f"amqp://{self.username}:{self.password}@{self.rabbitmq_ip}:{self.rabbitmq_port}/",
                    heartbeat=self.heartbeat,
                    blocked_connection_callback=self.on_connection_blocked,
                    unblocked_connection_callback=self.on_connection_unblocked,
                )

                # 创建 Channel
                self.channel = await self.connection.channel()

                # 声明交换机
                self.exchange = await self.channel.declare_exchange(
                    self.exchange_name, self.exchange_type, durable=True
                )

                # 声明队列
                args = {"x-message-ttl": self.ttl} if self.ttl else None
                self.queue = await self.channel.declare_queue(
                    self.queue_name,
                    durable=True,
                    arguments=args,
                )

                # 绑定队列到交换机
                for key in self.routing_key:
                    await self.queue.bind(self.exchange, key)

                msg = "Connected to RabbitMQ Successed..."
                print(msg)
                logging.info(msg)

            except Exception as ex:
                logging.error(f"Failed to connect to RabbitMQ: {ex}")
                await asyncio.sleep(5) 
    
    # 生产消息
    async def publish(self, message: list):
        try:
            # Ensure the connection and channel are open
            if self.connection is None or self.connection.is_closed:
                await self.connect()

            # Publish message
            for key in self.routing_key:
                await self.exchange.publish(
                    aio_pika.Message(
                        body=json.dumps(message).encode("utf-8"),
                        content_type="application/json",
                    ),
                    routing_key=key,
                )

            logging.info(
                f"Sent message to {self.exchange_name} routing_key: {self.routing_key}"
            )

        except Exception as ex:
            logging.error(f"Failed to send message: {ex}")
    
    # 回调函数,具体处理消息
    async def callback(self, message: aio_pika.IncomingMessage):
        try:
            async with message.process(ignore_processed=True):
                msg_body = message.body.decode()  # 假设消息是二进制格式
                msg = json.loads(msg_body)
                routing_key = self.routing_key
                await self.receive_message_queue.put((routing_key, msg))
                await message.ack()  # 手动确认消息(no_ack=False 时需要)
        except Exception as ex:
            logging.error(f"Error processing message: {ex}")
            await message.nack()  # 拒绝消息(可选)

    # 消费信息
    async def consume(self):
        try:
            if self.connection is None or self.connection.is_closed:
                await self.connect()
                if self.queue is None:
                    self.queue = await self.connection.channel.declare_queue(
                        self.queue_name
                    )

            if self.consumer_task is None or self.consumer_task.done():
                self.consumer_task = asyncio.create_task(
                    self.queue.consume(self.callback, no_ack=False)
                )
                logging.info("Consuming task started...")

            # 等待消费者任务完成(通常不会完成,除非有错误或取消)
            await self.consumer_task

        except Exception as ex:
            logging.error(ex)
            await asyncio.sleep(5)
  • AMQP aio_pika 生产消息Demo

import asyncio
import logging
from async_amqp_sdk import RabbitMQConnector


async def publish_task(message: dict):
    try:
        rabbitmq_ip = "10.146.212.85"
        rabbitmq_port = 30025
        exchange_name = "eason_exchange"
        queue_name = "eason_queue"
        routing_key = ["eason_routing01", "eason_routing02"]

        rabbitmq = RabbitMQConnector(
            rabbitmq_ip=rabbitmq_ip,
            rabbitmq_port=rabbitmq_port,
            exchange_name=exchange_name,
            queue_name=queue_name,
            routing_key=routing_key,
        )

        while True:
            await rabbitmq.publish(message)
            print(f"publish message: {message}")
    except Exception as ex:
        msg = f"main function error:{ex}"
        logging.error(msg)


async def main():
    try:
        # 并行运行两个任务
        await asyncio.gather(
            publish_task(
                {
                    "message": "this is a test message aio_pika111111111111111111111111111111111"
                }
            ),
            publish_task(
                {
                    "message": "this is a test message aio_pika222222222222222222222222222222222"
                },
            ),
        )

    except Exception as ex:
        msg = f"main function error:{ex}"
        print(msg)
        logging(msg)


if __name__ == "__main__":
    asyncio.run(main())
  • AMQP aio_pika 消费消息Demo
import asyncio
import logging
from async_amqp_sdk import RabbitMQConnector


async def process_messages(rabbitmq):
    """
    持续处理来自队列的消息。
    """
    while True:
        try:
            # 获取消息
            message = await rabbitmq.receive_message_queue.get()
            print(f"Consumed message: {message}")

        except asyncio.CancelledError:
            print("Message processing stopped by user")
            break
        except Exception as ex:
            print(f"Error processing message: {ex}")
            logging.error(f"Error processing message: {ex}", exc_info=True)


async def consume_task():
    try:
        rabbitmq_ip = "10.146.212.85"
        rabbitmq_port = 30025
        exchange_name = "eason_exchange"
        queue_name = "eason_queue"
        routing_key = ["eason_routing01", "eason_routing02"]

        rabbitmq = RabbitMQConnector(
            rabbitmq_ip=rabbitmq_ip,
            rabbitmq_port=rabbitmq_port,
            exchange_name=exchange_name,
            queue_name=queue_name,
            routing_key=routing_key,
        )
        # 启动消费者任务
        consumer_task = asyncio.create_task(rabbitmq.consume())
        # 启动消息处理任务
        process_task = asyncio.create_task(process_messages(rabbitmq))

        # 等待任务完成(通常不会完成,除非有错误或取消)
        await asyncio.gather(consumer_task, process_task)

    except Exception as ex:
        msg = f"main function error:{ex}" 
        logging.error(msg)


async def main():
    try:
        await consume_task()  # 消费消息

    except Exception as ex:
        msg = f"main function error:{ex}" 
        logging(msg)


if __name__ == "__main__":
    asyncio.run(main())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值