workerman如何主动关闭服务?然后继续执行Worker::runAll();后面的代码,比不上swoole的地方

dignfei

workerman只管开启,不管关闭,管杀不管埋,结果因为业务需求只能无奈转向swoole。而swoole都可以自由控制:
作为http服务端可以:Swoole\Server->shutdown() 关闭服务,停止监听
作为客户端可以: Swoole\Coroutine\Client->close()关闭客户端
多进程,可以 Swoole\Process\Pool->shutdown(): 关闭进程

use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('websocket://0.0.0.0:8484');
$worker->onWorkerStart = function(Worker $worker)
{
};
$worker->onMessage = function(TcpConnection $connection, $data)
{
    // 当收到特定的消息后如何退出workerman?停止监听端口,执行后面的代码  
};
// 运行worker
Worker::runAll();
// 如何退出workerman ,并且继续执行下面的代码  ?
echo 3333;

而swoole是可以实现的:

        $http = new \Swoole\Http\Server("0.0.0.0", 9902);
        $http->on('request', function ($request, $response)use($http) {
            var_dump($request);
            if(true)$http->shutdown();  // 接收指定请求后关闭http服务
        });
        $http->start();  // swoole可以实现的继续执行后面的内容
        echo 'http服务关闭,继续执行后面的代码……'.PHP_EOL;
1387 6 1
6个回答

Tinywan

建议好好先看看官方文档

  • dignfei 2022-02-28

    都看过了很多遍了,官方文档没怎么关闭啊,只写了后面的不执行

北月

完全可以参考workerman退出逻辑,自己写一下就好了

<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

// 创建一个Worker监听2345端口,使用http协议通讯
$http_worker = new Worker("http://0.0.0.0:2345");

// 启动4个进程对外提供服务
$http_worker->count = 4;

// 接收到浏览器发送的数据时回复hello world给浏览器
$http_worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $uri = $request->uri();
    if ($uri === '/stop') {
        $connection->send('stop');
        $master_pid      = \is_file(Worker::$pidFile) ? (int)\file_get_contents(Worker::$pidFile) : 0;
        $sig = \SIGQUIT;
        // Send stop signal to master process.
        $master_pid && \posix_kill($master_pid, $sig);
        Worker::log("Workerman[$master_pid] stop fail");
        // Timeout.
        $timeout    = 5;
        $start_time = \time();
        // Check master process is still alive?
        while (1) {
                $master_is_alive = $master_pid && \posix_kill((int) $master_pid, 0);
                if ($master_is_alive) {
                        // Timeout?
                        if (\time() - $start_time >= $timeout) {
                            Worker::log("Workerman stop fail");
                            exit;
                        }
                        // Waiting amoment.
                        \usleep(10000);
                        continue;
                }
                // Stop success.
                Worker::log("Workerman stop success");
                exit(0);
        }
    } else {
        $connection->send('hello world');
    }
};

// 运行worker
Worker::runAll();
  • 暂无评论
xiuwang

workerman 停止监听是 $worker->unlisten();
关闭客户端是 $connection->close();
退出进程是Worker::stopAll();

swoole也无法执行到3333

$server->start(); 
echo 3333;

感觉你的需求就是你发的这个 https://www.workerman.net/q/7957 ,关闭连接,然后重新建立一个新连接。这种需求和关闭服务和关闭进程以及执行worker->run()后面的代码没有关系。代码也很简单。

$worker->onWorkerStart = function(){
    // 每隔10秒用新token去连一次
    $token = md5(time());
    Timer::add(10, 'connect_with_token', [$token]);
};

function connect_with_token($token)
{
    static $connection;
    if ($connection) $connection->close();
    $connection = new AsyncTcpConnection('ws://127.0.0.1:8000/ws/?token='.$token);
    $connection->onMessage = function($connection, $data){
        var_dump($data);
    };
    $connection->connect();
}
  • dignfei 2022-03-01

    是两个不一样的需求。需求1.onWorkerStart内部关闭连接,然后重新建立新连接,可以用你的代码。

  • dignfei 2022-03-01

    需求2:执行Worker::stopAll();后的echo 3333; swoole是可以实现的,看我后面回复贴出来的代码

  • dignfei 2022-03-01

    Worker::stopAll();只能退出当前子进程,然后又会被workerman自动创建一个新的子进程,永远无法关闭

  • nitron 2022-03-01

    onWorkerStop回调

  • dignfei 2022-03-01

    onWorkerStop不是关闭workerman用的

dignfei

你的代码我测试了,stop fail无法停止啊。代码直接复制的,端口2345改为9902
截图
然后需要停止后执行Worker::runAll();之后的代码,怎么实现?

  • 暂无评论
dignfei
        $http = new \Swoole\Http\Server("0.0.0.0", 9902);
        $http->on('request', function ($request, $response)use($http) {
            var_dump($request);
            if(true)$http->shutdown();  // 接收指定请求后关闭http服务
        });
        $http->start();  // swoole可以实现的继续执行后面的内容
        echo 'http服务关闭,继续执行后面的代码……'.PHP_EOL;
  • nitron 2022-03-01

    首先Workerman是一个纯PHP实现的框架,在运行runAll()之后就阻塞在这里,所有的逻辑都在runAll内执行,stop实际上走的是exit/die的方式,你也知道代码里exit/die的结果就是后续代码不会再执行,所以runAll后续的代码不会执行

    Swoole是个PHP扩展,start之后,Swoole会接管这部分,stop的时候也是由swoole去控制,走的未必是exit/die逻辑,所以后面的echo会执行,如果你在代码里使用了exit/die,swoole也不会执行start之后的echo

    你这么比较一个纯PHP代码实现的框架和一个PHP扩展有点不妥吧

    我上面说的onWorkerStop是子进程关闭后的回调处理逻辑,每个子进程都会执行一遍,如果你需要的是在主进程关闭后继续处理逻辑,参考上面fuzqing的思路自行实现

liziyu

webman:欢迎再回来!

  • 暂无评论
年代过于久远,无法发表回答
🔝