Go 的并发模型的一些问题

2021-02-12 21:58:57 +08:00
 bushenx
最近在优化业务上的一块功能,现阶段这个功能会对用户的每个请求新建一个协程处理,但是个人感觉这样无节制的使用协程有些不妥。想在这上面优化一下,比如限制用户新建协程的数量。有这个想法但是具体实现应该如何做?有什么书籍或者文章介绍类似这样协程并发模型的,可以推荐学习一下吗?
1659 次点击
所在节点    问与答
19 条回复
pythonnoob
2021-02-12 22:17:50 +08:00
直接用消息队列削谷平峰,或者用令牌桶限制数量
bushenx
2021-02-12 22:23:35 +08:00
@pythonnoob 令牌桶有使用,但是想在协程创建的地方也控制一下协程的并发数量,可以给支个招或者有什么别的渠道学习一下吗?
matrix67
2021-02-12 22:24:38 +08:00
用户的每个请求当一个任务,丢到队列里面去,然后 go 开 worker 去解决任务。
bushenx
2021-02-12 22:26:29 +08:00
@matrix67 当时是想到这个方法,但是如果用户接入量很多,队列是不是需要一个全局锁去保护,这样感觉有失性能。
bushenx
2021-02-12 22:28:19 +08:00
我想能不能有什么并发模型能限制每个用户起协程的数量,但是又不会因为同步而损失太多性能。
rrfeng
2021-02-13 00:01:54 +08:00
千万级 goroutine 没什么问题。
延时敏感的也不会用 go 吧。
namaketa
2021-02-13 00:55:23 +08:00
一切性能问题都要问问自己为什么不能提配置 /加机器解决呢。
协程调度开销已经很低了,特别对于重 io 任务。
建议跑跑 benchmark 自己看调度耗时占比,再去判断要不要优化。
golang 管道性能确实比较一般,可以多开几个管道。
如果你真的有千万级别 /低时延 /重计算的任务,放过 go 吧。
faker1
2021-02-13 01:56:59 +08:00
1 楼的感觉可以, 实在想做感觉 可以参考 go 自己的任务调度, 锁的粒度放细, (全局,局部)类似分 group , 感觉这个是过度搞的,好像
ginjedoad
2021-02-13 08:15:41 +08:00
使用协程池就好了。
ginjedoad
2021-02-13 08:19:27 +08:00
比如这位同学写的稍微复杂了点。但是对于协程的限制数量级限制的同时,整体性能不升反降。https://github.com/panjf2000/ants

“单机上百万上千万的同步批量任务处理现实意义不大,但是在异步批量任务处理方面有很大的应用价值,所以我个人觉得,Goroutine Pool 真正的价值还是在:

限制并发的 goroutine 数量;
复用 goroutine,减轻 runtime 调度压力,提升程序性能;
规避过多的 goroutine 侵占系统资源( CPU&内存)。”
sujin190
2021-02-13 09:57:25 +08:00
在线程外设计协程本来就是为了干这个的啊,每个请求一个协程,你们倒好,居然还怕协程创建太多,真是服了
sujin190
2021-02-13 10:04:02 +08:00
之前做锁服务的时候测试过,每个请求一个协程,十万级 rps 并没有啥问题,想要更高确实需要协程复用,但这个过程必须是无锁的,无锁协程池并不是每个场景都能有的,web 这种真没啥必要
bushenx
2021-02-13 11:07:10 +08:00
或许是我的表述不够明确,业务背景是服务会处理所有用户的请求,假设某个用户在某时间段请求数量剧增,这就导致会创建很多协程,而很多的协程会影响其他用户创建的协程。我是想减轻单个用户对所有用户的影响,所以限制协程数量。
scnace
2021-02-14 20:54:20 +08:00
你自己做个 benchmark 就知道了啊, 反正楼上的人说了你也不敢直接就这么干吧。。实在不行就上 goroutine pool 呗。。
zxCoder
2021-02-15 00:48:12 +08:00
歪个楼问一句,要看懂楼上大佬们所讨论的东西,大概要几年的工作 /golang 经验
pythonnoob
2021-02-19 11:39:27 +08:00
@bushenx 加机器。除非到了加机器也解决不了的情况否则别做这种优化。
pythonnoob
2021-02-19 11:42:35 +08:00
协程的调度器是无数大牛做出来的,一般人做所谓的优化很多时候会适得其反。请求激增的情况应该首先考虑加机器、前端或反代限流这些极其轻松的手段。
pythonnoob
2021-02-19 11:44:12 +08:00
除非是 bat 、12306 这种体量,否则通过优化架构已经可以解决 99%的问题了
bushenx
2021-02-19 14:05:40 +08:00
@pythonnoob 我的问题楼上的老哥已经给出答案了,就是实现一个协程池。因为我的逻辑是根据用户的请求创建协程,这很可能会导致协程被无休止创建。但是协程池就可以很好解决这个问题。在同步任务下协程池确实是没有必要的,go 运行时会有逻辑复用 g,但是这异步任务下协程池就可以很好的控制协程数量。我这个需求应该不算是性能优化,是极端情况下的一种保护措施。

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

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

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

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

© 2021 V2EX