关于后端:Go-WebSocket-为什么我选用Go重构Python版本的WebSocket服务

1次阅读

共计 2128 个字符,预计需要花费 6 分钟才能阅读完成。

我是 HullQin,公众号 线下团聚游戏 的作者(欢送关注公众号,发送加微信,交个敌人),转发本文前需取得作者 HullQin 受权。我独立开发了《联机桌游合集》,是个网页,能够很不便的跟敌人联机玩斗地主、五子棋等游戏,不免费没广告。还开发了《Dice Crush》加入 Game Jam 2022。喜爱能够关注我 HullQin 噢~我有空了会分享做游戏的相干技术。

前言:题目其实有 2 重含意:为什么重构、为什么选 Go。

背景

如果你读过《我做了个《联机桌游合集: UNO+ 斗地主 + 五子棋》无需下载,点开即玩!叫上敌人,即刻开局!不看广告,不做工作,享受「纯正」的游戏!》这篇文章,就晓得我联机桌游的后端选型是 python,用了 ASGI 协定,用了 Daphne 实现。

然而 Python,家喻户晓,效率无限,为了让我的小破服务器接受更多并发压力,我须要让 CPU 更高效的运行,我心愿针对每一个申请,CPU 花的工夫更短,这样能够减少并发量。

利用瓶颈

其实很多 websocket 利用瓶颈在 CPU 性能和内存上。如果申请量大,CPU 解决不及时,源源不断的客户端申请会沉积在内存中,导致内存占用减少,进一步导致解决工夫变慢,CPU 高负荷运行。这样显著的特点是:CPU 打满、内存占用持续上升。用户的感触就是:点击按钮后没反馈,要等一会才有反馈,或者始终没响应。

当然,以上只是常见实践。具体利用瓶颈须要你做一下压测,寻找那个「短板」。这样当流量突增时,你晓得应该优先给哪里「扩容」。

为什么重构

自研的 WebSocket 框架,架构十分简洁,没有任何内部组件依赖(不依赖 Redis、MySQL、MQ 等数据库或队列)。使得咱们更容易去剖析。

整个链路是:用户浏览器 -> OpenResty -> Daphne(Python)。

其中 OpenResty 最大连接数我配置了 6w,近一段时间内都不会成为「短板」。如果当前用户量够高,咱们再想方法。

瓶颈最可能呈现在 Python 服务上。

目前存在如下问题:

  • 代码执行效率可优化。Python 是动静解释,效率不如编译成机器码的语言(C++、Go)高;有个外围逻辑是用 Python 序列化和反序列化 Protocol Buffer 二进制,目前是用纯 Python 实现,可优化。
  • 目前是基于协程解决各个连贯,因为 PIL 存在,Python 无奈基于多线程充分利用多核 CPU。
  • 所有数据存在内存中,随着工夫增长,内存占用会越来越高。
  • 无奈容灾 + 难以扩容。当初扩容只能对单台机器扩容,无奈将程序运行在多台机器上。而且单机宕机后,100% 用户受影响。

解决方案:

  • 针对问题一和问题二:放弃 Python,选用其它语言实现性能。选用的语言,要解决这两个问题。
  • 针对问题三和问题四:咱们当前再聊。

这一段,解答了我为什么要重构,其实外围就是:降本增效。没钱买贵的服务器,所以只能在不影响开发效率的前提下,压迫性能。

为什么选用 Go

Goroutine

大家能够理解下 C10K 的并发问题,Linux 引入 epoll 解决了这个问题。随后又有了 C10M 等问题。

如果靠传统的多线程模型,每个线程解决 1 个连贯。那么当连贯太多时,线程调度就会破费很多工夫,导致效率低。

所以有了协程(coroutine)这个概念。我之前应用 Python,就是利用协程解决的,每 1 个连贯就开启 1 个协程。整体只是 1 个线程,缩小了操作系统调度多个线程的老本。

此外,我又理解到了 Go,它提出了 goroutine,goroutine 不是协程、也不是线程。

  • 线程特点:调度齐全由操作系统调度,开发者无奈间接管制,只能通过加锁来治理多个线程的执行程序。
  • 协程特点:调度齐全由开发者掌控,然而某个协程被动放弃执行权之前,其它协程都必须挂起。
  • goroutine 特点:调度不是操作系统间接执行,但开发者也无法控制,因为 goroutine 的调度是由 go 的 runtime 调度的,一个比操作系统线程更轻量级的调度器。某个 goroutine 被动放弃执行权之前,其它 goroutine 也有机会执行(例如有多个 goroutine 时,限度每个 goroutine 最多间断执行 10ms,就得让出执行权)。此外开发者能够通过 channel 管制多个 goroutine 的执行程序。

总结一下:

  1. Goroutine 效率高于线程。跟协程类似。
  2. Goroutine 开发成本比线程低,应用 channel 可很大水平升高并发编程的心智累赘。但有时候还是须要依赖锁,这点不如协程。
  3. Goroutine 防止了协程的这个问题:繁多协程如果遇到了计算量大的工作,会阻塞其它协程。

开发效率与运行效率的衡量

Go 在保障开发效率的同时,也保障了优良的运行效率,被称为下一代 C ++。

这是网上的一张压测数据图,能够看到,综合来看,在 Python、NodeJS、Java 中,Golang 是比拟全面的选手。

写在最初

我是 HullQin,公众号 线下团聚游戏 的作者(欢送关注公众号,发送加微信,交个敌人),转发本文前需取得作者 HullQin 受权。我独立开发了《联机桌游合集》,是个网页,能够很不便的跟敌人联机玩斗地主、五子棋等游戏,不免费没广告。还开发了《Dice Crush》加入 Game Jam 2022。喜爱能够关注我 HullQin 噢~我有空了会分享做游戏的相干技术。

正文完
 0