在選定swoole做爲PHP微服務的底層之後,我找了好久swoole server端的超時控制,可是,swoole的官方文檔裏,沒有寫server端的超時控制(相似於php-fpm的request_terminate_timeout配置),swoole源碼裏的example寫了php
examples/process/func_timeout.phpswoole
<?php declare(ticks = 1); Swoole\Async::set([ 'enable_signalfd' => false, ]); class FunctionTimeoutException extends RuntimeException { } function test() { sleep(1); } $serv = new Swoole\Http\Server("127.0.0.1", 9502); $serv->set(['worker_num' => 1]); $serv->on('WorkerStart', function($serv, $workerId) { pcntl_signal(SIGALRM, function () { Swoole\Process::alarm(-1); throw new FunctionTimeoutException; }); }); $serv->on('Request', function($request, $response) { try { Swoole\Process::alarm(100 * 1000); test(); Swoole\Process::alarm(-1); $response->end("<h1>Finish</h1>"); } catch(FunctionTimeoutException $e) { $response->end("<h1>Timeout</h1>"); } }); $serv->start();
可是這個用法有個地方要注意,它依賴系統信號SIGALRM,而PHP處理系統信號,依賴架構
declare(ticks = 1)
並且是每個文件的頭部都要加上這句代碼,require和include都不行(後面加上once也不行)。框架
我剛開始寫基礎框架的時候,沒有注意到這一點,而後上線查看日誌的時候,發現,明明timeout設置的爲1000ms,爲毛日誌裏沒有超過1000ms的超時日誌,而後才意識每一個文件都要加上declare(ticks = 1),測下來也確實如此,雖然很噁心,可是也沒辦法。async
可是,在PHP升級到PHP 7.1 以後,就不用寫這個了微服務
只須要在框架入口處加上ui
pcntl_async_signals(true);
或者修改php.ini.net
pcntl.async_signals = 1
這樣就完美了。日誌
更多架構、PHP、GO相關踩坑實踐技巧請關注個人公衆號:PHP架構師