V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lesismal  ›  全部回复第 37 页 / 共 60 页
回复总数  1200
1 ... 33  34  35  36  37  38  39  40  41  42 ... 60  
2022-04-18 10:38:36 +08:00
回复了 gantleman 创建的主题 游戏开发 为什么 luacluster 可以实现万人同屏?
做技术的不踏踏实实,半吊子老来故弄玄虚地吹是真烦
2022-04-03 23:01:58 +08:00
回复了 josexy 创建的主题 Go 编程语言 Go 的网络轮询器疑惑?
我不敢说这就是原因,只作为猜测:
1. pipe 和 event 都可以实现功能
2. pipe 每次只需要 write 1 字节,而 eventfd 每次必须写入大于等于 8 字节、相比之下浪费
2022-04-01 00:49:06 +08:00
回复了 notokoy 创建的主题 Go 编程语言 Go 流媒体(直播音视频)服务器 LAL - 开源自荐
@notokoy

哦对了,slack 跟用英语没什么关系。我不用微信之类的是因为被一些事情恶心到了,所以跑到 slack 上躲清静。一些国人知名开源项目也在 slack 上开频道了,而且 slack 、discord 这些有现成的 github 相关的 app/功能集成,做自己开源项目还是有些便利的
2022-03-31 23:51:50 +08:00
回复了 notokoy 创建的主题 Go 编程语言 Go 流媒体(直播音视频)服务器 LAL - 开源自荐
@notokoy #19

哥们太客气了,我也能从你的项目中学到不少流媒体的知识,交流下来,大家都有收获就很开心。

> 不过。我依然觉得即使基于性能考虑,在流媒体场景也不是十分必须。

对,所以我一直说的是海量并发场景的问题。我前面和接下来说的也是基于海量并发,普通并发量,标准库绝对足够了。
按照普通硬件配置比如 4c8c ,1-5w 这种连接数,poller 的相应性能没有优势,甚至因为异步流编解码更复杂而不如标准库响应性能好,而内存的节约也是对应交互频率等存在一定的阈值,阈值范围内,标准库更优

> 第一,现在一条直播流的带宽随随便便就超过 Mb 了,以后的趋势应该是越来越大。即使是 CDN 应用,受限于带宽,连接也不会太多吧。
> 真要是单个节点那么大的量,我觉得可以考虑多进程了。

这倒是不一定,多网卡多线,还有不同码率的包 size 未必真就是单节点不会太高连接数。而且单进程的 go 的 net.Conn 如果有瓶颈,改成单硬件上的多进程仍然高成本,只能加硬件,这个倒不是能不能搞定业务的问题,主要是硬件成本、部署节点数量维护成本之类的

> 第二,流媒体场景,还有一点和很多短连接场景不同,就是连接间有很多交互,比如数据转发。

这个确实是,但不管是 net.Conn 、poller 方案,还是 c/cpp 也都有同样的成本。所以这一点上成本的区别不大,无非就是 map 上再加点 buckets 之类的来降低锁的粒度来减少竞争成本。
所以主要的区别仍然是协程数量导致的内存、gc 、调度的压力

> 我看过一些 IO 框架。
> 基本实现是支持多个 event loop ,然后连接绑定到一个固定的 event loop 中。

对于读,姿势有点多,常见的一些用法:
1. LT 模式如果跨协程 /线程去处理 event ,则可能会有事件的多次重复派发导致事件和事件对应的读 syscall 浪费(也可以做标记避免一些重复读的浪费,但事件的重复派发也是内核和应用层的浪费),所以这种基本上是在 epoll 协程 /线程里直接进行
2. ET 模式,可以像 LT 那样直接在 epoll 循环里读,也可以把事件传给专门的 IO 协程 /线程去处理读,因为 ET 是每次有新的数据只会触发一次、不像 LT 那样只要未读完就不停触发,加上协议交互、窗口拥塞机制,所以即使跨协程 /线程处理读、ET 也不会有太多事件的重复派发,但需要注意每个 conn 的读应在确定的协程 /线程中进行,否则多个并发流读的时候可能造成数据顺序的混乱
3. ET+ONESHOT ,可以避免事件重复派发,可以让协程 /线程池中的每个任务比较均衡地获取事件进行处理,不至于像 ET 那样跨并发流传递必须注意单个 conn 的有序读;但是 ONESHOT 因为每次需要重复添加事件,如果每种使用方式实现比较良好的情况下,则 ONESHOT 方式下整体上浪费更多的 epoll syscall ,所以通常性能比 LT 或 ET 的吞吐要差一些

我自己框架中可配置 LT 或者 ET 、不支持 ET+ONESHOT ,因为实测 LT 吞吐要略好所以默认配置是 LT 。另外就是 IO 通常也不会是一个服务的全部 cpu 消耗,所以即使是丢个这几个 IO 协程 /线程,交给系统去自然调度也是能够达到整体均衡的。

对于写,也基本是 conn 直接写的多一些,缓冲区满、写失败了才会把写事件加到 event 里然后等待可写再 flush 。

> 一些性能测试,是在自身 event loop 中 echo 数据,这种场景有两个特点:
> 1. 没有涉及到跨协程交互,可以无锁。
> 2. 理论上,一个 event loop 的所有连接可以共用一块读内存,因为不会长久持有。

如果是针对流媒体服务这种涉及不同连接之间的交互的,你举例子的这里的无锁有两个条件:
1. 只有一个 event loop
2. 所有 IO 、逻辑也都是在这个 event loop 中

如果不满足这两个条件,收到一个连接的数据想推送给另一个,就仍然需要锁,而满足这两个条件付出的代价可比锁大多了:
1. 只能利用单核
2 go 的指令速度还是不够快
3. 虽然是非阻塞,但涉及 IO 毕竟也是 syscall 、不是纯 cpu 消耗,所以仍然是慢

另外关于内存,其实这种场景的内存优化,普通连接数的时候,一不小心甚至比标准库更耗内存,主要区别是:
1. net.Conn 方案是读一个 message 处理一个然后下一个、同一个 buffer 可以复用
2. poller 框架节省协程数量,但是要想不被单个连接线头阻塞、IO 协程读到完整消息后需要丢给不同的协程去处理逻辑,同一个 conn 同时可能几个 message 在等待处理,而且这些 buffer 是跨协程的、生命周期更复杂,没法像标准库方案那样方便复用

结论就是各种消耗,标准方案主要与在线量相关,poller 方案主要与交互频率相关,所以前面提到阈值,不同的在线量、交互频率下,二者各有不同的优劣表现。

我最初也是写 c/cpp 的框架,写 go 的这个发现 go 比 c/cpp 的框架甚至还要复杂些,因为默认带 gc ,使用 sync.Pool 也无法精准控制,需要做更多策略。而且 go 的指令不够强,如果像很多 c/cpp 框架那样做成逻辑单线程则性能不够,所以 go 仍然需要逻辑多协程,而这又涉及到更多的锁、时序、一致性相关的细节优化,所以除了语法简单了,实现姿势其实有更多改变


PS: 最后再重复下,标准库方案绝大多数时候够用了,咱们探讨的 poller 只针对海量并发这种,所以我不是一定要劝楼主搞异步框架,够用就好:joy:
2022-03-31 18:46:47 +08:00
回复了 notokoy 创建的主题 Go 编程语言 Go 流媒体(直播音视频)服务器 LAL - 开源自荐
@notokoy #34

微信太闹腾了浪费很多时间,而且歪果仁也基本不用,你有 slack 频道没?可以 slack 弄点频道、还能进军海外扩张一下。也欢迎来我的项目的频道:
https://arpcnbio.slack.com/join/shared_invite/zt-16e6yu1mb-FUsil~2Jmn4Usl~IX_zv3g#/shared-invite/email

多数内部业务、尤其是需要很多功能定制的流媒体服务确实不需要太大在线量,毕竟外面有云、CDN 网络层层分担了在线数量的压力、同一 topic 只需要针对外层基础设施请求回源的节点数量就够用了,这个数量不会太大,而这些基础设施可能主流仍然是 c/cpp 的。
如果用 go 做云、CDN 之类的基础设施的开发、面向用户量很大,net.Conn 的开销也确实是还对应着挺高的硬件成本的,如果能换成 poller 和更多的内存优化,还是能声调不少资金、对能源环境问题也友好。

QUIC 这种也是路漫漫,不知道啥时候能普及,我的 poller 库只支持了 TLS/HTTP1.x/Websocket ,不打算支持 HTTP2.0 因为 2.0 太渣了。目前 go 的 QUIC 实现,也同样是一个连接至少一个协程,海量并发照样也是消耗很多资源。但是因为基于 UDP ,而 go 的 UDP 标准库已经足够简单了,所以我的 poller 库不打算支持 UDP 。至于 QUIC ,以后如果有档期,我也想搞一份不需要每个连接至少一个协程的实现,kcp-go 之类的类似标准库方案的一连接一协程也是同样的对海量并发不友好,海量并发时开销远超过其他语言的性能比较好的异步框架,剩下的只剩同步逻辑的便利,性能和消耗比其他语言异步框架劣势很多、甚至在基础设施领域,同步的便利已经无法弥补这个消耗的成本损失了。
每一样基础设施的工作量都有点大,真是想做很多但时间不够用了:joy:

你说的 go 的 io 线程数量应该是指 poller 线程数,这里先以这个作为前提,否则这样说可能不太准确。
之前我也没注意过 go 的 poller 线程数量是否只有 1 个,刚写代码试了下,net.Listen 0 个到 100 地址的时候,以及连接数 0 到 20w 的不同组合,确实都只有一个 eventfd ,而且即使不 listen 、没有连接也会有 eventfd ,是处理所有类型 fd 的 nonbloking 的:
但 top -Hp 查看,随着 net.Listen 地址数量或者连接数的增加,这 listener 和连接数的增加都对应着线程数的增加,应该是协程数多或者所需资源多时,runtime 动态增加了所需的线程。
考虑到 epoll 的不同用法和线程数量的情况,猜测 golang et 模式、epoll 线程里只是处理事件而不进行实际的读写,事件与 runtime 调度结合去触发用户协程的可读写唤醒,实际的读写则发生在用户的协程里,对应的是整个 runtime 的线程池 MPG 调度时被执行,而这个线程也是前面提到的随着负载增加而由 runtime 去增加的。所以前面我觉得“go 的 io 线程数量只有 1 个”这个说法可能不太准确。

引入 IO 框架倒还好,只是如果支持异步 IO ,编解码器要像 c/cpp 那样实现的是异步流解析,不像使用 net.Conn 同步解析这么简单,需要定制优化的地方也更多。统一实现成异步的编解码后,编解码器只收数据进行解析就可以、其实也就无所谓 IO 层是同步还是异步了,我的框架里目前就是这样,uni*是 epoll/kqueue 异步、windows 是使用 net.Conn 封装了下,框架传递数据给应用层。
并且,IO 这层节省了大量的协程数量,应用层则仍可以使用有限数量的协程池,而且应用层的协程池 1w-10w 这种 size 级别也足够用了,有特殊的阻塞需求还可以定制不同的 pool 来控制整个系统的协程资源,这样我们仍然可以在应用层写同步逻辑,我的库里现在就是这样做的,跑着效果还算挺好
2022-03-31 11:19:11 +08:00
回复了 notokoy 创建的主题 Go 编程语言 Go 流媒体(直播音视频)服务器 LAL - 开源自荐
并发量大的时候,基于标准库的 net.Conn 还是消耗很大。7 、8 年前记得国外有个团队单机 50w 连接推流,内存、调度成本还是很高
去年我自己的异步框架功能基本完善后,也琢磨支持下流媒体的然后不用每个连接一个协程去循环读了,可以节省太多协程数量、内存、gc ,都可以变得可控,但是我自己暂时没那么多时间精力搞这一大套、得看以后有没有适合的时机了。如果作者有兴趣可以试下搞套异步的

PS ,阿里系开源真是各种 KPI 烂尾,之前看他们有人出了个 livego ,代码感人,低级错误、连 panic 都没处理好稍微测试了下就宕机了,本想 pr 修复下,但是看已经烂尾了所以没再关注了

楼主这个,我之前就有关注过,加油!
生活就是这样子操蛋,同情楼主+1
@victor

外层有其他反代、中间件等设施做中转是可以交给其他基础设施处理。

但是 client 直连 go server 的,还是需要注意。比如用 go 做的基础设施
2022-03-11 23:37:49 +08:00
回复了 pipiking 创建的主题 电影 哪部电影,你看完久久不能释怀?
《喜剧之王》

某站上的那些凄凄厉厉声也是让人久久不能释怀的
2022-03-11 23:33:46 +08:00
回复了 dwlovelife 创建的主题 程序员 多少 QPS 算高并发,或者说高并发的标准
半尺码克十万起,线上业务一百加
2022-03-05 11:03:16 +08:00
回复了 voidmnwzp 创建的主题 程序员 (纯主观)一个 javaver 用 go 语言的初步体验
@hello2090
#22 也就写习惯了 CURD 简单逻辑的不太纠结这些。如果真都不用纠结,世间岂不早就被 c/cpp 一统江湖了
2022-03-05 11:00:52 +08:00
回复了 voidmnwzp 创建的主题 程序员 (纯主观)一个 javaver 用 go 语言的初步体验
支持,java 届的人间清醒。
ps:总有很多巨婴程序员觉得 go 没有这不行、没有那不行,其实都是常年写逻辑的你自己不行
@RedisMasterNode
第一,这与跟风完全无关,我不是因为 rsc 开贴而跟风,我自己的工程结构都是自己设计。
既然说到跟风,你有没有思考过哪种人擅长跟风?自己的设计能力不足、缺少判断力的人,才经常跟风,工程结构这种事情涉及到一定的设计审美能力,但还不至于是难度很大的事情、也不至于太过影响工程效率,因为即使工程结构不漂亮、只要团队人员都熟悉后形成项目规范、那项目就能足够有效推进了。各种语言,项目结构多了去了,对于工程效率,通常是约定大于配置
你觉得这个好,大概率是因为你在自己的 go 项目积累初期阶段没有自己花心思去认真思考和设计工程结构,刚好又看到有可以参考的就直接拿来用、并且用习惯了,用习惯之后其实就无所谓了。所谓的实践里你们很多工程按这个目录来也清晰明了没出什么问题,但你有没有想过其实如果你早期是参考了一个其他模板,习惯后也照样清晰没什么问题?因为这中工程结构,只是目录结构而已,并不是那些决定项目生死的算法、数据结构、框架基础设施实现质量最主要因素,比如高并发高性能,一些算法、数据结构、系统编程能力直接决定了项目能否满足性能要求(尤其是对单点性能要求很高、不是无状态那种随便加硬件就能解决的类型)。所以你说这个模板你们很多项目用着没什么问题——这说法没毛病,确实没什么问题,但这并不能证明它真的就是好,并不是所有人都能够像你们一样能够轻易接受别人的某种设计审美,而且至少我接触的高阶开发人员里,不喜欢这个模板的人居多

第二,先不论这个模板好不好,作者自己冠以 standard 。项目种类很多,你要是类似 spring 或者 larval 或者什么框架之类的,自带工程结构作为自己框架的 standard 那无话可说,然而你不是框架、只是个目录结构,跟中文那些文档类的 star 项目没什么本质区别。并且冠以 go 语言本身的 standard ,作者要脸吗?说句不好听的,这叫鸠占鹊巢、沽名钓誉,个人觉得这不仅不严谨,而且不道德

第三,说说这个模板到底好不好。不同的项目类型有不同的模块、组件需要,对应不同的目录结构通常是项目自家人员设计更贴合实际审美,通常大家倒是有一个共识——对于很多不同场景时没有银弹,既然没有银弹,即使是再去研究并且列举它哪里不好都是对时间的浪费。所以这个作者搞一个自以为通用适合所有项目类型的模板(只是目录结构),我觉得说他是招摇撞骗也不为过
@joesonw 这个项目的工程结构真的没什么可参考的。
@joesonw
又是一个受害者,早期被别人带跑偏了。。。

先看下 go 作者主力和一众人怎么喷这个项目早点纠正下姿势吧:joy::
https://github.com/golang-standards/project-layout/issues/117
2022-03-01 23:34:29 +08:00
回复了 qbhy 创建的主题 Go 编程语言 全新的国产 golang 框架准备发布啦,快来看看吧
虽然我仍然喜欢大道至简,但是希望有楼主这种项目能让那些对 golang 大道至简阴阳怪气的小白们闭嘴
2022-03-01 23:33:11 +08:00
回复了 qbhy 创建的主题 Go 编程语言 全新的国产 golang 框架准备发布啦,快来看看吧
@sunny1688
#4 简单 review 了下,先 issue 了个,欢迎多多交流
1 ... 33  34  35  36  37  38  39  40  41  42 ... 60  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1098 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 40ms · UTC 19:02 · PVG 03:02 · LAX 11:02 · JFK 14:02
Developed with CodeLauncher
♥ Do have faith in what you're doing.