swoole server 超时控制以及踩过的坑

谁说胖子不能爱 提交于 2019-11-26 18:45:27

在选定swoole作为PHP微服务的底层以后,我找了很久swoole server端的超时控制,但是,swoole的官方文档里,没有写server端的超时控制(类似于php-fpm的request_terminate_timeout配置),swoole源码里的example写了

examples/process/func_timeout.php

<?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),测下来也确实如此,虽然很恶心,但是也没办法。

但是,在PHP升级到PHP 7.1 之后,就不用写这个了

http://php.net/manual/zh/migration71.new-features.php#migration71.new-features.asynchronous-signal-handling

只需要在框架入口处加上

pcntl_async_signals(true);

或者修改php.ini

pcntl.async_signals = 1

这样就完美了。

更多架构、PHP、GO相关踩坑实践技巧请关注我的公众号:PHP架构师

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!