RabbitMQ Pika和Django通道websocket
我第一次使用Django频道和RabbitMQ pika。我正在尝试从RabbitMQ队列消费。我正在使用Django通道AsyncConsumer将其分组发送给websocket中连接的每个人RabbitMQ Pika和Django通道websocket,django,rabbitmq,django-channels,pika,Django,Rabbitmq,Django Channels,Pika,我第一次使用Django频道和RabbitMQ pika。我正在尝试从RabbitMQ队列消费。我正在使用Django通道AsyncConsumer将其分组发送给websocket中连接的每个人 用户类型1:可以创建任务 用户类型2:可以接受任务 用例:当用户类型1创建任务时,它将在rabbitmq中发布。当它从队列中使用时,它必须被组发送到前端。当用户类型2接受任务时,用户类型2的其他实例无法接受相同的任务,我们再次从队列中消费,并将队列中的下一个任务发送给所有人 我使用sync\u to\u
用户类型1
:可以创建任务
用户类型2
:可以接受任务
用例:当用户类型1
创建任务时,它将在rabbitmq中发布。当它从队列中使用时,它必须被组发送到前端。当用户类型2
接受任务时,用户类型2
的其他实例无法接受相同的任务,我们再次从队列中消费,并将队列中的下一个任务发送给所有人
我使用sync\u to\u async
在不同的线程中创建了连接,并将其从回调函数添加到内存中的列表中。
只要有人接受,我就把它从列表中弹出并确认队列
class AcceptTaskConsumer(AsyncConsumer):
body = [] #IN MEMORY LIST
delivery = {} #To store ack delivery_tag
async def websocket_connect(self, event):
print("AcceptTaskConsumer connected", event)
AcceptTaskConsumer.get_task() #STARTS Queue listener in new thread
self.room_group_name = "user_type_2"
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.send({
"type": "websocket.accept"
})
async def websocket_receive(self, event):
if event["text"] == "Hi": #If connecting first time
if AcceptTaskConsumer.body:
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "message",
"text": AcceptTaskConsumer.body[0]["body"]
}
)
else:
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "message",
"text": "No New Tasks"
}
)
else: #When someone accepts a task-> ack and send next task in queue
print(json.loads(event["text"])["id"])
AcceptTaskConsumer.channel.basic_ack(delivery_tag=AcceptTaskConsumer.delivery[json.loads(event["text"])["id"]])
AcceptTaskConsumer.delivery.pop(json.loads(event["text"])["id"])
AcceptTaskConsumer.body.pop(0)
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "message",
"text": "No New Tasks"
}
)
if AcceptTaskConsumer.body:
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "message",
"text": AcceptTaskConsumer.body[0]["body"]
}
)
async def message(self, event):
await self.send({
"type": "websocket.send",
"text": event["text"]
})
@classmethod
@sync_to_async
def get_task(cls): #pika consumer
cls.connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
cls.channel = cls.connection.channel()
cls.channel.queue_declare(queue='task_', arguments={"x-max-priority": 3})
cls.channel.basic_consume(
queue='task_', on_message_callback=AcceptTaskConsumer.callback, auto_ack=False)
cls.channel.start_consuming()
@classmethod
def callback(cls, ch, method, properties, body):
task_obj = {"body": json.dumps(body.decode("utf-8")),
"delivery_tag": method.delivery_tag}
AcceptTaskConsumer.body.append(task_obj)
AcceptTaskConsumer.delivery[json.loads(json.loads(task_obj["body"]))["id"]] = method.delivery_tag
cls.channel.stop_consuming()
async def websocket_disconnect(self, event):
print(event)
await self.send({
"type": "websocket.close"
})
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
我很确定这不是正确的方法,因为它没有按预期工作
我经常遇到像这样的错误
- 169个渠道中有39个在集团交付中产能过剩
- pika.exceptions.StreamLosError:流连接丢失:断开管道错误(32,“断开管道”)
有没有人对此有过想法?是否有更好的方法解决此问题?您应该将rabitMQ消费逻辑移出websocket消费程序 只要有一个运行Rabbit Consumer的django,该Consumer就可以从RabbitMQ获取消息,然后使用
send_group
将它们通过组发送到通道
如果使用django命令,则需要调用send_group,请参阅
从channels.layers导入获取通道层
通道层=获取通道层()
异步到同步(
信道\层组\发送
)(
“用户类型2”,
{“类型”:“消息”,“消息”:123}
)
然后,在websocket使用者中,您应该订阅用户希望/有权获得的组。您应该将rabitMQ消费逻辑移出websocket使用者 只要有一个运行Rabbit Consumer的django,该Consumer就可以从RabbitMQ获取消息,然后使用
send_group
将它们通过组发送到通道
如果使用django命令,则需要调用send_group,请参阅
从channels.layers导入获取通道层
通道层=获取通道层()
异步到同步(
信道\层组\发送
)(
“用户类型2”,
{“类型”:“消息”,“消息”:123}
)
然后,在websocket使用者中,您应该订阅用户想要/有权限获得的组。感谢您的发布如果我配置了自定义命令,它会在其他线程中运行吗?因为线程似乎是这里的问题。如果你知道更好的方法。我是earsAlso,如果我们在不同的命令中运行它,我们如何将消息传递给发送组?我们需要一个第三方脏存储,对吗?(我已经更新了awser,包括如何从您的命令中发送到组)谢谢发布。如果我配置了自定义命令,它会在不同的线程中运行吗?因为线程似乎是这里的问题。如果你知道更好的方法。我是earsAlso,如果我们在不同的命令中运行它,我们如何将消息传递给发送组?我们需要一个第三方脏存储,对吗?(我已经更新了awser,包括如何从命令中发送到组)