V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cs5117155
V2EX  ›  PHP

解释一下 Workerman 中使用 global 问题

  •  
  •   cs5117155 · 23 天前 · 975 次点击
    <?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");
    
    // 启动 1 个进程对外提供服务
    $http_worker->count = 1;
    $http_worker->onWorkerStart = function ($worker) {
    // 将 db 实例存储在全局变量中(也可以存储在某类的静态成员中)
        global $a;
        $a=0;
    };
    // 接收到浏览器发送的数据时回复 hello world 给浏览器
    $http_worker->onMessage = function(TcpConnection $connection, Request $request)
    {
        global $a;
        $a++;
        // 向浏览器发送 hello world
        $connection->send("hello world---$a");
    };
    
    // 运行 worker
    Worker::runAll();
    
    

    为何浏览器每次运行不是递增,而是 1,3,5,7,9....这样的

    能否从计算机原理基础解释一下吗,我看 workman 文档说进程间的共享数据,可以用全局变量,或者管道,或者 redis 这样的存储工具,我声明了一个 global,该进程也是只有 1 个,读取$a 的时候,只会从$a 地址读取值,但是值每次都不是递增,实在想不通

    15 条回复    2024-05-23 19:03:39 +08:00
    b821025551b
        1
    b821025551b  
       23 天前
    $a++ 后面打 log 进文件,看具体怎么执行的。
    sun2920989
        2
    sun2920989  
       23 天前
    看看浏览器是不是自动多请求了一次图标文件.
    sun2920989
        3
    sun2920989  
       23 天前
    或者换命令行或 postman 之类的工具再试试.
    cs5117155
        4
    cs5117155  
    OP
       23 天前
    @sun2920989 如果开了一个进程,确实多请求图标导致。但是如果我开了 4 个进程
    hello world---4 ➜ ✗ curl http://127.0.0.1:2345
    hello world---1 ➜ ✗ curl http://127.0.0.1:2345
    hello world---1 ➜ ✗ curl http://127.0.0.1:2345
    hello world---1 ➜ ✗ curl http://127.0.0.1:2345
    hello world---1 ➜ ✗ curl http://127.0.0.1:2345
    hello world---2 ➜ ✗ curl http://127.0.0.1:2345
    hello world---2 ➜ ✗ curl http://127.0.0.1:2345
    hello world---2 ➜ ✗ curl http://127.0.0.1:2345
    hello world---3 ➜ ✗ curl http://127.0.0.1:2345
    hello world---3 ➜ ✗ curl http://127.0.0.1:2345
    hello world---2 ➜ ✗ curl http://127.0.0.1:2345
    hello world---4 ➜ ✗ curl http://127.0.0.1:2345
    hello world---5 ➜ ✗ curl http://127.0.0.1:2345
    为何它$a 请求不一样,是因为我请求的时候是无状态,每次请求会从 4 个进程中随机选取一个,然后再进行$a++,所以每次请求的$a ,不一定是上一次请求的进程?
    sundev
        5
    sundev  
       23 天前   ❤️ 1
    一看就是浏览器多请求的。
    还有如果多进程,workerman 是没有会话级别负载均衡的,就是从空闲的进程分配一个来处理的。
    sundev
        6
    sundev  
       23 天前
    你如果的确需要真全局变量的,你可以使用 https://github.com/walkor/GlobalData 来实现,或者用个缓存组件来做。
    javalaw2010
        7
    javalaw2010  
       23 天前
    @cs5117155 workerman 是多进程的,你用 global 声明,其实只在当前的进程内有效,Worker::runAll()之后,进程就 fork 了,此时你的 global 变量在每个进程里都是独立的。
    cs5117155
        8
    cs5117155  
    OP
       23 天前
    @javalaw2010 谢谢,这样说,我就明了很多了,有时看文档说,进程间数据不互通,都是独立,需要编程者自已实现互通,总感觉就停留在似懂非懂的状态
    sun2920989
        9
    sun2920989  
       23 天前
    @cs5117155 进程间的 global 不是互通的.
    cs5117155
        10
    cs5117155  
    OP
       23 天前
    @sun2920989 那我还想问一个问题,我在 workman 里面使用 Mysql 获取数据,workman 开启 4 个进程,每一个 tcp 请求进来,通过数据库查询 A 用户金额,那么 4 个进程中获取 A 用户金额肯定是不变的吧,数据的变动只依赖数据库有无改动
    sun2920989
        11
    sun2920989  
       23 天前
    @cs5117155 如果您数据库的值没有变 那么四个进程去查询的结果当然是一样的. 另外请注意四个进程每个要使用一个独立的数据库连接.不要共享数据库连接.
    cs5117155
        12
    cs5117155  
    OP
       23 天前
    @sun2920989 在 workman 文档 https://www.workerman.net/doc/workerman/components/workerman-mysql.html 。看到在 onWorkerStart 回调中初始化数据库连接,并设置 global $db ,$worker->onMessage 使用$db 的连接查询,Worker::runAll()之后,进程就开始 4 个 fork 了,有 4 个进程,那么这时 global $db 都是 4 个相互独立的数据库连接吧,并没有发生共享数据库连接的情况?
    ivanshaoaz
        13
    ivanshaoaz  
       23 天前   ❤️ 1
    @cs5117155 #12 我的理解:onWorkerStart 回调函数会在每个 worker 进程启动时执行,这个回调中初始化的任何变量都是这个进程独有的,初始化的 $db 变量对于每个 worker 进程是独立的,不会发生共享。
    cs5117155
        14
    cs5117155  
    OP
       23 天前
    @ivanshaoaz 感谢。我也是这样认为
    sun2920989
        15
    sun2920989  
       23 天前
    @cs5117155 是的 您和 13 楼说的完全正确.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1046 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:31 · PVG 03:31 · LAX 12:31 · JFK 15:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.