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 多路复用的机制吗?
1
coderxy 2023-09-11 19:01:29 +08:00 1
一般是一个连接给一个协程去处理。 问题嘛,就是严格说起来协程起多了也不够极致高性能(极致的高性能应该是有请求才需要协程去处理)。 但是实际上直接用默认的就够了。
|
2
assiadamo OP @coderxy 按我老 javaer 的做法,会是创建几个 channel ,读 conn 的 goroutine 只会产出协议对象,根据业务或其他 hash 到不同的 channel 中,固定的几个 goroutine 读取协议对象进行业务处理,这里把 goroutine 当线程用了
|
4
securityCoding 2023-09-11 19:33:47 +08:00 1
不是高并发的情况使用 go net 原生 api 就好了保持简单,如果是 rpc 或者高并发场景可以看下 gnet
|
5
1423 2023-09-11 19:37:31 +08:00
就应该这么用
|
6
cosiner 2023-09-11 19:46:10 +08:00
可以这样理解, go runtime 是一个 epoll 框架, goroutine 是 callback, 所以业务层没必要再去做异步了, 真到了 goroutine 太多调度影响性能, 那时候才需要做选择, 修改架构
|
7
voidmnwzp 2023-09-11 20:25:42 +08:00 via iPhone
goroutine 也会占内存,但开销跟线程比不值一提,有些人会为了机制的内存性能重新在 goroutine 层面封装了 epoll ,我感觉没啥必要
|
8
BBCCBB 2023-09-11 20:30:20 +08:00
性能要求高的网络框架一般都会搞个 netty 那种模型. stackless 协程应该是可以不搞 netty 网络模型. 但 go 是 stackful.
一个连接两个 goroutine 不适用于超级多的网络连接. |
9
lesismal 2023-09-11 20:51:06 +08:00
绝大多数人处理的连接数都不算大、用标准库足够了。
@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 ) |
10
happy32199 2023-09-11 22:47:32 +08:00 via iPhone
fasthttp ? 性能提高很多,但是不稳定
|
11
Nazz 2023-09-11 22:48:35 +08:00 via Android
需要控制最大并发,用 chan 简单封装下
|
12
assiadamo OP 我是想用来写游戏服务器的,有状态长连接
|
13
lesismal 2023-09-12 01:03:10 +08:00 1
@assiadamo #12
游戏的单服务在线量不会太大,举几个例子: 1. MMORPG 同屏/同地图 CPU 计算量大、通常要分区限制单个区人数,所以单个游戏服在线也不会很大 2. MOBA/FPS 类也是 CPU 计算量大但没有大地图的广播消耗,单局游戏/单个房间也是玩家数量不大、最多也就 10 个、几十个,所以战斗服务器横向扩展堆机器就够用了 3. 反倒是那些轻量游戏,比如休闲类的、弱单机轻状态的游戏,玩家之间的互动性较少,也是可以横向扩容堆机器,但是这种对 CPU 消耗不高,所以如果用 Poller 来节省协程数量的话,单个服务能承载很多玩家在线、节省服务器软硬件资源 所以除非是做上面的 3 中这一类,否则单个游服没多大在线量。普通在线量的场景,自己搞 epoll 这些框架的响应性能并不如标准库方案,因为通常需要 IO 与逻辑协程分离,跨协程的变量逃逸、变量生命周期不容易 pool 复用优化,还有其他一些细节,各种因素加起来,响应性能不如标准库方案。 所以如果只是为了游戏服务性能、并且不是上面的 3 ,建议 OP 不用研究这个问题了,自己感兴趣倒是可以继续深入 |