• 请不要在回答技术问题时复制粘贴 AI 生成的内容
chaleaochexist
V2EX  ›  程序员

websocket 方案求助 -- 如何实现实时进度提交给前端

  •  
  •   chaleaochexist · Sep 26, 2019 · 7174 views
    This topic created in 2594 days ago, the information mentioned may be changed or developed.

    前端点一个按钮, 发送一个 ajax, 后端开始做动作,同时不停的将处理进度实时推送给前端.

    现在的思路是, 前端和后端 ajax 同时绑定同一个 group. 后端给 group 发消息, websocket 接什么消息发什么消息,向同一个 group. 这样前端就收到消息了.

    def view(request):
        ws = websocket(***)
        # do something business logic
        ws.send()
        return 666
    

    伪代码大概是这样的,但是 websocket server 端的心跳机制会导致和 view 里面创建的 ws 客户端失去连接.

    现在的解决方案是, 在 view 里面创建一个线程, 在新起的线程里面 不停的发消息给 websocket server.

    拍脑袋感觉,应该在 view 里面做一个非阻塞带回调的 websocket 客户端,但是...如何实现呢...

    Supplement 1  ·  Sep 27, 2019

    实际效果 逻辑框图

    30 replies  •  2019-09-27 13:06:53 +08:00
    halk
    halk
    Sep 26, 2019
    1
    1. websocket server 端的心跳机制会导致和 view 里面创建的 ws 客户端失去连接.
    --这句话怎么理解?

    2. 试试 SSE,能满足你的需求吗
    wolfie
    wolfie
    Sep 26, 2019
    2
    ws 不是长连接吗,为什么会断开。

    客户端定时检查连接是否可用,断了就重连。
    Carseason
    Carseason
    Sep 26, 2019
    3
    websocket 是长连接,你心跳也不需要把当前的断开重连吧?
    服务端应该把客户端存到一个队列里面,然后当服务端接收到新消息后对该队列推送消息来实现广播
    hantsy
    hantsy
    Sep 26, 2019
    4
    SSE 比较适合
    poet00
    poet00
    Sep 26, 2019
    5
    拍脑袋想, 你这样子连 websocket 链接也创建不起来吧?

    并不是你在 server 端起一个 websocket server,然后不停的 send,客户端就会接收数据。 在 websocket 链接创建之前还有 http 报文做协商认证和链接过程。

    websocket 的第一个报文是这样的 (ietf rfc 7977):
    ```
    GET / HTTP/1.1
    Host: a.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Origin: http://www.example.com
    Sec-WebSocket-Protocol: msrp
    Sec-WebSocket-Version: 13
    ```

    一个可能的办法是: 页面先跟 server 创建一个 websocket 链接,使用 groupId 标识这个链接。

    页面点击动作的 ajax 将自己的 groupId 作为参数传入 view。view 触发业务逻辑以后就返回 ok, 不需要阻塞等待。

    业务逻辑处理过程中的进度信息,通过 websocket 推送到 client
    neoblackcap
    neoblackcap
    Sep 26, 2019 via iPhone
    6
    websocket 之类的长连接就该用 Tornado 之类的框架,一般基于 request-response 的框架当然会断
    KuroNekoFan
    KuroNekoFan
    Sep 26, 2019 via iPhone
    7
    你这提问看得我一头雾水
    21paradox
    21paradox
    Sep 26, 2019
    8
    用 server send events 吧,sse 或者前端轮询
    mengqi
    mengqi
    Sep 26, 2019
    9
    看了几遍题主的说明,最后终于确认:没看懂…
    1. 为什么前后端不能直接建立 websocket 长连接,而需要一个 group ?
    2. “server 端的心跳机制”是指服务器向客户端发送心跳还是客户端向服务端发送心跳?又为什么会导致客户端断开连接?
    3. 你贴的伪代码是服务端的代码吗?为什么后面的解决方案又说“在 view 里面创建一个线程, ……不停的发消息给 websocket server”?
    zhuzhibin
    zhuzhibin
    Sep 26, 2019 via iPhone
    10
    连接成功做你需要做的事 如果断了自己做一次重连
    izoabr
    izoabr
    Sep 26, 2019
    11
    我是直接用 rabbitmq 的 websocket,然后后台和前台都连一下,前台监控队列做回调显示进度就好了。
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    12
    @mengqi 我当时问这个问题的时候就想到了可能看不懂...

    一会儿主贴补一个框图...供您参考.
    1. 为什么前后端不能直接建立 websocket 长连接,而需要一个 group ?
    前端 后端 wsserver 我们现在有这三个实例, 后端需要将消息发送给前端 通过 ws. name 后端和 ws 之间需要通信,我们通过 ws.
    否则 ws 后端接到的消息如何推送给前端?
    2. “server 端的心跳机制”是指服务器向客户端发送心跳还是客户端向服务端发送心跳?又为什么会导致客户端断开连接?
    这个是 server 向 client 发送心跳, 断开连接是服务端(daphne)的配置,心跳间隔 20s.超过 20s 就主动断开连接. 修改心跳间隔是解决思路之一,但是目前我们并不想采用.
    3. 你贴的伪代码是服务端的代码吗?为什么后面的解决方案又说“在 view 里面创建一个线程, ……不停的发消息给 websocket server”?
    是后端的代码,后端属于 ws 客户端. 前端也是 ws 客户端.
    因为,如果客户端不停的给 ws 服务端,那么服务端就不会,也不需要发送心跳了.
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    13
    @neoblackcap 可不可以把一个 ws client 做成 异步形式?
    现在的项目就是用 django 做的,不可能为了一个 api 换框架啊.代价大了点.
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    14
    @wolfie
    客户端定时检查是指前端定时检查吗? 前端没有问题,浏览器会替我们发送心跳包.
    我们现在遇到的问题是另一个客户端 -- http 后端. 定时检查如何处理?我们现在是起了一个线程.
    @Carseason
    这个是框架的做法.我也没好办法.
    @kxiaong
    我就是这么做的. 但是遇到了 ws 服务端 20 秒会发送心跳包给 http 服务端. 我现在需要在 http 服务端 view 里面做一个非阻塞最好是异步的 ws 客户端. 除了起新线程, 有没有更好的办法.譬如用 gevent 有没有例子.
    neoblackcap
    neoblackcap
    Sep 27, 2019 via iPhone
    15
    @chaleaochexist 那你去用 Django 官方出的 channel 啊
    Nasei
    Nasei
    Sep 27, 2019 via Android
    16
    这么麻烦的吗…进度更新只用过 netcore 的 signalR,基本傻瓜式操作
    zazalu
    zazalu
    Sep 27, 2019
    17
    没看懂+1 不过我是因为菜没看懂 mark 下
    longkas
    longkas
    Sep 27, 2019 via Android
    18
    b821025551b
    b821025551b
    Sep 27, 2019❤️1
    19
    这个是 server 向 client 发送心跳, 断开连接是服务端(daphne)的配置,心跳间隔 20s.超过 20s 就主动断开连接. 修改心跳间隔是解决思路之一,但是目前我们并不想采用.
    -----------------------------------------------

    怎么总觉得怪怪的?正常心跳 1s 一个,20s 是没收到心跳就断了;你这是设置了 40s 一个心跳然后 20s 没心跳就断了?
    不想修改心跳是什么鬼?
    还有,即使是断了,再请求一个重连不就行了?想那么麻烦干吗?
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    20
    @b821025551b 谢谢,最后一句话有用.我没想到.

    心跳就是 20s 间隔.我看代码默认是这个配置.超过 20S(这个是心跳间隔)+30S(这个是 timeout) 就会主动断开连接.
    忘记是 channel 还是 daphne 的代码了.\
    ```
    class Server():
    def __init__():
    pass # 就在这里
    ```

    @neoblackcap 谢谢我用的就是 channel,另外本问题和 ws server 端没有太大关系,我的问题是如何做一个异步非阻塞的 ws 客户端.channel 还支持客户端吗?像 aiohttp 那样?
    tanszhe
    tanszhe
    Sep 27, 2019
    21
    这么简单的问题 ,搞不清楚 ……
    MonoLogueChi
    MonoLogueChi
    Sep 27, 2019 via Android
    22
    @Nasei signalR 吹?我也喜欢用
    LeeSeoung
    LeeSeoung
    Sep 27, 2019
    23
    ws 不是双向的么。。没搞明白你想做啥。。为啥 ws 会自己断。。
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    24
    @LeeSeoung 和本题无关的一种可能, timeout 不就断了吗?很好理解.
    shuizhengqi
    shuizhengqi
    Sep 27, 2019
    25
    直接 setInterval 不好使么?
    shuizhengqi
    shuizhengqi
    Sep 27, 2019
    26
    1s 一次,就能做到跟实时差不多的效果
    zpf
    zpf
    Sep 27, 2019
    27
    前端不应该直接请求 websocket 服务器,为什么还要先请求 view 层,view 层在做请求转发?
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    28
    @shuizhengqi 当然可以 setInterval 直接发 ajax 就可以了,和 websocket 有啥关系?

    @zpf 实时推送后台的处理进度.
    view 在做一个业务逻辑,并将业务逻辑的进度发送给前端.
    你的意思是说,这个业务逻辑不用 ajax 而是用 websocket 来实现是吗?
    hsfzxjy
    hsfzxjy
    Sep 27, 2019 via Android
    29
    django channels,了解一下
    chaleaochexist
    chaleaochexist
    OP
    Sep 27, 2019
    30
    @hsfzxjy 谢谢我用的就是 channel,另外本问题和 ws server 端没有太大关系,我的问题是如何做一个异步非阻塞的 ws 客户端.channel 还支持客户端吗?像 aiohttp 那样?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1306 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 21:02 · PVG 05:02 · LAX 13:02 · JFK 16:02
    ♥ Do have faith in what you're doing.