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實例存儲在全局變量中(也可以存儲在某類的靜態(tài)成員中)
global $db;
$db = new \Workerman\MySQL\Connection('host', 'port', 'user', 'password', 'db_name');
};
$worker->onMessage = function(TcpConnection $connection, $data)
{
// 通過全局變量獲得db實例
global $db;
// 執(zhí)行SQL
$all_tables = $db->query('show tables');
$connection->send(json_encode($all_tables));
};
// 運行worker
Worker::runAll();
這個【global $db】是只在本子線程里有效吧?
也就是,當有客戶端A連上來時,假如本子線程被分配使用,本子線程執(zhí)行onWorkerStart,當收到消息時執(zhí)行onMessage,只要客戶端A沒斷開連接,本子線程就一直給客戶端A使用,直到客戶端A斷開,斷開后Workerman會清理掉這個子線程、直到下次被分配使用。本子線程里的【global $db】,只是在本子線程里的全局變量,不影響主線程、其它子線程、主線程里取它不到、其它子線程取它不到(其它子線程可以使用自己的,但直接取不到其它子線程里的),這樣嗎?
越學(xué)越覺得Workerman牛B,之前一直使用windows環(huán)境,因為客戶不懂linux,用windows環(huán)境 若有問題 ,客戶自己也能解決。但自從我使用linux,Workerman簡直就是倚天屠龍。
workerman/webman是多進程服務(wù),進程與進程之間是隔離的,不論是全局變量還是靜態(tài)變量都是相互隔離的;
在workerman/webman啟動前的全局變量也是隔離的,不會相互影響,fork后是進行了拷貝
謝謝。但官方有這么一段話,似乎與你說的【啟動前的全局變量也是隔離的,不會相互影響】有出入?官方:強烈建議在onWorkerStart回調(diào)中初始化數(shù)據(jù)庫連接,避免在Worker::runAll();運行前就初始化連接,在Worker::runAll();運行前初始化的連接屬于主進程,子進程會繼承這個連接,主進程和子進程共用相同的數(shù)據(jù)庫連接會導(dǎo)致錯誤。
(http://wtbis.cn/doc/workerman/components/workerman-mysql.html)
因為是fork的,相當于拷貝,除非數(shù)據(jù)庫連接在底層支持了拷貝之后相關(guān)的處理,否則建議在拷貝發(fā)生后創(chuàng)建連接,每個拓展的支持程度不同,比如grpc拓展就支持fork,目前看來普遍都是不支持的,所以建議在onWorkerStart里面做初始化操作
舉個例子,主進程創(chuàng)建了一個數(shù)據(jù)庫client,被分配為client-id = 1,當fork發(fā)生后,子進程獲得了拷貝的client-id = 1的客戶端信息,但實際上僅僅只是php對象中的數(shù)據(jù)信息做了拷貝,數(shù)據(jù)庫服務(wù)器缺只認主進程的client;這個操作就好比你有一張名為xx的銀行卡,復(fù)制了一張,拿給另一個用,但另一個人的信息和你是不同的,所以沒辦法使用,僅僅只是他也有張一模一樣的卡罷了。