Closed Allenxuxu closed 4 years ago
这是一个特性需求,我把 issue 移到这里。
目前 websocket 插件支持还不够完善。 不过插件和 gev 框架是分开的,修改 websocket 相关部分就好了。 通过 connection 的 Context 保存 header ,似乎改动不大。
func (c *Connection) SetContext(ctx interface{}) {
c.ctx = ctx
}
https://github.com/Allenxuxu/gev/tree/master/plugins/websocket
这个EventLoop中的onMessage执行是同步的,如果里面有网络调用,会阻塞EventLoop,生成一个gorutine执行的话返回消息有发送不了了,websocket Send没法用
这个EventLoop中的onMessage执行是同步的,如果里面有网络调用,会阻塞EventLoop,生成一个gorutine执行的话返回消息有发送不了了,websocket Send没法用
网络调用为什么会阻塞EventLoop?
这个EventLoop中的onMessage执行是同步的,如果里面有网络调用,会阻塞EventLoop,生成一个gorutine执行的话返回消息有发送不了了,websocket Send没法用
网络调用为什么会阻塞EventLoop?
我的cpu32核心,eventloop是由32个goroutine执行的,当执行到OnMessage的时候,如果发生网络调用,那么这个goroutine就休眠了,那么就没有goroutine执行eventloop了,没法处理到来的请求了.现在我是在OnMessage里面新生成一个goroutine执行业务的,缺点就是返回数据需要用Send调用,OnMessage的返回值没用
这个EventLoop中的onMessage执行是同步的,如果里面有网络调用,会阻塞EventLoop,生成一个gorutine执行的话返回消息有发送不了了,websocket Send没法用
网络调用为什么会阻塞EventLoop?
我的cpu32核心,eventloop是由32个goroutine执行的,当执行到OnMessage的时候,如果发生网络调用,那么这个goroutine就休眠了,那么就没有goroutine执行eventloop了,没法处理到来的请求了.现在我是在OnMessage里面新生成一个goroutine执行业务的,缺点就是返回数据需要用Send调用,OnMessage的返回值没用
不应该在 OnMessage 做耗时的操作,如果比较耗时,最好只在 OnMessage 里切割数据,然后使用 Send 发送。
@lyfunny 考虑 在 gev 里增加一个协程池, OnMessage 函数放到协程池中执行。
https://github.com/Allenxuxu/gev/blob/master/example/websocket/main.go
websocke 增加了取 header 的例子 @lyfunny
func main() {
//....
wsUpgrader := &ws.Upgrader{}
wsUpgrader.OnHeader = func(c *connection.Connection,key, value []byte) error {
fmt.Println(string(key),":" ,string(value))
// 这个回调函数会在 协议升级成功被调用
// 在这里可以将需要的 header 保存起来,通过 c.SetContext 方法
return nil
}
s, err := NewWebSocketServer(handler, wsUpgrader,
gev.Network("tcp"),
gev.Address(":"+strconv.Itoa(port)),
gev.NumLoops(loops))
if err != nil {
panic(err)
}
s.Start()
}
https://github.com/Allenxuxu/gev/blob/master/example/websocket/main.go
websocke 增加了取 header 的例子 @lyfunny
func main() { //.... wsUpgrader := &ws.Upgrader{} wsUpgrader.OnHeader = func(c *connection.Connection,key, value []byte) error { fmt.Println(string(key),":" ,string(value)) // 这个回调函数会在 协议升级成功被调用 // 在这里可以将需要的 header 保存起来,通过 c.SetContext 方法 return nil } s, err := NewWebSocketServer(handler, wsUpgrader, gev.Network("tcp"), gev.Address(":"+strconv.Itoa(port)), gev.NumLoops(loops)) if err != nil { panic(err) } s.Start() }
这样设置好像没用啊,你在这里设置为true了
out, _, err = p.upgrade.Upgrade(c, buffer)
if err != nil {
log.Error("Websocket Upgrade :", err)
return
}
c.SetContext(true) // 设置为true,标志已经upgrade过了
websocket升级的时候需要把http header保存下来的,里面的数据后面conn处理请求要用到的,现在看起来没法做到,需要修改框架支持,
Originally posted by @lyfunny in https://github.com/Allenxuxu/gev/issues/4#issuecomment-613216254