GO服务端Syscall、epollwait CPU开销过高

wudi2022 · · 2930 次点击
更多评论
![image.png](https://static.golangjob.cn/221121/a2d9dc67c22104138ef82a2a681acbe6.png)
#1
程序是实现了一个数据库代理服务: 客户端 <---> 代理服务 <--> 数据库 代码逻辑大概如下: // 建立监听 s.listener, err = net.Listen(netProto, s.addr) //循环accept for s.running { conn, err := s.listener.Accept() if err != nil { ... continue } // 协程处理connection go s.onConn(conn, dbType) } // func (s *Server) onConn(c net.Conn, dbType string) { ... // 循环监听读connection消息 for { // 使用 io.ReadFull读消息;RB是 bufio.Reader; 若没消息程序会停在这里,我理解这就是epoll的挂起 并不消耗cpu header := make([]byte, 5) if _, err := io.ReadFull(cc.pkg.Rb, header); err != nil { return nil, nil, err } .... //收到消息后 会通过后端数据库链接将消息写入数据库连接中;Wb是 io.Writer // 其中后端链接通过连接池维护,轮询选取,选取时有一个锁控制选取哪个节点;此方法cpu耗时很少 err = cc.backendConn.Conn.pkg.Wb.Write(data) ... //for循环监听数据库端返回消息 for { header := make([]byte, 5) data, err = io.ReadFull(cc.backendConn.Conn.pkg.Rb, header ) // 处理消息 ..... //写消息到客户端 c.pkg.Wb.Write(data) } // 回收数据库连接到资源池 c.closeConn(c.backendConn, false) } ... }
#3