实际业务场景,发现连接池这个东西还是需要的

aphper

webman本身很省连接,一个进程一个连接,也看过老大对连接池解释的帖子,但是最近遇到一个场景,感觉业务量如果再加大,没有连接池是不行了

业务场景如下:
原本开了4倍进程,32*4,Mysql500个开连接,webman+fpm程序总共用不到200个连接,活跃连接1-3

最近新加了一个功能,我司用到一个第三方付费接口,该接口在我司客户端产品调用,但是该接口只有一个固定秘钥字符串,没有生成签名之类的。

为了防止该付费接口被客户端抓包非法调用,并且要对该API加价计费,于是写了一个接口,中转调用第三方付费接口,调用成功之后扣除用户在我方平台的余额。该接口是实时代理采集淘宝、拼多多等电商平台数据,所以返回较慢,很多需要800-1200ms才能返回接口,这导致我原来的4倍进程不够用,大量后续请求阻塞。

于是我把进程一直上调到CPU核*12倍=382个进程,才实现了不堵塞,虽然进程多了,但是实际CPU和内存负载还是很多,估计开30倍都没问题。但是过来一会儿出现了另外的问题,原来的fpm老项目也连了这个数据库,因为Mysql连接数限制的500,这时候就出现了进FPM连接数不够用的问题,fpm项目出现502,最后将Mysql最大连接数改1000解决

长远思考,如果我的业务量放大到10台服务器,业务相近,就需要10台32核心12 = 3820个进程,Mysql就要4000+个连接数才能够用,这种场景下没有连接池是不行了

2913 9 5
9个回答

gddd

同问,配置的时候 应该乘以多少合理,或者说该怎样判断,我现在是*6,我感觉还能加大,提升并发能力

chaz6chez

你这个业务和连接池没关系,是业务设计的问题;
业务设计建议使用异步的思路,把阻塞等待的时间用于接收请求,其实这个过程就是消息队列的过程;可以使用比如webhook、消息队列、分布式事务等达到这个效果;
连接池需要线程,PHP没有线程;连接池数量也有上限,一旦达到上限,一样会阻塞;
你说的这个问题,归根结底和TCP的队头阻塞原理是一样的。

  • 暂无评论
xiuwang

如果每个php进程都开一个连接池,感觉占用的mysql连接更多。本来一个进程一个mysql连接,php内部开了连接池导致每个进程建立N个数据库连接。假设每个进程的连接池开10个mysql连接,100个进程本来需要100个mysql连接,现在需要1000个mysql连接了。连接数就更多了。

除非你用那种统一的连接池服务,类似一个独立的mysql代理服务。webman连接代理服务,代理服务连接mysql。代理服务控制自己与mysql的总连接数,这样webman和代理服务之间的连接数不限制。

我觉得最好用队列来处理这些慢业务。如果无法用队列,可以开一些进程专门做这些慢业务的接口。

  • 暂无评论
evilk

即使上了连接池,但池子里的链接总数也是有上限的,如果达到了MySQL最大连接数,外层的应用一样GG

  • 暂无评论
ontheway

你这个问题是在请求第三方接口太耗时了(800~1200ms),问题不是在MySQL吧。如果是golang就很好办

  • aphper 2022-08-18

    能指点下php下的解决思路吗

  • aphper 2022-08-18

    Nginx的进程数设置为auto的时候会阻塞吗,如果把这一个接口反向代理用其他东西写

  • ontheway 2022-08-19

    好像没什么好的办法,只能多开进程,或者看可不可以把接口搞成异步的

    你这个业务不耗cpu,时间都耗在了等待网络接口请求返回上了,cpu不需要这么多,这个业务体现不出workerman的优势,还不如用php-fpm,多开点进程,用php-fmp的好处是,用了mysql马上就释放掉了,你在请求第三方接口的时候就不会占用mysql连接了

nitron

多线程+同步模型处理低CPU开销+高IO延迟的场景,什么时候挂取决于worker线程的最大数量,因为所有的线程最终都会占用掉,然后资源不足gg。和语言的关系反而不大了,你换最慢的python也一样

这个场景下,FPM反而会比Webman好,毕竟请求结束资源就释放了...[叹气]

  • liziyu 2022-08-20

    @nitron 大佬!搭个顺风车,把webman进程设置为1的情况下,可不可以理解为 FPM模式?

  • nitron 2022-08-20

    大概相当于fpm.conf里的pm=static,max_children=1...但不会释放mysql连接

luohonen

你的问题就跟连接池没关系,我建议你去谷歌一下什么是连接池

  • 暂无评论
ontheway

兄弟直接用golang吧,golang的协程很好的解决了这个问题。

比如,你使用golang的gin框架,因为gin把每个连接都丢给了一个协程去处理,cpu不会消耗在等待网络请求上,很好的解决了你的这个问题,既不耗cpu,也不耗内存,一个2核4G的服务器就可以满足要求。

  • ontheway 2022-08-25

    推荐使用gofiber或者gin框架

  • happy321 2022-08-25

    go里面json解析 操作数据库 是不是都要先定义 字段和类型的结构体?这样工作量会不会比较多?

  • ontheway 2022-08-26

    是要定义结构体,json解析比较简单,你把json数据复制到goland ide里面,然后选中,右键有菜单可以直接将json转为结构体,也有在线转的工具,比如https://utils.fun/go-struct-json

    goland里面有个插件,可以将json和sql转化为结构体
    https://plugins.jetbrains.com/plugin/14409-convert-json-sql-to-go-struct

  • mon 2022-08-26

    我有个疑惑,golang的协程就不占用mysql的连接数么?
    如果占用,那问题不还是一样存在么?

  • evilk 2023-04-01

    @mon 当然要占用连接数,把MySQL连接上打满了,一样的GG

walkor

这个不是连接池能解决的问题,除非是单独开一个专门的连接池服务,否则每个进程都开个连接池,那么占用的连接数会更多。

这个解决方案有挺多,
方案一、最简单的让php-fpm去处理这些慢请求。
方案二、webman开一组自定义进程,利用 workerman/http-client 去处理
方案三、webman1.4支持新开http进程,让慢请求到专门的进程里去处理,参考 https://www.workerman.net/q/9067
方案四、弄个中间件,每次执行完关闭mysql连接
方案五、专门启动一个mysql代理服务,连接mysql改成连接mysql代理

  • fenger 2023-03-31

    workman/webman 如果除了固定进程数,新增进程数管理方式类似fpm【动态进程数】比如这样可设置: max_children(最大进程数)、start_servers(起始进程数)、min_spare_servers(最小空闲进程数)、max_servers(最大空闲进程数),会不会能解决题主的问题呢?这样会不会对性能影响大?

  • walkor 2023-03-31

    解决不了,进程数达到max_children仍然会占用很多连接

年代过于久远,无法发表回答
🔝