91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Swoole?webSocket客服IM消息系統怎么實現

發布時間:2023-03-14 15:17:14 來源:億速云 閱讀:117 作者:iii 欄目:開發技術

這篇文章主要講解了“Swoole webSocket客服IM消息系統怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Swoole webSocket客服IM消息系統怎么實現”吧!

實現方案

技術的實現方案點主要PMQ,2組客戶端(用戶端、客服管理端),3個主要的部分組成(Push推送消息+Pull拉取未讀消息+MessageQueue消息隊列),具體流程和交互方式見上面的架構流程圖。

Swoole?webSocket客服IM消息系統怎么實現

1.建立鏈接,借鑒Tcp3次握手的原理,將每一次的用戶詢問新增一個關系,詢問結束時再將關系釋放,因為每次隨機分配的客服是不一致的,客服管理員控制臺,進入控制臺會觸發檢測客服映射關系的程序,以保證關系的唯一性。

2.客服分配:客服分配是根據用戶是否為第一次進入鏈接進行判定依據,首次會隨機分發配給在線客服中的其中一個,如果之前分配過的客服也在線,優化分配存在客服,這樣處理的原因是客服不易變,用戶異變,防止反復鏈接/斷開操作,減少網絡開銷。

3.并發鎖:相同用戶在同一時間有3s的鎖定狀態,用來防止關系錯亂,在客戶端發來請求時優先獲取緩存,近少可能的訪問數據庫,提高服務的穩定性和性能。

//設置分布式鎖,3s之內只能請求一次
$lock = RedisPool::invoke(function (Redis $redis) use ($toUid) {
    return $redis->get(Category::$openLock . $toUid);
}, self::REDIS_CONN_NAME);
if ($lock) {
    $msgErrorRet['code'] = 416;
    $msgErrorRet['msg'] = 'Please try again';
    return $this->response()->setMessage(json_encode($msgErrorRet));
}
//查詢是否存在鏈接關系
$imUserRelation = RedisPool::invoke(function (Redis $redis) use ($toUid) {
    $redis->setEx(Category::$openLockPrefix . $toUid, 3, $toUid);
    return $redis->get(Category::$imUserRelationName . $toUid);
}, self::REDIS_CONN_NAME);

4.網絡異常處理,回收服務:針對App崩潰、網絡異常斷開的鏈接,主動監聽斷開的fd,進行關系處理,對所有斷開鏈接的websocket,進行回收,清除關系。

static function onClose(\swoole_server $server, int $fd, int $reactorId)
{
    $info = $server->getClientInfo($fd);
    $fd = intval($fd);
    if ($info && $info['websocket_status'] === WEBSOCKET_STATUS_FRAME) {
        TaskManager::getInstance()->async(function () use ($fd) {
            RedisPool::invoke(function (Redis $redis) use ($fd) {
                //回收用戶
                $uid = $redis->hGet('PUSH_MSG_SOCKET_FD', $fd);
                if (isset($uid) && !empty($uid) && is_numeric($uid)) {
                    $redis->zRem('PUSH_MSG_USER_LOGIN', $fd);
                    //檢測是否有客服關系未斷開
                    $redis->del(Category::$imUserRelationName . $uid);
                    $redis->hDel('PUSH_MSG_SOCKET_FD', $fd);
                }
                //回收客服管理用戶
                $cUid = $redis->hGet('PUSH_CUSTOMER_MSG_SOCKET_FD', $fd);
                if (isset($cUid) && !empty($cUid)) {
                    $redis->zRem('PUSH_CUSTOMER_MSG_USER_LOGIN', $fd);
                    $redis->hDel('PUSH_CUSTOMER_MSG_SOCKET_FD', $fd);
                }
            }, 'redis');
        });
    }
}

5.獲取離線消息分配算法,按照客服管理員在線人數,把離線消息按照用戶來重新組裝,平均分配給在線管理員,如果數量不能被整除,也不會造成分配不均情況。

//驗證客服管理員在線
$vUid = [];
$server = ServerManager::getInstance()->getSwooleServer();
foreach ($virtualUid as $fd => $vid){
    $info = $server->getClientInfo($fd);
    if ($info && $info['websocket_status'] == 3) {
        $vUid[$fd] = $vid;
    }
}
if (!empty($pullData) && !empty($vUid)) {
    $uIds = array_keys($pullData);
    $row = ceil(count($uIds) / count($vUid));
    $share = array_chunk($uIds, $row, true);
    $keyDict = $vUid;
    $pushList = [];
    // code 組裝代碼略... 
}

6.websocket對象不回收:從控制臺打開新窗口時,就會新增一個websocket對象,后來在瀏覽器中刷新處理的,沒有找到回收的辦法。

7.心跳:客服的websocket心跳使用的是實時push消息,5s循環一次,防止鏈接斷開,服務下線。

實踐Swoole里的坑

鏈接數變化正常,但是內存好像沒有得到很好的釋放,而且進程里也出現了很多野進程,野進程多可能存在的原因是這樣的,你沒有守護啟動,然后主進程掛了,后面的進程找不到父進程,變成了僵尸進程或者是孤兒進程。

Swoole?webSocket客服IM消息系統怎么實現

內存也不對勁,大概率是我執行腳本里出了問題,去掉了修改配置的語句,在Base類里加入了unset,及時釋放掉內存。

Swoole?webSocket客服IM消息系統怎么實現

出現問題的解決的原因是我在Crontab腳本里加了結束時長造成的問題,cli模式下的php生命周期進程得不到釋放造成的,合理使用Swoole中的協程就好了。

ini_set('memory_limit', '1024M');
set_time_limit(0);

感謝各位的閱讀,以上就是“Swoole webSocket客服IM消息系統怎么實現”的內容了,經過本文的學習后,相信大家對Swoole webSocket客服IM消息系統怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莆田市| 福州市| 晋州市| 株洲市| 分宜县| 汽车| 祁门县| 田东县| 永清县| 海宁市| 涡阳县| 古丈县| 荣昌县| 衡水市| 阿拉善盟| 正镶白旗| 浮山县| 行唐县| 元谋县| 图木舒克市| 巴彦淖尔市| 泰顺县| 定日县| 韶关市| 福鼎市| 六枝特区| 新田县| 长治市| 万荣县| 辉县市| 保德县| 青阳县| 彝良县| 吐鲁番市| 保康县| 简阳市| 太保市| 酉阳| 津南区| 合阳县| 隆德县|