python-3.x - 从 rest api 或服务器向特定的 django websocket 客户端发送响应

标签 python-3.x websocket redis django-channels

consumer.py

    # accept websocket connection
    def connect(self):
    self.accept()

    # Receive message from WebSocket
    def receive(self, text_data):
     text_data_json = json.loads(text_data)
     command = text_data_json['command']
     job_id = text_data_json['job_id']
     if command == 'subscribe':
        self.subscribe(job_id)
     elif command == 'unsubscribe':
        self.unsubscribe(job_id)
     else:
        self.send({
            'error': 'unknown command'
        })

   # Subscribe the client to a particular 'job_id'
   def subscribe(self, job_id):
    self.channel_layer.group_add(
        'job_{0}'.format(job_id),
        self.channel_name
    )       

   # call this method from rest api to get the status of a job
   def send_job_notification(self, message, job_id):
    channel_layer = get_channel_layer()
    group_name = 'job_{0}'.format(job_id)
    channel_layer.group_send(
    group_name,
    {
        "type": "send.notification", 
        "message": message, 
    }
)   

# Receive message from room group
def send_notification(self, event):
    message = event['message']
    # Send message to WebSocket
    self.send(text_data=json.dumps(
     message))

在上面的代码中,我试图做的是将客户端连接到套接字,并通过使用“订阅”方法创建一个名为“job_1”的组并将其添加到 channel 层,将客户端订阅到特定的“job_id”。组的创建是动态的。

我正在使用下面来自 Google 的“简单 websocket 客户端扩展”来连接到上面的 websocket。我能够与 websocket 建立连接并向其发送请求,如下图所示。

enter image description here

现在,由于客户端已连接并订阅了特定的“job_id”, 我正在使用“ postman ”通过在请求中传递 job_id 来向订阅特定“job_id”的上述连接客户端(简单的 websocket 客户端扩展)发送通知,如下面黄色突出显示。

当我向“REST-API”发帖时,我正在调用“consumer.py”文件的“send_job_notification(self, message, job_id)”方法以及图中所示的“job_id”为“1”下面是黄色的

enter image description here

完成所有这些后,我没有看到任何消息发送到连接的客户端,该客户端订阅了“REST-API”调用的“job_id”。

任何帮助将不胜感激,因为它已经拖延了很长时间。

编辑:

感谢 Ken 的建议,将方法设置为“@staticmethod”是值得的,但 Ken 我如何让 API 向连接的客户端发送作业状态更新,因为我的长期运行作业会在某个进程中运行并发送更新消息通过 REST-API 返回后端,然后需要将更新发送到正确的客户端(通过 websockets)。

我对套接字消费者的 API 调用如下:

从 websocket_consumer 导入消费者 类 websocket_connect(APIView): def post(self, request, id): 消费者.ChatConsumer.send_job_notification("hello",id)

我的套接字消费者代码如下: enter image description here

编辑

`CHANNEL_LAYERS = {
"default": {
    "BACKEND": "channels_redis.core.RedisChannelLayer",
    "CONFIG": {
        "hosts": [("localhost", 6379)],
    },
},

}` 如您所见,“Redis”服务也在运行 enter image description here

编辑-1

enter image description here

最佳答案

您不能直接从外部代码调用消费者中的方法,因为您需要将特定的消费者实例连接到您的客户端。这是通过使用消息传递系统或代理(如 reddis)实现的 channel 层的工作。 据我所知,您已经朝着正确的方向前进,除了 send_job_notification 是一个需要实例化消费者的实例方法。改为将其设为静态方法,这样您就可以在没有消费者实例的情况下直接调用它

@staticmethod
def send_job_notification(message, job_id):
    channel_layer = get_channel_layer()
    group_name = 'job_{0}'.format(job_id)
    channel_layer.group_send(
    group_name,
    {
        "type": "send.notification", 
        "message": message, 
    }

在您的 API View 中,您可以将其简单地称为: ChatConsumer.send_job_notification(message, job_id)

关于python-3.x - 从 rest api 或服务器向特定的 django websocket 客户端发送响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55122184/

相关文章:

python - 如何批量更新Elasticsearch中的字段?

python - Pandas 如何按时间段过滤 DataFrame

nginx - Shiny 的 Websocket 错误

ruby-on-rails - Redis + Devise 配置困惑

caching - 保存到 Redis 缓存时性能较差(使用 ServiceStack.Redis)

scala - Actor 的接收方法中的多个 Future 调用

python - 使用 Python 读取文本文件并分类到字典中时遇到问题

python - 在 Linux 上 pip 安装 UnicodeDecodeError

javascript - Firebase - 当 websocket 被公司代理/防火墙阻止时,是否有一个标志来强制进行长轮询?

c# - 从 ASP.NET Core 中的 WebSocket 请求返回什么 IActionResult?