深入php redis pconnect

來源:互聯網
上載者:User

pconnect, phpredis中用於client串連server的api。

The connection will not be closed on close or end of request until the php process ends.
這是api說明中的一句原文

那麼問題來了:
1. php process ends是指一次php執行完結,還是fpm的終結。如果是後者,那意味著即使一次php執行完畢,redis串連也不會被釋放,下一次執行時redis串連會被重用。
2. The connection will not be closed on close是 說如果使用了pconnect, 即使在代碼中顯示的調用close(), 也不會關閉串連。

帶著這兩個問題,我們做下實驗,深入看一下pconnect究竟做了些什麼。 準備工作

環境:
nginx + fpm
php5.3
我們將fpm配置為

pm.max_children = 1pm.start_servers = 1pm.max_spare_servers = 1

這樣,我們的頁面請求會由一個確定的fpm進程執行,方便strace跟蹤。

對應頁面請求的php代碼:

$ip = "10.136.30.144"; $port = 7777; $redis = new Redis();$redis->pconnect($ip, $port, 1);$key = "test";$value = "this is test";$redis->set($key, $value);$d = $redis->get($key);var_dump($d);

代碼的功能很簡單,串連redis,先設定一個值,再取出。 測試問題1

思路:
使用strace觀察fpm的系統調用,如果串連的生命週期是一次php執行,那麼每次頁面調用,都會有connect系統調用,用以串連redis;如果串連的生命週期是fpm的終結,那麼只有第一次頁面調用會有connect系統調用 ,之後由於串連被重用,無需connect,直接發命令請求即可。

啟動一個新的fpm(進程號28082)。
執行

strace -p 28082 -s 1024 -o redis_1

記錄一次頁面請求的系統調用。如下圖所示:

可以看到進程先建立了socket串連(檔案描述符為9)。然後給reids發一系列命令,最終取到“this is test”的結果串。且沒有關閉串連相關的redis命令或系統調用。

頁面請求結束後,我們執行

lsof -n -p 28082


可以看到,fpm進程仍然保有一個到10.136.30.144的reids串連,其檔案描述符為9(這與strace的結果一致)。

執行

strace -p 28082 -s 1024 -o redis_2

記錄 第二次頁面請求的系統調用,得到下面結果。

與第一次請求的區別是:省去了建立串連的過程,直接發送reids命令,得到結果。
再使用lsof -n -p 28082查看fpm開啟的檔案描述符,結果與上檔案相同。
說明,串連的確是被重用的,沒有建立。

執行第6次頁面請求(因為我們在準備工作中的配置,此時fpm已經是一個新的進程了),用lsof查看進程開啟的檔案描述符。

我們發現,雖然仍然有描述符為9的reids串連,但兩個tcp串連的臨時連接埠不同了,也就是串連改變了。

至此,我們得出問題1的結論:
當使用pconnect時,串連會被重用,串連的生命週期是fpm進程的生命週期,而非一次php的執行。測試問題2

為了對比,我們先看一下,使用connect串連redis,並調用redis->close()的系統調用。(將上述代碼中的pconnect改為connect, 同時在最後加入redis->close())

我們看到,除了建立串連外,在程式結尾,還向reids發送了quit命令,並關閉了串連的檔案描述符。

接下來,我們看在使用pconnect後,redis->close()有何表現
代碼調整為:

$ip = "10.136.30.144";$port = 7777;$redis = new Redis();$redis->pconnect($ip, $port, 1);$key = "test";$value = "this is test";$redis->set($key, $value);$d = $redis->get($key);var_dump($d);$redis->close();try{    $redis->get($key);} catch (Exception $e){    echo $e->getMessage();}

我們直接看第2次執行頁面請求的系統調用
並沒有建立串連,同樣是直接發送命令得到結果。說明串連被重用。同時,沒有向reids server發送quit命令,也無關閉串連的系統調用。
但注意,頁面請求的返回結果:

至此,我們得出問題2的結論:
如果代碼中使用pconnect, close的作用僅是使當前php不能再進行redis請求,但無法真正關閉redis長串連,串連在後續請求中仍然會被重用,直至fpm進程生命週期結束。 結論

1. 當使用pconnect時,串連會被重用,串連的生命週期是fpm進程的生命週期,而非一次php的執行。
2.如果代碼中使用pconnect, close的作用僅是使當前php不能再進行redis請求,但無法真正關閉redis長串連,串連在後續請求中仍然會被重用,直至fpm進程生命週期結束。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.