[已解决]UDP服务,定时器数量不断自动增加

wwng

问题描述

如题,我在UDP服务的onWorkerStart回调中启动了一个定时器,log显示onWorkerStart也只调用了一次,但是status里面发现ntp_worker的内存占用与timer数量在不断增加。
百思不得其解,只好来提问,请大神帮忙看看。
以下是debug启动,可以看见Timer added只发生了一次。

[root@crazy crazy-ntp]# php w.php start
Workerman[w.php] start in DEBUG mode
-------------------------------------------- WORKERMAN ---------------------------------------------
Workerman version:4.1.8          PHP version:8.1.16           Event-Loop:\Workerman\Events\Select
--------------------------------------------- WORKERS ----------------------------------------------
proto   user            worker              listen                    processes    status           
tcp     root            globalDataServer    frame://127.0.0.1:2207    1             [OK]            
udp     root            NTP Service         udp://127.0.0.1:123       1             [OK]            
----------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
Worker started!
Timer added!
query:, is_limit:0
Timer act, clear list.
query:0, is_limit:0
Timer act, clear list.
query:0, is_limit:0
Timer act, clear list.
^CWorkerman[w.php] stopping ...
Workerman[w.php] has been stopped

然后start -d,观察内存与timer数量:

[root@crazy crazy-ntp]# php w.php start -d
Workerman[w.php] start in DAEMON mode
-------------------------------------------- WORKERMAN ---------------------------------------------
Workerman version:4.1.8          PHP version:8.1.16           Event-Loop:\Workerman\Events\Select
--------------------------------------------- WORKERS ----------------------------------------------
proto   user            worker              listen                    processes    status           
tcp     root            globalDataServer    frame://127.0.0.1:2207    1             [OK]            
udp     root            NTP Service         udp://127.0.0.1:123       1             [OK]            
----------------------------------------------------------------------------------------------------
Input "php w.php stop" to stop. Start success.
[root@crazy crazy-ntp]# php w.php status
Workerman[w.php] status 
----------------------------------------------GLOBAL STATUS----------------------------------------------------
Workerman version:4.1.8          PHP version:8.1.16
start time:2023-02-26 11:35:07   run 0 days 0 hours   
load average: 0.65, 1.02, 1.02   event-loop:\Workerman\Events\Select
2 workers       2 processes
worker_name      exit_status      exit_count
globalDataServer 0                0
NTP Service      0                0
----------------------------------------------PROCESS STATUS---------------------------------------------------
pid memory  listening              worker_name      connections send_fail timers  total_request qps    status
92247   1.06M   frame://127.0.0.1:2207 globalDataServer 4           0         0       16            0      [idle]
92248   1.05M   udp://127.0.0.1:123    NTP Service      0           0         5       0             0      [idle]
----------------------------------------------PROCESS STATUS---------------------------------------------------
Summary 2M      -                      -                4           0         0       21            0      [Summary] 

[root@crazy crazy-ntp]# php w.php status
Workerman[w.php] status 
----------------------------------------------GLOBAL STATUS----------------------------------------------------
Workerman version:4.1.8          PHP version:8.1.16
start time:2023-02-26 11:35:07   run 0 days 0 hours   
load average: 0.59, 1, 1.01      event-loop:\Workerman\Events\Select
2 workers       2 processes
worker_name      exit_status      exit_count
globalDataServer 0                0
NTP Service      0                0
----------------------------------------------PROCESS STATUS---------------------------------------------------
pid memory  listening              worker_name      connections send_fail timers  total_request qps    status
92247   1.09M   frame://127.0.0.1:2207 globalDataServer 13          0         0       52            0      [idle]
92248   1.14M   udp://127.0.0.1:123    NTP Service      0           0         14      0             0      [idle]
----------------------------------------------PROCESS STATUS---------------------------------------------------
Summary 2M      -                      -                13          0         0       66            0      [Summary] 

可以发现内存占用与timers都在不停增加。

程序代码或配置

<?php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/NTPLite.php';

use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\UdpConnection;

$GlobalData = new GlobalData\Server('127.0.0.1', 2207);
$ntp_worker = new Worker('udp://127.0.0.1:123');
$ntp_worker->name = 'NTP Service';
$ntp_worker->onWorkerStart = function () {
    echo "Worker started!\n";
    $time_interval = 1;
    Timer::add(
        $time_interval,
        function () {
            $global = new GlobalData\Client('127.0.0.1:2207');
            echo "query:$global->query_now, is_limit:";
            echo $global->is_limited ? 1 : 0;
            echo "\nTimer act, clear list.\n";
            $global->query_now = 0;
            $global->is_limited = false;
        }
    );
    echo "Timer added!\n";
};
$ntp_worker->onMessage = function (UdpConnection $connection, $data) {
    $global = new GlobalData\Client('127.0.0.1:2207');
    $global->query_now++;
    if ($global->query_now > 2)
    {
        $global->is_limited = true;
        $connection->close(0x00);
    }
    if (!$global->is_limited and $connection->getRemoteIp()) {
        $NTP = new NTPLite();
        if (!$NTP->readMessage($data)) {
            $hex = '';
            for ($i = 0; $i < strlen($data); $i++) {
                $hex .= sprintf('%02x', ord($data[$i]));
            }
            echo "Bad request, aborted\n$hex\n";
        } else {
            //$NTP->dump();
            //echo "\n", $NTP;
            $NTP->leapIndicator = 0;
            $NTP->mode = 4;
            $NTP->stratum = 6;
            $NTP->precision = -20;
            $NTP->rootDelay = 0;
            $NTP->rootDispersion = 0.0120;
            $NTP->referenceIdentifier = ip2long('202.38.64.7');
            $now = new DateTime(NULL);
            $NTP->referenceTimestamp = NTPLite::convertDateTimeToSntp($now);
            $NTP->originateTimestamp = $NTP->transmitTimestamp;
            $NTP->receiveTimestamp = NTPLite::convertDateTimeToSntp($now);
            $NTP->transmitTimestamp = NTPLite::convertDateTimeToSntp($now);
            $message = $NTP->writeMessage();
            unset($NTP);
            $connection->close($message);
        }
    }
};

Worker::runAll();

同时想问一下GlobalData变量共享的连接怎么关闭?一段时间以后连接数超过了1000,看代码没有找到方法。

重现问题的步骤

直接启动

操作系统环境及workerman/webman等具体版本

Fedora 37, PHP 8.1.16, Workerman 4.1.8

580 1 0
1个回答

walkor

GlobalData Client不支持关闭连接,GlobalData Client应该在全局初始化,例如onWorkerStart里初始化,其它地方复用它。
GlobalData Client内部会使用定时器,每创建一个GlobalData Client实例,就可能会创建一个定时器。
所以你复用GlobalData Client就好了。

  • wwng 2023-02-26

    明白了,谢谢老大及时回复。我马上去改

  • wwng 2023-02-26

    修改以后正常了。

    [root@crazy crazy-ntp]# php w.php status
    Workerman[w.php] status 
    ----------------------------------------------GLOBAL STATUS----------------------------------------------------
    Workerman version:4.1.8          PHP version:8.1.16
    start time:2023-02-26 12:37:37   run 0 days 0 hours   
    load average: 1.5, 1.89, 2.1     event-loop:\Workerman\Events\Select
    2 workers       2 processes
    worker_name      exit_status      exit_count
    globalDataServer 0                0
    NTP Service      64000            14
    ----------------------------------------------PROCESS STATUS---------------------------------------------------
    pid memory  listening              worker_name      connections send_fail timers  total_request qps    status
    104299  0.94M   frame://127.0.0.1:2207 globalDataServer 0           0         0       0             0      [idle]
    104346  1M      udp://127.0.0.1:123    NTP Service      0           0         1       0             0      [idle]
    ----------------------------------------------PROCESS STATUS---------------------------------------------------
    Summary 1M      -                      -                0           0         0       1             0      [Summary] 
年代过于久远,无法发表回答
🔝