laravel redis Error while reading line from the server.

代碼運行一段時間後,會報下面的錯誤。php

[Predis\Connection\ConnectionException]                              redis

Error while reading line from the server. [tcp://127.0.0.1:6379]服務器

 

最初的懷疑是鏈接數過多,致使鏈接不上服務器,出現上述錯誤。查看進程,發現大量redis狀態爲TIME_WAIT的tcp鏈接。tcp

 

首先考慮的是,減小TIME_WAIT的進程,保持隨時能夠鏈接到服務器。因此想到的減小TIME_WAIT狀態的進程,將進程快速回收。修改內核參數sysctl.conf,net.ipv4.tcp_timestamps=1(1爲開啓),開啓快速回收net.ipv4.tcp_tw_recycle=1。tw_recycle是經過時間戳判斷哪一個是最新的進程,將不是最新的TIME_WAIT的進程回收,因此須要先開啓tcp_timestamps。php-fpm

修改後觀察,果真沒有繼續報錯。server

 

可是使能快速回收TIME_WAIT進程,可能會丟包,致使沒有收到應答,不能成功創建鏈接。但這種辦法也不是最佳解決辦法,尤爲修改內核參數,涉及環節太多,需深刻了解纔可修改。進程

 

底層不去修改,就從predis客戶端入手,源碼發現有read_write_timeout這個參數,能夠設置超時時間,這樣讀取流數據時就不會報錯。Predis做者建議設置關閉redis.conf中timeout(修改timeout 0),表示不關閉與客戶端的鏈接,我感受這樣比較耗費資源,能夠適當增長timeout時間。ip

 

因此此次暫時是這樣解決的,設置read_write_timeout=-1和redis.conf的timeout參數。資源

其實有不少解決方式,後續能夠繼續尋找一個更優的方案。源碼

 

比較了常見的兩個php鏈接redis客戶端,phpredis和predis。Laravel中使用的predis,其中鏈接redis使用connect,當請求結束鏈接關閉。而phpredis使用pconnect鏈接,依賴於php-fpm,php-fpm不關閉,鏈接一直都在。再次使用pconnect,鏈接會被重用,不會再次新建。

 

後來查看predis源碼發現,persistent這個參數,手冊說明都沒有提到,可是看字面意思,可能相似於pconnect方式的持久鏈接,這個後續再研究一下。