Goroutines有高怠速唤醒电话
我正在使用Golang同时使用Goroutines同时运行两个Websocket客户端(一个用于私有数据,一个用于公共数据)。从表面上看,一切似乎都很好。两个客户都会收到从WebSocket服务器传输的数据。我相信我可能已经设置了问题,但是,自从我检查活动监视器时,我的程序始终具有500-1500个空闲唤醒UPS,并且使用了我的CPU的200%。对于两个WebSocket客户端的简单内容,这似乎并不正常。
我将代码放入片段中,以便阅读较少的内容(希望可以更易于理解),但是如果您需要整个代码,我也可以发布该代码。这是我的主要功能中运行WS客户端的代码
comms := make(chan os.Signal, 1)
signal.Notify(comms, os.Interrupt, syscall.SIGTERM)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
wg.Add(1)
go pubSocket.PubListen(ctx, &wg, &activeSubs, testing)
wg.Add(1)
go privSocket.PrivListen(ctx, &wg, &activeSubs, testing)
<- comms
cancel()
wg.Wait()
,这是客户如何运行GO例程的代码
func (socket *Socket) PubListen(ctx context.Context, wg *sync.WaitGroup, subManager *ConnStatus, testing bool) {
defer wg.Done()
for {
select {
case <- ctx.Done():
log.Println("closing public socket")
socket.Close()
return
default:
socket.OnTextMessage = func(message string, socket Socket) {
log.Println(message)
pubJsonDecoder(message, testing)
//tradesParser(message);
}
}
}
}
func (socket *Socket) PrivListen(ctx context.Context, wg *sync.WaitGroup, subManager *ConnStatus, testing bool) {
defer wg.Done()
for {
select {
case <- ctx.Done():
log.Println("closing private socket")
socket.Close()
return
default:
socket.OnTextMessage = func(message string, socket Socket) {
log.Println(message)
}
}
}
}
。我应该使用多线程而不是并发吗?在此先感谢您的任何帮助!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您在这里浪费CPU(多余的环路):
尝试这样的事情:
也可能会有所帮助:
You're wasting CPU here (superfluous loop):
Try something like this:
Also this may help:
https://github.com/gorilla/websocket/blob/master/examples/chat/client.go
TL/DR:Websocket很难:)
看起来您可能有几个旋转器。您是在a for -select语句的默认情况下为ontextMessage()分配处理程序函数。如果没有其他情况,默认情况总是执行。因为在默认情况下没有任何阻止,所以循环只是失控。这样的两种旋转旋转都可能会钉2个核心。 WebSocket是网络IO,这些Goroutines可能会并行运行。这就是为什么您看到200%使用的原因。
看看大猩猩/Websocket库。我不会说它比任何其他Websocket库更好或更糟,我对此有很多经验。
https://github.com/gorilla/websocket/websocket
以下是我多次使用过的实现。
设置的方式是收到某个消息时触发的注册处理程序功能。假设消息中的一个值是“类型”:“ start-job”,WebSocket服务器将调用您分配给“ start-Job” Websocket消息的处理程序。感觉就像为HTTP路由器编写端点。
package serverws
context.go
wshandler.go
package wsocket
types.go
wsocket.go
此实现适用于Web应用程序。这是JavaScript中客户端的简化版本。您可以处理与此实现的许多并发连接,并且您要做的就是定义包含响应ID的对象/结构,该响应ID与下面的开关中的情况匹配,它基本上是一个长开关语句,序列化并将其发送到另一侧,另一侧会ack。我有一些在几个生产环境中运行的版本。
Websocket.js
在无限循环中一遍又一遍地分配处理程序函数绝对不会工作。
https://github.com/gorilla/gorilla/websocket
tl/dr: websockets are hard :)
It looks like you might have a couple of spinners. You are assigning the handler function for OnTextMessage() in the default case of a for - select statement. The default case always executes if no other cases are ready. Because there is nothing that blocks in the default case, that for loop just spins out of control. Both goroutines spinning like this will likely peg 2 cores. Websockets are network IO and those goroutines are likely to run in parallel. This is why you are seeing 200% utilization.
Take a look at the gorilla/websocket library. I'm not going to say that it is better or worse than any other websocket library, I have a lot of experience with it.
https://github.com/gorilla/websocket
Below is an implementation that I have used many times.
The way it is set up is you register handler functions that are triggered when a certain message is received. Say one of the values in your message was "type" : "start-job", the websocket server will call the handler you assigned to the "start-job" websocket message. It feels like writing endpoints for an http router.
Package serverws
context.go
wshandler.go
package wsocket
types.go
wsocket.go
This implementation was for a web application. This is a simplified version of the client side in javascript. You can handle many concurrent connections with this implementation and all you do to communicate is define objects/structs that contain a responseID that matches a case in the switch below, it is basically one long switch statement, serialize it and send it to the other side, and the other side will ack. I have some version of this running in several production environments.
websocket.js
Assigning handler functions over and over again in an infinite loop is definitely not going to work.
https://github.com/gorilla/websocket