在 go net 库实现了 I/O 多路复用的情况下,还需要自己实现一套吗?

239 天前
 assiadamo
ln, err := net.Listen("tcp", ":8080")
if err != nil {
	// handle error
}
for {
	conn, err := ln.Accept()
	if err != nil {
		// handle error
	}
	go handleConnection(conn)
}

这是 net package 中提供的例子 其中的 conn 虽然操作是“阻塞”式的,但底层的 fd 都是 non-blocking 的,由 go runtime 调用 epoll 等机制监听并唤醒 goroutine 进行操作,如果将不耗时的业务也放在该 goroutine 中,耗时的业务辅以其他的异步处理,这样做会有什么问题?在实际的工程中,会怎样操作?需要在业务层实现一套 I/O 多路复用的机制吗?

1813 次点击
所在节点    Go 编程语言
15 条回复
coderxy
239 天前
一般是一个连接给一个协程去处理。 问题嘛,就是严格说起来协程起多了也不够极致高性能(极致的高性能应该是有请求才需要协程去处理)。 但是实际上直接用默认的就够了。
assiadamo
239 天前
@coderxy 按我老 javaer 的做法,会是创建几个 channel ,读 conn 的 goroutine 只会产出协议对象,根据业务或其他 hash 到不同的 channel 中,固定的几个 goroutine 读取协议对象进行业务处理,这里把 goroutine 当线程用了
coderxy
239 天前
@assiadamo 没必要,因为 goroutine 很轻量级,没必要再折腾一圈
securityCoding
239 天前
不是高并发的情况使用 go net 原生 api 就好了保持简单,如果是 rpc 或者高并发场景可以看下 gnet
1423
239 天前
就应该这么用
cosiner
239 天前
可以这样理解, go runtime 是一个 epoll 框架, goroutine 是 callback, 所以业务层没必要再去做异步了, 真到了 goroutine 太多调度影响性能, 那时候才需要做选择, 修改架构
voidmnwzp
239 天前
goroutine 也会占内存,但开销跟线程比不值一提,有些人会为了机制的内存性能重新在 goroutine 层面封装了 epoll ,我感觉没啥必要
BBCCBB
239 天前
性能要求高的网络框架一般都会搞个 netty 那种模型. stackless 协程应该是可以不搞 netty 网络模型. 但 go 是 stackful.

一个连接两个 goroutine 不适用于超级多的网络连接.
lesismal
239 天前
绝大多数人处理的连接数都不算大、用标准库足够了。

@coderxy #3
@voidmnwzp #7
少量人需要处理海量连接、节约硬件、提高服务稳定性,nbio 简单压测 4c2g 跑 10w qps
https://www.v2ex.com/t/945827
标准库方案,差不多得 10g 左右内存了,cpu 核心数也得多些否则 gc 压力大、stw 不友好、稳定性低

另外 nbio 本身支持 http 、websocket 的连接采用标准库 Conn 、阻塞模式,只是用 nbio 的解析器,性能好、占用平衡

@securityCoding #4 gnet 自己支持的东西太少了,扩展起来也比较难,欢迎 pk (性能、功能、易用性都可以 pk )
happy32199
239 天前
fasthttp ? 性能提高很多,但是不稳定
Nazz
239 天前
需要控制最大并发,用 chan 简单封装下
assiadamo
239 天前
我是想用来写游戏服务器的,有状态长连接
lesismal
239 天前
@assiadamo #12

游戏的单服务在线量不会太大,举几个例子:
1. MMORPG 同屏/同地图 CPU 计算量大、通常要分区限制单个区人数,所以单个游戏服在线也不会很大
2. MOBA/FPS 类也是 CPU 计算量大但没有大地图的广播消耗,单局游戏/单个房间也是玩家数量不大、最多也就 10 个、几十个,所以战斗服务器横向扩展堆机器就够用了
3. 反倒是那些轻量游戏,比如休闲类的、弱单机轻状态的游戏,玩家之间的互动性较少,也是可以横向扩容堆机器,但是这种对 CPU 消耗不高,所以如果用 Poller 来节省协程数量的话,单个服务能承载很多玩家在线、节省服务器软硬件资源


所以除非是做上面的 3 中这一类,否则单个游服没多大在线量。普通在线量的场景,自己搞 epoll 这些框架的响应性能并不如标准库方案,因为通常需要 IO 与逻辑协程分离,跨协程的变量逃逸、变量生命周期不容易 pool 复用优化,还有其他一些细节,各种因素加起来,响应性能不如标准库方案。
所以如果只是为了游戏服务性能、并且不是上面的 3 ,建议 OP 不用研究这个问题了,自己感兴趣倒是可以继续深入
mengdodo
239 天前
@lesismal 一篇文章我看到了 5 个所以,哈哈
lesismal
238 天前
@mengdodo #14 网页回复随便打打字,见笑了,我下次注意!😋😋

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/972811

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX