webman本身很省連接,一個進程一個連接,也看過老大對連接池解釋的帖子,但是最近遇到一個場景,感覺業(yè)務(wù)量如果再加大,沒有連接池是不行了
業(yè)務(wù)場景如下:
原本開了4倍進程,32*4,Mysql500個開連接,webman+fpm程序總共用不到200個連接,活躍連接1-3
最近新加了一個功能,我司用到一個第三方付費接口,該接口在我司客戶端產(chǎn)品調(diào)用,但是該接口只有一個固定秘鑰字符串,沒有生成簽名之類的。
為了防止該付費接口被客戶端抓包非法調(diào)用,并且要對該API加價計費,于是寫了一個接口,中轉(zhuǎn)調(diào)用第三方付費接口,調(diào)用成功之后扣除用戶在我方平臺的余額。該接口是實時代理采集淘寶、拼多多等電商平臺數(shù)據(jù),所以返回較慢,很多需要800-1200ms才能返回接口,這導(dǎo)致我原來的4倍進程不夠用,大量后續(xù)請求阻塞。
于是我把進程一直上調(diào)到CPU核*12倍=382個進程,才實現(xiàn)了不堵塞,雖然進程多了,但是實際CPU和內(nèi)存負載還是很多,估計開30倍都沒問題。但是過來一會兒出現(xiàn)了另外的問題,原來的fpm老項目也連了這個數(shù)據(jù)庫,因為Mysql連接數(shù)限制的500,這時候就出現(xiàn)了進FPM連接數(shù)不夠用的問題,fpm項目出現(xiàn)502,最后將Mysql最大連接數(shù)改1000解決
長遠思考,如果我的業(yè)務(wù)量放大到10臺服務(wù)器,業(yè)務(wù)相近,就需要10臺32核心12 = 3820個進程,Mysql就要4000+個連接數(shù)才能夠用,這種場景下沒有連接池是不行了
同問,配置的時候 應(yīng)該乘以多少合理,或者說該怎樣判斷,我現(xiàn)在是*6,我感覺還能加大,提升并發(fā)能力
http://wtbis.cn/doc/workerman/faq/processes-count.html 現(xiàn)在我的是8核16 是6,按照文檔來就算一個經(jīng)常50m,我也可以設(shè)置10,文檔說*2都可以,感覺好浪費
你這個業(yè)務(wù)和連接池沒關(guān)系,是業(yè)務(wù)設(shè)計的問題;
業(yè)務(wù)設(shè)計建議使用異步的思路,把阻塞等待的時間用于接收請求,其實這個過程就是消息隊列的過程;可以使用比如webhook、消息隊列、分布式事務(wù)等達到這個效果;
連接池需要線程,PHP沒有線程;連接池數(shù)量也有上限,一旦達到上限,一樣會阻塞;
你說的這個問題,歸根結(jié)底和TCP的隊頭阻塞原理是一樣的。
如果每個php進程都開一個連接池,感覺占用的mysql連接更多。本來一個進程一個mysql連接,php內(nèi)部開了連接池導(dǎo)致每個進程建立N個數(shù)據(jù)庫連接。假設(shè)每個進程的連接池開10個mysql連接,100個進程本來需要100個mysql連接,現(xiàn)在需要1000個mysql連接了。連接數(shù)就更多了。
除非你用那種統(tǒng)一的連接池服務(wù),類似一個獨立的mysql代理服務(wù)。webman連接代理服務(wù),代理服務(wù)連接mysql。代理服務(wù)控制自己與mysql的總連接數(shù),這樣webman和代理服務(wù)之間的連接數(shù)不限制。
我覺得最好用隊列來處理這些慢業(yè)務(wù)。如果無法用隊列,可以開一些進程專門做這些慢業(yè)務(wù)的接口。
你這個問題是在請求第三方接口太耗時了(800~1200ms),問題不是在MySQL吧。如果是golang就很好辦
好像沒什么好的辦法,只能多開進程,或者看可不可以把接口搞成異步的
你這個業(yè)務(wù)不耗cpu,時間都耗在了等待網(wǎng)絡(luò)接口請求返回上了,cpu不需要這么多,這個業(yè)務(wù)體現(xiàn)不出workerman的優(yōu)勢,還不如用php-fpm,多開點進程,用php-fmp的好處是,用了mysql馬上就釋放掉了,你在請求第三方接口的時候就不會占用mysql連接了
多線程+同步模型處理低CPU開銷+高IO延遲的場景,什么時候掛取決于worker線程的最大數(shù)量,因為所有的線程最終都會占用掉,然后資源不足gg。和語言的關(guān)系反而不大了,你換最慢的python也一樣
這個場景下,FPM反而會比Webman好,畢竟請求結(jié)束資源就釋放了...[嘆氣]
兄弟直接用golang吧,golang的協(xié)程很好的解決了這個問題。
比如,你使用golang的gin框架,因為gin把每個連接都丟給了一個協(xié)程去處理,cpu不會消耗在等待網(wǎng)絡(luò)請求上,很好的解決了你的這個問題,既不耗cpu,也不耗內(nèi)存,一個2核4G的服務(wù)器就可以滿足要求。
是要定義結(jié)構(gòu)體,json解析比較簡單,你把json數(shù)據(jù)復(fù)制到goland ide里面,然后選中,右鍵有菜單可以直接將json轉(zhuǎn)為結(jié)構(gòu)體,也有在線轉(zhuǎn)的工具,比如https://utils.fun/go-struct-json
goland里面有個插件,可以將json和sql轉(zhuǎn)化為結(jié)構(gòu)體
https://plugins.jetbrains.com/plugin/14409-convert-json-sql-to-go-struct
這個不是連接池能解決的問題,除非是單獨開一個專門的連接池服務(wù),否則每個進程都開個連接池,那么占用的連接數(shù)會更多。
這個解決方案有挺多,
方案一、最簡單的讓php-fpm去處理這些慢請求。
方案二、webman開一組自定義進程,利用 workerman/http-client 去處理
方案三、webman1.4支持新開http進程,讓慢請求到專門的進程里去處理,參考 http://wtbis.cn/q/9067
方案四、弄個中間件,每次執(zhí)行完關(guān)閉mysql連接
方案五、專門啟動一個mysql代理服務(wù),連接mysql改成連接mysql代理