PHP 部分改造为 go 与全部改造为 go 是否会提升性能?

2023-06-30 15:57:07 +08:00
 dandankele
由于 php-fpm 是以进程为单位提供服务的,大量 php-fpm 进程运行并接收客户端请求,当 php-fpm 极其依赖缓存、数据库等外部服务时,php-fpm 与外部服务之间的网络连接交互也会多,导致网络 IO 频繁,进而导致 php-fpm 进程间的频繁切换问题。这种情况经常在监控上显示为进程的墙钟时间比较大,cpu 消耗时间比较小。

所以在考虑如果用 go 改造的话,使用 go 去连接缓存、数据库等外部服务,php-fpm 充当纯前端 SSR 从 go 那里获取数据渲染页面。那么,在服务器资源配置不变的情况下,请求量与之前不变的情况下,应用性能是否会有所提高?这里主要指 RT 响应时间是否会缩短?

但是我觉得假设改造前是 100 个 fpm 进程,改造后还是 100 个 fpm 进程,并且还要增加一个 go 进程,100 个 fpm 依然要与 go 连接,依然会在 100 个 fpm 进程之间切换进程,所以在资源配置不变的情况下,RT 响应时间应该也不会变化太大吧?
难道需要 go 把 php-fpm 全部替代了?
9575 次点击
所在节点    Go 编程语言
103 条回复
star7th
2023-06-30 16:24:12 +08:00
我的建议是,先把系统拆分,按功能拆也行,按业务拆也行。拆开后,看哪个有性能问题,就哪个用 go 重写。
如果没办法拆,那就整个重写,或者保持现状。
dandankele
2023-06-30 16:24:12 +08:00
@leonshaw 瓶颈分析了啊。。就是依赖外部服务导致网络 IO 大,fpm 进程切换频繁消耗 cpu 资源。。用 go 的话至少是协程、线程级别的上下文切换。。。但是相同服务器配置下,两个放一起能否提升性能就是本文要问的问题
hewiefsociety
2023-06-30 16:24:15 +08:00
建议别改
8355
2023-06-30 16:26:31 +08:00
webman 和 swoole 改 go 提升是很有限的
改 go 的主要目的是提高单机并发数
至于原来的业务假如有调大量的外部接口和流式执行依赖查库性能并不会有多少提升。
提升比较大的是需要从数据库查询大量数据之后做处理这个部分的耗时
laravel 的性能确实比较垃圾 毫无疑义 但已经不是现代 php 了
用 laravel 的底线是要上 octane
dandankele
2023-06-30 16:28:51 +08:00
@8355 意思是改用 go 的话对于响应时间优化并不会有太大帮助?依赖外部服务查询数据的瓶颈主要还是在于网络传输性能与外部服务的性能吗?
herozzm
2023-06-30 16:29:29 +08:00
我是反着走,之前有 go 写的,业务一繁杂,go 写来相当难受,一个普通的用户权限控制,go 啥都没有,而 php 就几行代码搞定了
leonshaw
2023-06-30 16:32:03 +08:00
@dandankele 不知道这个结论是想出来的还是测出来的?进程大概有多少,IO 并发有多少?
8355
2023-06-30 16:37:55 +08:00
@dandankele #25
https://www.techempower.com/benchmarks/#section=data-r21&hw=ph&test=db&l=zijnjz-6bj
权威测评 不是我乱说

无理由臆想质疑拿数据说话吧。
defunct9
2023-06-30 16:40:03 +08:00
会。比如 www.huabbao.com ,之前是 ThinkPHP+K8S ,后来瓶颈部分统统用 go 拆出来了。很不错
dandankele
2023-06-30 16:40:54 +08:00
@leonshaw 目前只是根据少部分监控数据猜测出来的。。php 的调用栈的监控数据显示,每个慢的请求中,都是慢在了从外部服务获取数据的过程(如 fread 、Memcached::get 、Redis::get 之类的),而且消耗的时间上,wall time 挺大的,但是 cpu time 很小。并且服务器网络监控上,服务器带宽、收发数据包 pps 都没有打满。。所以目前是猜测在等待网络 IO 传输数据的过程中进程切换导致的时间消耗。。。进程目前大概是 cpu 核数的 8 倍,但再增加导致 RT 时间变长,减少的话也会变长。。
QlanQ
2023-06-30 17:09:44 +08:00
@dandankele 基于你上面的分析,如果真的是你说的这个问题,是在请求外部服务的时候,延迟高,那你只能整个重构才能解决吧,具体的就是直接使用 外部服务的时候,由目前的单次连接,改成连接池?

我以前遇到过的是,redis 所在服务带宽满了,阿里的 redis ,出口带宽很低,缓存的单个 key 数据量不能大

感觉还要是基于 目前的 qps 和瓶颈解决问题
php 性能确实不如 go
但是绝大部分项目,都触碰不到 php 的性能瓶颈的
在团队主要技术栈是 php 的情况下,没有必要硬上 go 吧
如果真的要上,可以按功能,甚至按接口来拆分,这样影响最小,效果明显,代价也小

当然其实我还是建议上 swoole 的,切 hyperf
pota
2023-06-30 17:15:50 +08:00
go 我用来解决 php 异步的问题切换了部分业务过去,单纯业务还是 php 舒服
seth19960929
2023-06-30 17:17:31 +08:00
之前重构过一个服务, 日 3000w 请求. 常见的缓存接口, 还有一些个人中心收藏接口. 从 16 个 pod 降到了 5 个.
你可以参考一下.
8355
2023-06-30 17:32:09 +08:00
@dandankele #25
举个例子说明下
情况 1
假设你提供一个接口 A
接口的功能是通过 Http 调用外部接口接口 B 接口响应时间是 100ms
那你的接口响应时间 100ms+ 无论是 go 还是 php 对吧。。。

情况 2
假设你提供一个接口 A
接口的功能是通过 Http 调用外部接口接口 B 接口响应时间是 100ms
同时还要再依赖接口 B 的返回值去调接口 C 接口响应时间是 100ms
那你的接口响应时间 200ms+ 无论是 go 还是 php 对吧。。。

情况 3
假设你提供一个接口 A
接口的功能是通过 Http 调用外部接口接口 B 接口响应时间是 100ms
另外去调接口 C 不需要依赖 B 的返回值 接口响应时间是 100ms
使用 go 和 swoole A 接口响应时间是 100ms+ 因为是协程并发调用 等待时间以最长的为准。
这种情况下用 go/swoole 可以改善响应时间 但 swoole 和 go 的差距并没有那么大

同样逻辑适用于写库 调接口各种 io 等待的同理
串行依赖意义不大,可以并行才能降低响应时间

你需要考虑有哪些业务是适合用 go/swoole 去写 而不是说上来就重构。。。
几个接口的任务量和一个系统重构的业务量是两码事。。。
FrankAdler
2023-06-30 17:34:26 +08:00
go 的学习成本没那么高,用业务切入边写边学,几天就能上手了,哪怕用的不精通,写出来的东西性能也吊打 php-fpm ,所以收益非常高投入低。
切多少就看你想投入多少精力动老代码了。
daley
2023-06-30 17:37:41 +08:00
什么框架啊,如果是 laravel ,把版本升到 8 ,用 go 或者 swoole 开个 octane 加速,从此告别 fpm ,除了手写的单例代码基本不用改
everyx
2023-06-30 17:39:39 +08:00
看描述是 php-fpm 由于没有连接池不能复用 IO 导致的 IO 拥堵,切换到 Go 可以用连接池来解决这个问题,那为什么不把这部分用 swoole 这类支持连接池的来重构呢?还能复用之前的 PHP 代码。

或者另一个角度,能否优化缓存来降低 IO 呢?前端页面缓存,API 缓存,数据库缓存这些
hongfs
2023-06-30 17:42:42 +08:00
@everyx mysql redis 这些配置成长连接,算是连接池了吧。
japeth
2023-06-30 17:48:03 +08:00
@dandankele qps cpu 我当时没看 因为也不是我重构的 季会的时候 做的那个人汇报的
japeth
2023-06-30 17:48:37 +08:00
@flyqie php-fpm 用的 larval 框架

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

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

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

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

© 2021 V2EX