NBIO 第三弹 —— 真正的 Websocket 百万连接,以及 HTTPS 支持

lesismal · · 3446 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

## NBIO 第三弹 —— 真正的 Websocket 百万连接,以及 HTTPS 支持 上周又撸了个 Upgrader 支持 Websocket ,功能已经打通,Upgrader 握手的部分是直接从 [gorilla/websocket](https://github.com/gorilla/websocket) CV 大法然后修改的,感谢 [gorilla/websocket](https://github.com/gorilla/websocket) ,二进制协议部分是从头写的。 经过一番纠结,没有支持 Websocket 的 permessage-deflate 压缩,因为不是所有浏览器/client都支持该功能,所以如果 server 开启了压缩,反倒可能导致车祸。 如果需要压缩,应用层框架自己封装下发送 payload 的方法就能轻易实现,并且更能自主选择压缩算法。 ### 为什么叫真正的 Websocket 百万连接? 曾经有个老外的帖子讲到单机百万websocket连接的优化: [Going Infinite, handling 1M websockets connections in Go](https://speakerdeck.com/eranyanay/going-infinite-handling-1m-websockets-connections-in-go) 对应的仓库好像是这个:[1m-go-websockets](https://github.com/eranyanay/1m-go-websockets) 早前就有看过这个帖子,但是没有细读该仓库的代码,刚好前阵子有人向我推荐它,我就去试了下这个仓库优化到最后一步的代码 [4_optimize_gobwas](https://github.com/eranyanay/1m-go-websockets/tree/master/4_optimize_gobwas) 我做了个"粘包"测试,这个帖子的优化代码应该是有问题的:这个帖子和仓库的优化方式,只是把连接的 FD events 添加到了 epoll,但是并没有设置 FD 为 Non-Blocking mod,然后等到 epoll 监听可读时再读,虽然避免了每个连接一个协程,但是由于单个 FD 的阻塞,如果这个 FD 上有某个或者某些 Websocket 完整消息的数据不是一次性全部到达,这个 FD 的 websocket 读整个消息将被阻塞,从而导致这个 epoll 上的其他 FD 也要等它读到完整包。 这个"粘包"测试的详细代码在这里,有兴趣的小伙伴可以去试下: [server](https://github.com/lesismal/arpc/issues/2#issuecomment-747258191) [client](https://github.com/lesismal/arpc/issues/2#issuecomment-747258984) NBIO-HTTP-Websocket 是真正的异步非阻塞,所以能像其他语言的异步库那样实现单机高并发,可以避免每个连接创建一个协程,代码示例请参考: [nbio-websocket-examples](https://github.com/lesismal/nbio/tree/master#websocket-examples) [nbio-websocket-1m-connections-examples](https://github.com/lesismal/nbio/tree/master#websocket-1m-connections-examples) ### HTTPS 支持 由于更早些时候魔改了下标准库的 TLS 已经跟 NBIO 打通,所以也就封装了下支持 HTTPS Server ,用法: ```golang cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatalf("tls.X509KeyPair failed: %v", err) } tlsConfig := &tls.Config{ Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true, } tlsConfig.BuildNameToCertificate() mux := &http.ServeMux{} mux.HandleFunc("/echo", onEcho) svr := nbhttp.NewServerTLS(nbhttp.Config{ Network: "tcp", Addrs: []string{"localhost:8080"}, }, mux, nil, nil, tlsConfig) err = svr.Start() if err != nil { fmt.Printf("nbio.Start failed: %v\n", err) return } defer svr.Stop() ``` 完整代码请参考: [https-server](https://github.com/lesismal/nbio/blob/master/examples/http/server_tls/server.go) #### 欢迎有兴趣的小伙伴关注、进行更多测试,以及 issue、pr、star,^_^

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3446 次点击  ∙  2 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传