// Get column mapping for UI
foreach(static::getUiColumns() as $column_name => $prop){
!isset($worker->{$prop}) && $worker->{$prop} = 'NNNN';
$prop_length = \strlen($worker->{$prop});
$key = '_max' . \ucfirst(\strtolower($column_name)) . 'NameLength';
static::$$key = \max(static::$$key, $prop_length);
}
// Listen.
if (!$worker->reusePort) {
$worker->listen();
}
關(guān)閉端口復(fù)用疑問:
1、“服務(wù)端套接字”為什么不直接通過forkWorkersForLinux() 在子進(jìn)程創(chuàng)建;要在主進(jìn)程創(chuàng)建“服務(wù)端套接字”,通過子進(jìn)程復(fù)制父進(jìn)程mainSocket 呢?
請問是因?yàn)?,關(guān)閉端口復(fù)用情況下;主進(jìn)程單獨(dú)監(jiān)聽端口,不會報出“端口被占用錯誤”?
// Remove other listener.
foreach(static::$_workers as $key => $one_worker) {
if ($one_worker->workerId !== $worker->workerId) {
$one_worker->unlisten();
unset(static::$_workers[$key]);
}
}
2、創(chuàng)建新的子進(jìn)程監(jiān)聽服務(wù)端口,取消其它“服務(wù)端套接字”;這個是什么意思?創(chuàng)建出來的子進(jìn)程,不應(yīng)該只復(fù)制master的“服務(wù)端套接字”,為什么還要unlisten()?
\stream_context_set_option($this->_context, 'socket', 'so_reuseport', 1);
3、reusePort = true , 我即使注釋掉上面這個代碼,多個子進(jìn)程未提醒“端口占用問題”。是因?yàn)槲冶镜豔SL linux 版本高的原因?
$socket = \socket_import_stream($this->_mainSocket);
\socket_set_option($socket, \SOL_SOCKET, \SO_KEEPALIVE, 1);
4、SO_KEEPALIVE 連接復(fù)用,這個配置參數(shù)指的是長連接,實(shí)際體現(xiàn)是什么樣子?
1、如果沒開reusePort,進(jìn)程A監(jiān)聽某端口后,進(jìn)程B就無法再監(jiān)聽這個端口,否則會報錯address already in use
。
所以需要主進(jìn)程監(jiān)聽某個端口,通過fork來實(shí)現(xiàn)多個進(jìn)程監(jiān)聽同一端口
2、主進(jìn)程為了業(yè)務(wù)需要可能執(zhí)行了多個端口監(jiān)聽,主進(jìn)程fork出子進(jìn)程后,子進(jìn)程繼承了主進(jìn)程的監(jiān)聽,其實(shí)子進(jìn)程不需要所有的監(jiān)聽,所以會關(guān)閉不需要的監(jiān)聽,只保留一個屬于自己的監(jiān)聽
3、WSL沒試過,不清楚。一般情況linux系統(tǒng)在沒開reusePort的情況下不允許重復(fù)監(jiān)聽端口
4、SO_KEEPALIVE 是一個TCP選項(xiàng),當(dāng)連接空閑一段時間后TCP底層會發(fā)送keepalive報文。SO_KEEPALIVE開啟后可以用來檢測死連接,避免死連接占用服務(wù)器資源。如果把發(fā)送keepalive報文間隔縮短,也可以用來tcp?;睿乐惯B接長時間不通訊被路由節(jié)點(diǎn)或者防火墻等斷開。
4、SO_KEEPALIVE 是一個TCP選項(xiàng),這個選項(xiàng)我注釋掉。
643 138.624632 127.0.0.1 127.0.0.1 TCP 45 [TCP Keep-Alive] 56182 → 19000 [ACK] Seq=7220 Ack=12535 Win=10135 Len=1
516 111.607103 127.0.0.1 127.0.0.1 TCP 44 19000 → 57377 [ACK] Seq=1 Ack=3 Win=10233 Len=0
56182:瀏覽器客戶端端口
19000: Workerman http端口
我注釋掉“SO_KEEPALIVE”選項(xiàng),Wireshark 捕獲日志,發(fā)現(xiàn) “TCP Keep-Alive” 來自客戶端發(fā)出,Workerman 作出回應(yīng)。這是系統(tǒng)配置默認(rèn)會出現(xiàn),還是因?yàn)榭蛻舳酥鲃影l(fā)起呢??
“SO_KEEPALIVE”選項(xiàng)生效后,連接處于空閑狀態(tài),“TCP Keep-Alive” 數(shù)據(jù)包是由客戶端還是服務(wù)器發(fā)送出來呢???
if (! isset($this->_fd[$fd_key])) { ..... } else { $fd_val = $this->_fd[$fd_key]; $res = true; if ($flag === self::EV_READ) { if (($fd_val & SWOOLE_EVENT_READ) !== SWOOLE_EVENT_READ) { $res = Event::set($fd, $func, null, SWOOLE_EVENT_READ | >SWOOLE_EVENT_WRITE); $this->_fd[$fd_key] |= SWOOLE_EVENT_READ; } } else { if (($fd_val & SWOOLE_EVENT_WRITE) !== SWOOLE_EVENT_WRITE) { $res = Event::set($fd, null, $func, SWOOLE_EVENT_READ | >SWOOLE_EVENT_WRITE); $this->_fd[$fd_key] |= SWOOLE_EVENT_WRITE; } } }
5、Events 命名空間下Swoole 循環(huán)事件,\Workerman\Events\EventInterface::add()
請問為什么不直接通過 Swoole\Event::isset(mixed $fd, int $events = SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE): bool ,這種方式判斷FD是否已經(jīng)注冊讀寫事件,然后作出事件“讀/寫” 修改操作??