gpt4 book ai didi

django - 如何使用 Django channel 进行 HTTP 长轮询

转载 作者:行者123 更新时间:2023-12-01 03:25:36 24 4
gpt4 key购买 nike

我正在尝试为 Web 请求实现 HTTP 长轮询,但似乎在 Channels 文档中找不到合适的示例,一切都与 Web Sockets 有关。

使用 HTTP 消息时我需要做的是:

  • 等待保存特定模型时将发送的关于组的消息(可能使用信号)
  • 等待超时,如果没有收到消息

  • 然后返回一些东西给客户。

    现在我有可以在示例中看到的代码:
    def http_consumer(message):
    # Make standard HTTP response - access ASGI path attribute directly
    response = HttpResponse("Hello world! You asked for %s" % message.content['path'])
    # Encode that response into message format (ASGI)
    for chunk in AsgiHandler.encode_response(response):
    message.reply_channel.send(chunk)

    所以我必须在这个 http_consumer 中返回一些东西这将表明我暂时没有要发送的内容,但我无法在此处屏蔽。也许我不能返回任何东西?然后我必须在特定组上捕获新消息,或者达到超时,并将响应发送给客户端。

    看来我需要存储 message.reply_channel某个地方以便我稍后做出回应,但我不知道如何:
  • 捕获群消息并生成响应
  • 当没有收到消息(超时)时生成响应,也许延迟服务器可以在这里工作?
  • 最佳答案

    所以,我最终这样做的方式如下所述。

    在消费者中,如果我发现我没有立即响应发送,我将存储 message.reply_channel在相关事件的情况下将被通知的组上,并安排延迟消息,该消息将在达到最大等待时间时触发。

    group_name = group_name_from_mac(mac_address)
    Group(group_name).add(message.reply_channel)
    message.channel_session['will_wait'] = True

    delayed_message = {
    'channel': 'long_polling_terminator',
    'content': {'mac_address': mac_address,
    'reply_channel': message.reply_channel.name,
    'group_name': group_name},
    'delay': settings.LONG_POLLING_TIMEOUT
    }
    Channel('asgi.delay').send(delayed_message, immediately=True)

    然后,可能会发生两件事。要么我们在相关组上收到一条消息并提前发送响应,要么延迟的消息到达表明我们已经用尽了我们必须等待的时间,并且必须返回一个表明没有事件的响应。

    为了在相关事件发生时触发消息,我依赖 Django 信号:
    class PortalConfig(AppConfig):
    name = 'portal'

    def ready(self):
    from .models import STBMessage

    post_save.connect(notify_new_message, sender=STBMessage)

    def notify_new_message(sender, **kwargs):
    mac_address = kwargs['instance'].set_top_box.id
    layer = channel_layers['default']
    group_name = group_name_from_mac(mac_address)
    response = JsonResponse({'error': False, 'new_events': True})
    group = Group(group_name)
    for chunk in AsgiHandler.encode_response(response):
    group.send(chunk)

    当超时到期时,我在 long_polling_terminator 上收到一条消息 channel ,我需要发送一条消息,表明没有事件:
    def long_polling_terminator(message):
    reply_channel = Channel(message['reply_channel'])
    group_name = message['group_name']
    mac_address = message['mac_address']
    layer = channel_layers['default']
    boxes = layer.group_channels(group_name)
    if message['reply_channel'] in boxes:
    response = JsonResponse({'error': False, 'new_events': False})
    write_http_response(response, reply_channel)
    return

    最后要做的是从组中删除此回复 channel ,我在 http.disconnect 中执行此操作消费者:
    def process_disconnect(message, group_name_from_mac):
    if message.channel_session.get('will_wait', False):
    reply_channel = Channel(message['reply_channel'])
    mac_address = message.channel_session['mac_address']
    group_name = group_name_from_mac(mac_address)
    Group(group_name).discard(reply_channel)

    关于django - 如何使用 Django channel 进行 HTTP 长轮询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41858300/

    24 4 0
    文章推荐: Laravel 关系 - 在 View 中访问相关值
    文章推荐: javascript - 如何通过将鼠标悬停在子
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com