Golang Go语言中 websocket 为什么是按顺序执行的?

Golang Go语言中 websocket 为什么是按顺序执行的?

我用的是 echo 里面的 gorilla websocket 示例

https://echo.labstack.com/cookbook/websocket

我原本的后台是 node 写的,node 上没事,但是为什么 go 这边是按顺序执行的而不是同时执行?

https://i.loli.net/2020/07/10/qcGlzNh25ADPULb.png


更多关于Golang Go语言中 websocket 为什么是按顺序执行的?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

31 回复

没做过,但是我觉得开个协程不就得了

更多关于Golang Go语言中 websocket 为什么是按顺序执行的?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


执行什么?

你的请求是同时嘛?

#2 执行了个 http 请求,我页面是 6 个任务同时发送的,但是后台是一个接一个执行,而不是同时执行 6 个任务

#3 对,页面请求是同时发出 6 个请求的,看时间戳就知道了

如果没有开协程和多线程,那么本身就是按顺序执行的。

#6 对,我是想过应该是这个问题。刚接触 go 还不太了解,没搜到有关 websocket 的教程或者例子,找到的那些都是聊天室的例子,但我这个只是 1v1 的

因为你函数写的是同步代码,你需要开协程去处理,并通过 chan 来收发结果。

起码把代码发一下,不然 v 友都不知道你做了什么暗箱操作

LZ 的 Node 环境是不是开了多线程了。
Node 本身是异步单线程的,加上多线程那就是乱序了……

#8 代码我 append 了,貌似没有在线运行 go 的代码托管网站

#9 单线,异步的。转 go 之后不知道 go 这边要怎么写

第一张图每次 send 间隔好几毫秒啊 同时请求??

#12

也不能说死磕”同时“这个字眼,你发到后台去,按我理解的话它肯定是接收到一个就去执行一个,但是 go 这边像是被缓存住了,是一个执行完成后再去执行,而不是“接收到一个就去执行一个”。应该就是像#6 说的那样

一个长连接本来就是顺序接收消息的啊,不知道 node 是怎么处理的,可能收到一条消息都生成 async task 类似 goroutine 吧

  1. 看一下你给的链接里的 demo,https://github.com/labstack/echox/blob/master/cookbook/websocket/gorilla/server.go 。Subscribe 里 readLoop 不应该新开 go 程,直接卡在这里,直到 ws 断开。因为 Subscribe 是 HTTP Server 调的,你返回了,它就会认为这个连接已经结束了,虽然不一定会马上关(keep-alive),但必要的时候会断开。

    2. 作为一个 HTTP Server,Subscribe 应该是在不同的 go 程里被调用的,不然就就成了单协程了,你可以打印出来试一下

#14 我是用 nest.js ,async 、await


1.是否你的每个 for 在不同的 go 程,打印出来看看
2. 加延迟,晚点发

nestjs 里面改成同步响应就和 go 一样了,或者 go 里面读到 body 的时候新建一个 goroutine 处理这样也就和 nestjs 里的异步响应效果一样。你用 nodejs 之所以习惯了异步处理是因为程序是单线程的,同步可能会长时间阻塞其他的请求,但在 go 里面,每个连接本身就在一个 goroutine 里,放心用同步的方式处理消息就是了,还能避免乱序问题

#19 乱序是什么?

按顺序处理每一条消息


我觉得你不要开协程去做 readloop,直接执行 readloop 。如果 CreateFromUrl 方法中涉及 io 处理或者可以并发执行的话,可以开协程执行并通过 chan 取回结果。参考: http://litang.me/post/golang-channel/#%E5%A4%9A%E5%86%99%E4%B8%80%E8%AF%BB

#18

https://i.loli.net/2020/07/10/CxVOXqPmNdyvZ5D.png

打印出了 goroutine 和随机 Sleep 值

#21 是这理没错,可是我想要按顺序多个一起执行

看到最后才看懂楼主的顺序执行是什么意思…同一个连接里收到的 event, 那可不就是顺序执行, 想要并发就在 for 循环里只要 ReadMessage 读到数据, 就启个 goroutine 去处理, 你 go c.readLoop(ctx)用错地方了.

不要教坏人家了. 弄一个 channel 缓存, 然后按照想要的并发量起 goroutine.

#25
#26

的确是 read 到数据就开个 goroutine 就行了

NestJS 不是应该用 Rxjs 多?

都有用,但是有些复杂的地方用 rxjs 也会嵌套太深

最近玩了一下 Nestjs,如果没有 Rxjs 支持, 我根本就没兴趣。

Nestjs 很多概念很源自 Angular,写 Angular 习惯了,async,await 和 promise 那一套实在用起来难受。Nestjs 内部几乎和 Angular 一致,都是 Rxjs 优先,但可惜,第三方集成很多还是基于 Promise 。

https://github.com/hantsy/nestjs-sample 我这个的 Sample 除了 LocalStrategy 用了 Promise (用 Observable,需要额外转换),其它地方都是 Rxjs 。

在Golang(Go语言)中,WebSocket按顺序执行的现象主要源于Go的并发模型和WebSocket库的设计方式。

首先,Go语言通过goroutine实现并发,但这些goroutine在访问共享资源(如WebSocket连接)时,需要通过同步机制(如互斥锁)来避免数据竞争。在典型的WebSocket服务器实现中,每个连接通常由一个单独的goroutine处理,这些goroutine会按顺序处理来自客户端的消息,因为它们访问的是同一个连接对象,而连接对象的操作通常是线程不安全的,需要按顺序进行。

其次,WebSocket库(如gorilla/websocket)在设计时也考虑了线程安全的问题。库内部可能会使用锁或其他同步机制来确保连接的状态和操作是线程安全的。这种设计虽然增加了复杂性,但保证了并发环境下连接的稳定性和可靠性。

此外,WebSocket协议本身是一个全双工通信协议,它要求服务器和客户端之间保持一个持久的连接。在这个连接上,消息是按顺序发送和接收的,这也有助于保证数据的完整性和顺序性。

综上所述,Golang中WebSocket按顺序执行的现象是由Go的并发模型、WebSocket库的设计以及WebSocket协议的特性共同决定的。这种设计保证了在并发环境下,WebSocket连接能够稳定、可靠地工作。如果你需要在WebSocket处理中引入更多的并发性,可以考虑在业务逻辑层面进行拆分和优化,而不是直接挑战连接层面的顺序性。

回到顶部