<?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();
能否从计算机原理基础解释一下吗,我看 workman 文档说进程间的共享数据,可以用全局变量,或者管道,或者 redis 这样的存储工具,我声明了一个 global,该进程也是只有 1 个,读取$a 的时候,只会从$a 地址读取值,但是值每次都不是递增,实在想不通
1
b821025551b 211 天前
$a++ 后面打 log 进文件,看具体怎么执行的。
|
2
sun2920989 211 天前
看看浏览器是不是自动多请求了一次图标文件.
|
3
sun2920989 211 天前
或者换命令行或 postman 之类的工具再试试.
|
4
cs5117155 OP @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 ,不一定是上一次请求的进程? |
5
sundev 211 天前 1
一看就是浏览器多请求的。
还有如果多进程,workerman 是没有会话级别负载均衡的,就是从空闲的进程分配一个来处理的。 |
6
sundev 211 天前
你如果的确需要真全局变量的,你可以使用 https://github.com/walkor/GlobalData 来实现,或者用个缓存组件来做。
|
7
javalaw2010 211 天前
@cs5117155 workerman 是多进程的,你用 global 声明,其实只在当前的进程内有效,Worker::runAll()之后,进程就 fork 了,此时你的 global 变量在每个进程里都是独立的。
|
8
cs5117155 OP @javalaw2010 谢谢,这样说,我就明了很多了,有时看文档说,进程间数据不互通,都是独立,需要编程者自已实现互通,总感觉就停留在似懂非懂的状态
|
9
sun2920989 211 天前
@cs5117155 进程间的 global 不是互通的.
|
10
cs5117155 OP @sun2920989 那我还想问一个问题,我在 workman 里面使用 Mysql 获取数据,workman 开启 4 个进程,每一个 tcp 请求进来,通过数据库查询 A 用户金额,那么 4 个进程中获取 A 用户金额肯定是不变的吧,数据的变动只依赖数据库有无改动
|
11
sun2920989 211 天前
@cs5117155 如果您数据库的值没有变 那么四个进程去查询的结果当然是一样的. 另外请注意四个进程每个要使用一个独立的数据库连接.不要共享数据库连接.
|
12
cs5117155 OP @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 个相互独立的数据库连接吧,并没有发生共享数据库连接的情况?
|
13
ivanshaoaz 211 天前 1
@cs5117155 #12 我的理解:onWorkerStart 回调函数会在每个 worker 进程启动时执行,这个回调中初始化的任何变量都是这个进程独有的,初始化的 $db 变量对于每个 worker 进程是独立的,不会发生共享。
|
14
cs5117155 OP @ivanshaoaz 感谢。我也是这样认为
|
15
sun2920989 211 天前
@cs5117155 是的 您和 13 楼说的完全正确.
|