onWorkerStart里的global全局变量,是只在本子线程里有效吗?

klyz505

onWorkerStart里的global全局变量,是只在本子线程里有效吗?

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

$worker = new Worker('websocket://0.0.0.0:8484');
$worker->onWorkerStart = function($worker)
{
    // 将db实例存储在全局变量中(也可以存储在某类的静态成员中)
    global $db;
    $db = new \Workerman\MySQL\Connection('host', 'port', 'user', 'password', 'db_name');
};
$worker->onMessage = function(TcpConnection $connection, $data)
{
    // 通过全局变量获得db实例
    global $db;
    // 执行SQL
    $all_tables = $db->query('show tables');
    $connection->send(json_encode($all_tables));
};
// 运行worker
Worker::runAll();

这个【global $db】是只在本子线程里有效吧?
也就是,当有客户端A连上来时,假如本子线程被分配使用,本子线程执行onWorkerStart,当收到消息时执行onMessage,只要客户端A没断开连接,本子线程就一直给客户端A使用,直到客户端A断开,断开后Workerman会清理掉这个子线程、直到下次被分配使用。本子线程里的【global $db】,只是在本子线程里的全局变量,不影响主线程、其它子线程、主线程里取它不到、其它子线程取它不到(其它子线程可以使用自己的,但直接取不到其它子线程里的),这样吗?
越学越觉得Workerman牛B,之前一直使用windows环境,因为客户不懂linux,用windows环境 若有问题 ,客户自己也能解决。但自从我使用linux,Workerman简直就是倚天屠龙。

839 1 0
1个回答

chaz6chez

workerman/webman是多进程服务,进程与进程之间是隔离的,不论是全局变量还是静态变量都是相互隔离的;
在workerman/webman启动前的全局变量也是隔离的,不会相互影响,fork后是进行了拷贝

  • klyz505 2022-11-21

    谢谢。但官方有这么一段话,似乎与你说的【启动前的全局变量也是隔离的,不会相互影响】有出入?官方:强烈建议在onWorkerStart回调中初始化数据库连接,避免在Worker::runAll();运行前就初始化连接,在Worker::runAll();运行前初始化的连接属于主进程,子进程会继承这个连接,主进程和子进程共用相同的数据库连接会导致错误。
    https://www.workerman.net/doc/workerman/components/workerman-mysql.html

  • chaz6chez 2022-11-21

    因为是fork的,相当于拷贝,除非数据库连接在底层支持了拷贝之后相关的处理,否则建议在拷贝发生后创建连接,每个拓展的支持程度不同,比如grpc拓展就支持fork,目前看来普遍都是不支持的,所以建议在onWorkerStart里面做初始化操作

  • chaz6chez 2022-11-21

    举个例子,主进程创建了一个数据库client,被分配为client-id = 1,当fork发生后,子进程获得了拷贝的client-id = 1的客户端信息,但实际上仅仅只是php对象中的数据信息做了拷贝,数据库服务器缺只认主进程的client;这个操作就好比你有一张名为xx的银行卡,复制了一张,拿给另一个用,但另一个人的信息和你是不同的,所以没办法使用,仅仅只是他也有张一模一样的卡罢了。

  • klyz505 2022-11-21

    谢谢辛苦回答。

  • chaz6chez 2022-11-21

    不用谢,小意思

年代过于久远,无法发表回答
🔝