內(nèi)存溢出 out of memory,是指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請(qǐng)了一個(gè)integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。
內(nèi)存泄露 memory leak,是指程序在申請(qǐng)內(nèi)存后,無(wú)法釋放已申請(qǐng)的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴(yán)重,無(wú)論多少內(nèi)存,遲早會(huì)被占光。
memory leak會(huì)最終會(huì)導(dǎo)致out of memory!
php-fpm 內(nèi)存泄露問(wèn)題
在一臺(tái)常見的 nginx + php-fpm 的服務(wù)器上:
nginx 服務(wù)器 fork 出 n 個(gè)子進(jìn)程(worker), php-fpm 管理器 fork 出 n 個(gè)子進(jìn)程。
當(dāng)有用戶請(qǐng)求, nginx 的一個(gè) worker 接收請(qǐng)求,并將請(qǐng)求拋到 socket 中。
-
php-fpm 空閑的子進(jìn)程監(jiān)聽到 socket 中有請(qǐng)求,接收并處理請(qǐng)求。
image
一個(gè) php-fpm 的生命周期大致是這樣的:
模塊初始化(MINIT)-> 請(qǐng)求初始化(RINIT)-> 請(qǐng)求處理 -> 請(qǐng)求結(jié)束(RSHUTDOWN) -> 請(qǐng)求初始化(RINIT)-> 請(qǐng)求處理 -> 請(qǐng)求結(jié)束(RSHUTDOWN)……. 請(qǐng)求初始化(RINIT)-> 請(qǐng)求處理 -> 請(qǐng)求結(jié)束(RSHUTDOWN)-> 模塊關(guān)閉(MSHUTDOWN)。
在請(qǐng)求初始化(RINIT)-> 請(qǐng)求處理 -> 請(qǐng)求結(jié)束(RSHUTDOWN)這個(gè)“請(qǐng)求處理”過(guò)程是: php 讀取相應(yīng)的 php 文件,對(duì)其進(jìn)行詞法分析,生成 opcode , zend 虛擬機(jī)執(zhí)行 opcode 。
php 在每次請(qǐng)求結(jié)束后自動(dòng)釋放內(nèi)存,有效避免了常見場(chǎng)景下內(nèi)存泄露的問(wèn)題,然而實(shí)際環(huán)境中因某些擴(kuò)展的內(nèi)存管理沒(méi)有做好或者 php 代碼中出現(xiàn)循環(huán)引用導(dǎo)致未能正常釋放不用的資源。
在 php-fpm 配置文件中,將pm.max_requests這個(gè)參數(shù)設(shè)置小一點(diǎn)。這個(gè)參數(shù)的含義是:一個(gè) php-fpm 子進(jìn)程最多處理pm.max_requests個(gè)用戶請(qǐng)求后,就會(huì)被銷毀。當(dāng)一個(gè) php-fpm 進(jìn)程被銷毀后,它所占用的所有內(nèi)存都會(huì)被回收。
作者:飯米粒_0ec3
鏈接:http://www.itdecent.cn/p/44d8870d6986
來(lái)源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
