前端点一个按钮, 发送一个 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 客户端,但是...如何实现呢...
实际效果 逻辑框图
1
halk 2019-09-26 19:05:29 +08:00
1. websocket server 端的心跳机制会导致和 view 里面创建的 ws 客户端失去连接.
--这句话怎么理解? 2. 试试 SSE,能满足你的需求吗 |
2
wolfie 2019-09-26 19:17:59 +08:00
ws 不是长连接吗,为什么会断开。
客户端定时检查连接是否可用,断了就重连。 |
3
Carseason 2019-09-26 19:25:53 +08:00
websocket 是长连接,你心跳也不需要把当前的断开重连吧?
服务端应该把客户端存到一个队列里面,然后当服务端接收到新消息后对该队列推送消息来实现广播 |
4
hantsy 2019-09-26 20:39:54 +08:00
SSE 比较适合
|
5
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 |
6
neoblackcap 2019-09-26 21:01:42 +08:00 via iPhone
websocket 之类的长连接就该用 Tornado 之类的框架,一般基于 request-response 的框架当然会断
|
7
KuroNekoFan 2019-09-26 21:03:53 +08:00 via iPhone
你这提问看得我一头雾水
|
8
21paradox 2019-09-26 21:17:37 +08:00
用 server send events 吧,sse 或者前端轮询
|
9
mengqi 2019-09-26 21:31:58 +08:00
看了几遍题主的说明,最后终于确认:没看懂…
1. 为什么前后端不能直接建立 websocket 长连接,而需要一个 group ? 2. “server 端的心跳机制”是指服务器向客户端发送心跳还是客户端向服务端发送心跳?又为什么会导致客户端断开连接? 3. 你贴的伪代码是服务端的代码吗?为什么后面的解决方案又说“在 view 里面创建一个线程, ……不停的发消息给 websocket server”? |
10
zhuzhibin 2019-09-26 22:12:30 +08:00 via iPhone
连接成功做你需要做的事 如果断了自己做一次重连
|
11
izoabr 2019-09-26 23:15:19 +08:00
我是直接用 rabbitmq 的 websocket,然后后台和前台都连一下,前台监控队列做回调显示进度就好了。
|
12
chaleaochexist OP @mengqi 我当时问这个问题的时候就想到了可能看不懂...
一会儿主贴补一个框图...供您参考. 1. 为什么前后端不能直接建立 websocket 长连接,而需要一个 group ? 前端 后端 wsserver 我们现在有这三个实例, 后端需要将消息发送给前端 通过 ws. name 后端和 ws 之间需要通信,我们通过 ws. 否则 ws 后端接到的消息如何推送给前端? 2. “server 端的心跳机制”是指服务器向客户端发送心跳还是客户端向服务端发送心跳?又为什么会导致客户端断开连接? 这个是 server 向 client 发送心跳, 断开连接是服务端(daphne)的配置,心跳间隔 20s.超过 20s 就主动断开连接. 修改心跳间隔是解决思路之一,但是目前我们并不想采用. 3. 你贴的伪代码是服务端的代码吗?为什么后面的解决方案又说“在 view 里面创建一个线程, ……不停的发消息给 websocket server”? 是后端的代码,后端属于 ws 客户端. 前端也是 ws 客户端. 因为,如果客户端不停的给 ws 服务端,那么服务端就不会,也不需要发送心跳了. |
13
chaleaochexist OP @neoblackcap 可不可以把一个 ws client 做成 异步形式?
现在的项目就是用 django 做的,不可能为了一个 api 换框架啊.代价大了点. |
14
chaleaochexist OP |
15
neoblackcap 2019-09-27 07:33:54 +08:00 via iPhone
@chaleaochexist 那你去用 Django 官方出的 channel 啊
|
16
Nasei 2019-09-27 08:12:39 +08:00 via Android
这么麻烦的吗…进度更新只用过 netcore 的 signalR,基本傻瓜式操作
|
17
zazalu 2019-09-27 08:39:40 +08:00
没看懂+1 不过我是因为菜没看懂 mark 下
|
19
b821025551b 2019-09-27 08:59:10 +08:00 1
这个是 server 向 client 发送心跳, 断开连接是服务端(daphne)的配置,心跳间隔 20s.超过 20s 就主动断开连接. 修改心跳间隔是解决思路之一,但是目前我们并不想采用.
----------------------------------------------- 怎么总觉得怪怪的?正常心跳 1s 一个,20s 是没收到心跳就断了;你这是设置了 40s 一个心跳然后 20s 没心跳就断了? 不想修改心跳是什么鬼? 还有,即使是断了,再请求一个重连不就行了?想那么麻烦干吗? |
20
chaleaochexist OP @b821025551b 谢谢,最后一句话有用.我没想到.
心跳就是 20s 间隔.我看代码默认是这个配置.超过 20S(这个是心跳间隔)+30S(这个是 timeout) 就会主动断开连接. 忘记是 channel 还是 daphne 的代码了.\ ``` class Server(): def __init__(): pass # 就在这里 ``` @neoblackcap 谢谢我用的就是 channel,另外本问题和 ws server 端没有太大关系,我的问题是如何做一个异步非阻塞的 ws 客户端.channel 还支持客户端吗?像 aiohttp 那样? |
21
tanszhe 2019-09-27 09:16:10 +08:00
这么简单的问题 ,搞不清楚 ……
|
22
MonoLogueChi 2019-09-27 09:31:29 +08:00 via Android
@Nasei signalR 吹?我也喜欢用
|
23
LeeSeoung 2019-09-27 09:36:33 +08:00
ws 不是双向的么。。没搞明白你想做啥。。为啥 ws 会自己断。。
|
24
chaleaochexist OP @LeeSeoung 和本题无关的一种可能, timeout 不就断了吗?很好理解.
|
25
shuizhengqi 2019-09-27 10:38:58 +08:00
直接 setInterval 不好使么?
|
26
shuizhengqi 2019-09-27 10:39:39 +08:00
1s 一次,就能做到跟实时差不多的效果
|
27
zpf 2019-09-27 11:34:47 +08:00
前端不应该直接请求 websocket 服务器,为什么还要先请求 view 层,view 层在做请求转发?
|
28
chaleaochexist OP @shuizhengqi 当然可以 setInterval 直接发 ajax 就可以了,和 websocket 有啥关系?
@zpf 实时推送后台的处理进度. view 在做一个业务逻辑,并将业务逻辑的进度发送给前端. 你的意思是说,这个业务逻辑不用 ajax 而是用 websocket 来实现是吗? |
29
hsfzxjy 2019-09-27 12:25:18 +08:00 via Android
django channels,了解一下
|
30
chaleaochexist OP @hsfzxjy 谢谢我用的就是 channel,另外本问题和 ws server 端没有太大关系,我的问题是如何做一个异步非阻塞的 ws 客户端.channel 还支持客户端吗?像 aiohttp 那样?
|