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

2019-09-26 17:17:29 +08:00
 chaleaochexist

前端点一个按钮, 发送一个 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 客户端,但是...如何实现呢...

5698 次点击
所在节点    程序员
30 条回复
halk
2019-09-26 19:05:29 +08:00
1. websocket server 端的心跳机制会导致和 view 里面创建的 ws 客户端失去连接.
--这句话怎么理解?

2. 试试 SSE,能满足你的需求吗
wolfie
2019-09-26 19:17:59 +08:00
ws 不是长连接吗,为什么会断开。

客户端定时检查连接是否可用,断了就重连。
Carseason
2019-09-26 19:25:53 +08:00
websocket 是长连接,你心跳也不需要把当前的断开重连吧?
服务端应该把客户端存到一个队列里面,然后当服务端接收到新消息后对该队列推送消息来实现广播
hantsy
2019-09-26 20:39:54 +08:00
SSE 比较适合
kxiaong
2019-09-26 20:57:06 +08:00
拍脑袋想, 你这样子连 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
2019-09-26 21:01:42 +08:00
websocket 之类的长连接就该用 Tornado 之类的框架,一般基于 request-response 的框架当然会断
KuroNekoFan
2019-09-26 21:03:53 +08:00
你这提问看得我一头雾水
21paradox
2019-09-26 21:17:37 +08:00
用 server send events 吧,sse 或者前端轮询
mengqi
2019-09-26 21:31:58 +08:00
看了几遍题主的说明,最后终于确认:没看懂…
1. 为什么前后端不能直接建立 websocket 长连接,而需要一个 group ?
2. “server 端的心跳机制”是指服务器向客户端发送心跳还是客户端向服务端发送心跳?又为什么会导致客户端断开连接?
3. 你贴的伪代码是服务端的代码吗?为什么后面的解决方案又说“在 view 里面创建一个线程, ……不停的发消息给 websocket server”?
zhuzhibin
2019-09-26 22:12:30 +08:00
连接成功做你需要做的事 如果断了自己做一次重连
izoabr
2019-09-26 23:15:19 +08:00
我是直接用 rabbitmq 的 websocket,然后后台和前台都连一下,前台监控队列做回调显示进度就好了。
chaleaochexist
2019-09-27 07:04:56 +08:00
@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
2019-09-27 07:13:49 +08:00
@neoblackcap 可不可以把一个 ws client 做成 异步形式?
现在的项目就是用 django 做的,不可能为了一个 api 换框架啊.代价大了点.
chaleaochexist
2019-09-27 07:18:40 +08:00
@wolfie
客户端定时检查是指前端定时检查吗? 前端没有问题,浏览器会替我们发送心跳包.
我们现在遇到的问题是另一个客户端 -- http 后端. 定时检查如何处理?我们现在是起了一个线程.
@Carseason
这个是框架的做法.我也没好办法.
@kxiaong
我就是这么做的. 但是遇到了 ws 服务端 20 秒会发送心跳包给 http 服务端. 我现在需要在 http 服务端 view 里面做一个非阻塞最好是异步的 ws 客户端. 除了起新线程, 有没有更好的办法.譬如用 gevent 有没有例子.
neoblackcap
2019-09-27 07:33:54 +08:00
@chaleaochexist 那你去用 Django 官方出的 channel 啊
Nasei
2019-09-27 08:12:39 +08:00
这么麻烦的吗…进度更新只用过 netcore 的 signalR,基本傻瓜式操作
zazalu
2019-09-27 08:39:40 +08:00
没看懂+1 不过我是因为菜没看懂 mark 下
longkas
2019-09-27 08:55:21 +08:00
b821025551b
2019-09-27 08:59:10 +08:00
这个是 server 向 client 发送心跳, 断开连接是服务端(daphne)的配置,心跳间隔 20s.超过 20s 就主动断开连接. 修改心跳间隔是解决思路之一,但是目前我们并不想采用.
-----------------------------------------------

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

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

@neoblackcap 谢谢我用的就是 channel,另外本问题和 ws server 端没有太大关系,我的问题是如何做一个异步非阻塞的 ws 客户端.channel 还支持客户端吗?像 aiohttp 那样?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/604487

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX