英文:
Scaling webscocket connections using golang
问题
func handleConn(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
if _, ok := err.(websocket.HandshakeError); !ok {
log.Println(err)
}
return
}
go writer(ws)
reader(r, ws)
}
func main() {
http.HandleFunc("/", handleConn)
}
我正在尝试使用golang构建一个高扩展性的WebSocket服务器。由于原生的go WebSocket包支持不足,我正在使用https://github.com/gorilla/websocket。
对于每个连接,将会生成一个goroutine来处理写入操作。为了处理大量的连接,假设我有100万个并发连接,那么服务器上将会有100万个goroutine在运行。
硬件规格:
16 GB内存
4核CPU
2.5 GHz英特尔Core i5
在不影响性能的情况下,它能够处理大量的连接吗?
英文:
func handleConn(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
if _, ok := err.(websocket.HandshakeError); !ok {
log.Println(err)
}
return
}
go writer(ws)
reader(r, ws)
}
func main() {
http.HandleFunc("/", handleConn)
}
I am trying to build a high scaling websocket server using golang. Since there is lack of support in native go websocket package, i am using https://github.com/gorilla/websocket.
For every connection, a goroutine will be spawned to take care of writes to it. For scaling huge number of connections. Let's say if I have 1M concurrent connections then there should be 1M goroutines will be running on the server.
Hardware Specification:
16 GB Ram
4 Core CPU
2.5 GHz Intel Core i5
will it work for large number of connections without affecting the performance?
答案1
得分: 3
让我们进行一些数学计算:
理论上:
每个go协程消耗8KB的内存。
所以,对于一百万个套接字,需要8GB的内存。
现在,让我们将重点转向实际情况。
由于您正在使用Web套接字,您正在寻找双向通信通道。因此,您需要为从每个套接字读取数据保留一个缓冲区。
所以,仅用于监听套接字数据的另外8GB内存就会消失。
这些数字仅表示旋转和生成一百万个连接所需的资源,并不包括其他重要因素(为其他任务保留的资源,内核保留空间,操作系统保留空间等)。
结论:这种方法很简单,但在一定限度之外无法扩展。
您肯定需要更多的RAM来满足提出的要求。
您可以通过实现类似kQueue/ePoll的东西来减少内存消耗。通过这种方法,您不再需要不断等待数据被消耗,并浪费缓冲区内存,而是实现一个回调函数,该函数在套接字准备好读取/写入数据时被通知,然后您可以创建一个缓冲区并在文件描述符上进行读取/写入操作。这将帮助您重用缓冲区,从而减少资源消耗。
希望对您有所帮助!
英文:
Lets do some mathematics:
Theoretically:
Each go-routine consumes 8KB of memory.
So, for a million sockets, 8GB of ram is required.
Now, let's shift the paradigm towards practicality.
Since, you are using web socket, you are looking for two way channel communication. So, you would have to reserve a buffer for reading data from each socket.
So, another 8 GB of RAM gone just for listening the data from socket.
These figures just denotes the resource, required to spin and spawn a million connections, and doesn't include other important factors (resource reserved for other tasks, kernel reserved space, OS reserved space, etc.)
Conclusion: This approach is simple, but not scalable beyond a certain limit.
You would definitely need much more RAM, to scale at the proposed figure.
You can minimise the memory consumption by implementing something like kQueue/ePoll. Via this approach, instead of constantly waiting for data to be consumed, and wasting the buffer memory, you would implement a callback, which gets informed if the socket is ready to read/write data, and then you can create a buffer and do read/write operations over the file descriptor. This would help you reuse the buffer, and thereby reduce resource consumption.
Hope that helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论