您好,登錄后才能下訂單哦!
這篇文章主要講解了“Swoole webSocket客服IM消息系統(tǒng)怎么實(shí)現(xiàn)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Swoole webSocket客服IM消息系統(tǒng)怎么實(shí)現(xiàn)”吧!
技術(shù)的實(shí)現(xiàn)方案點(diǎn)主要PMQ,2組客戶(hù)端(用戶(hù)端、客服管理端),3個(gè)主要的部分組成(Push推送消息+Pull拉取未讀消息+MessageQueue消息隊(duì)列),具體流程和交互方式見(jiàn)上面的架構(gòu)流程圖。
1.建立鏈接,借鑒Tcp3次握手的原理,將每一次的用戶(hù)詢(xún)問(wèn)新增一個(gè)關(guān)系,詢(xún)問(wèn)結(jié)束時(shí)再將關(guān)系釋放,因?yàn)槊看坞S機(jī)分配的客服是不一致的,客服管理員控制臺(tái),進(jìn)入控制臺(tái)會(huì)觸發(fā)檢測(cè)客服映射關(guān)系的程序,以保證關(guān)系的唯一性。
2.客服分配:客服分配是根據(jù)用戶(hù)是否為第一次進(jìn)入鏈接進(jìn)行判定依據(jù),首次會(huì)隨機(jī)分發(fā)配給在線客服中的其中一個(gè),如果之前分配過(guò)的客服也在線,優(yōu)化分配存在客服,這樣處理的原因是客服不易變,用戶(hù)異變,防止反復(fù)鏈接/斷開(kāi)操作,減少網(wǎng)絡(luò)開(kāi)銷(xiāo)。
3.并發(fā)鎖:相同用戶(hù)在同一時(shí)間有3s的鎖定狀態(tài),用來(lái)防止關(guān)系錯(cuò)亂,在客戶(hù)端發(fā)來(lái)請(qǐng)求時(shí)優(yōu)先獲取緩存,近少可能的訪問(wèn)數(shù)據(jù)庫(kù),提高服務(wù)的穩(wěn)定性和性能。
//設(shè)置分布式鎖,3s之內(nèi)只能請(qǐng)求一次 $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)); } //查詢(xún)是否存在鏈接關(guān)系 $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.網(wǎng)絡(luò)異常處理,回收服務(wù):針對(duì)App崩潰、網(wǎng)絡(luò)異常斷開(kāi)的鏈接,主動(dòng)監(jiān)聽(tīng)斷開(kāi)的fd,進(jìn)行關(guān)系處理,對(duì)所有斷開(kāi)鏈接的websocket,進(jìn)行回收,清除關(guān)系。
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) { //回收用戶(hù) $uid = $redis->hGet('PUSH_MSG_SOCKET_FD', $fd); if (isset($uid) && !empty($uid) && is_numeric($uid)) { $redis->zRem('PUSH_MSG_USER_LOGIN', $fd); //檢測(cè)是否有客服關(guān)系未斷開(kāi) $redis->del(Category::$imUserRelationName . $uid); $redis->hDel('PUSH_MSG_SOCKET_FD', $fd); } //回收客服管理用戶(hù) $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.獲取離線消息分配算法,按照客服管理員在線人數(shù),把離線消息按照用戶(hù)來(lái)重新組裝,平均分配給在線管理員,如果數(shù)量不能被整除,也不會(huì)造成分配不均情況。
//驗(yàn)證客服管理員在線 $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對(duì)象不回收:從控制臺(tái)打開(kāi)新窗口時(shí),就會(huì)新增一個(gè)websocket對(duì)象,后來(lái)在瀏覽器中刷新處理的,沒(méi)有找到回收的辦法。
7.心跳:客服的websocket心跳使用的是實(shí)時(shí)push消息,5s循環(huán)一次,防止鏈接斷開(kāi),服務(wù)下線。
鏈接數(shù)變化正常,但是內(nèi)存好像沒(méi)有得到很好的釋放,而且進(jìn)程里也出現(xiàn)了很多野進(jìn)程,野進(jìn)程多可能存在的原因是這樣的,你沒(méi)有守護(hù)啟動(dòng),然后主進(jìn)程掛了,后面的進(jìn)程找不到父進(jìn)程,變成了僵尸進(jìn)程或者是孤兒進(jìn)程。
內(nèi)存也不對(duì)勁,大概率是我執(zhí)行腳本里出了問(wèn)題,去掉了修改配置的語(yǔ)句,在Base類(lèi)里加入了unset,及時(shí)釋放掉內(nèi)存。
出現(xiàn)問(wèn)題的解決的原因是我在Crontab腳本里加了結(jié)束時(shí)長(zhǎng)造成的問(wèn)題,cli模式下的php生命周期進(jìn)程得不到釋放造成的,合理使用Swoole中的協(xié)程就好了。
ini_set('memory_limit', '1024M'); set_time_limit(0);
感謝各位的閱讀,以上就是“Swoole webSocket客服IM消息系統(tǒng)怎么實(shí)現(xiàn)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Swoole webSocket客服IM消息系統(tǒng)怎么實(shí)現(xiàn)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。