在选定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架构师