最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Swoole?webSocket客服IM消息系統(tǒng)方案解析

 更新時間:2023年03月14日 10:46:55   作者:stark張宇  
這篇文章主要為大家介紹了Swoole?webSocket客服IM消息系統(tǒng)方案解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

概述

基于Swoole的websocket服務,再之前的消息系統(tǒng)系列的第4篇,實現(xiàn)了更加復雜的業(yè)務場景,是對消息推送的完善和優(yōu)化,代碼本身就是不斷自我優(yōu)化的過程。

實現(xiàn)方案

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

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

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

3.并發(fā)鎖:相同用戶在同一時間有3s的鎖定狀態(tài),用來防止關(guān)系錯亂,在客戶端發(fā)來請求時優(yōu)先獲取緩存,近少可能的訪問數(shù)據(jù)庫,提高服務的穩(wěn)定性和性能。

//設(shè)置分布式鎖,3s之內(nèi)只能請求一次
$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));
}
//查詢是否存在鏈接關(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)絡異常處理,回收服務:針對App崩潰、網(wǎng)絡異常斷開的鏈接,主動監(jiān)聽斷開的fd,進行關(guān)系處理,對所有斷開鏈接的websocket,進行回收,清除關(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) {
                //回收用戶
                $uid = $redis->hGet('PUSH_MSG_SOCKET_FD', $fd);
                if (isset($uid) && !empty($uid) && is_numeric($uid)) {
                    $redis->zRem('PUSH_MSG_USER_LOGIN', $fd);
                    //檢測是否有客服關(guān)系未斷開
                    $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.獲取離線消息分配算法,按照客服管理員在線人數(shù),把離線消息按照用戶來重新組裝,平均分配給在線管理員,如果數(shù)量不能被整除,也不會造成分配不均情況。

//驗證客服管理員在線
$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循環(huán)一次,防止鏈接斷開,服務下線。

實踐Swoole里的坑

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

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

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

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

成果

上線2年的時間里,進行了5次升級和優(yōu)化,活躍用戶10w+,最高峰值6w/s,130w/h訪問量,是一個非常成功的實踐結(jié)果。

用最簡單的技術(shù)實現(xiàn)方式,節(jié)省企業(yè)成本,減少系統(tǒng)開發(fā)和維護成本,提高辦公效率才是技術(shù)人應該做的事兒,做解決實際復雜業(yè)務解決方案并落地的技術(shù)人,En。

以上就是Swoole webSocket客服IM消息系統(tǒng)方案解析的詳細內(nèi)容,更多關(guān)于Swoole webSocket IM消息的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Yii2主題(Theme)用法詳解

    Yii2主題(Theme)用法詳解

    這篇文章主要介紹了Yii2主題(Theme)用法,結(jié)合實例形式分析了Yii2主題(Theme)的配置方式、函數(shù)與相關(guān)屬性的使用技巧,需要的朋友可以參考下
    2016-07-07
  • PHP內(nèi)核探索之變量

    PHP內(nèi)核探索之變量

    php變量由變量名,類型,內(nèi)容等部分組成,本文給大家分享php內(nèi)核探索之變量,對php內(nèi)核探索相關(guān)知識感興趣的朋友一起學習吧
    2015-12-12
  • thinkphp 中的volist標簽在ajax操作中的特殊性(推薦)

    thinkphp 中的volist標簽在ajax操作中的特殊性(推薦)

    在一個ThinkPHP的復雜頁面(包含volist)中實現(xiàn)volist標簽顯示Jquery查詢結(jié)果的返回。這篇文章給大家介紹了thinkphp 中的volist標簽在ajax操作中的特殊性(推薦),需要的朋友參考下吧
    2018-01-01
  • 關(guān)于Laravel-admin的基礎(chǔ)用法總結(jié)和自定義model詳解

    關(guān)于Laravel-admin的基礎(chǔ)用法總結(jié)和自定義model詳解

    今天小編就為大家分享一篇關(guān)于Laravel-admin的基礎(chǔ)用法總結(jié)和自定義model詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • PHP中的函數(shù)聲明與使用詳解

    PHP中的函數(shù)聲明與使用詳解

    這篇文章主要介紹了PHP中的函數(shù)聲明與使用,需要的朋友可以參考下
    2017-05-05
  • phpstorm 配置xdebug的示例代碼

    phpstorm 配置xdebug的示例代碼

    這篇文章主要介紹了phpstorm 配置xdebug的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • 詳解PHP中instanceof關(guān)鍵字及instanceof關(guān)鍵字有什么作用

    詳解PHP中instanceof關(guān)鍵字及instanceof關(guān)鍵字有什么作用

    這篇文章主要介紹了PHP中instanceof關(guān)鍵字詳解及instanceof關(guān)鍵字有什么作用的相關(guān)資料,需要的朋友可以參考下
    2015-11-11
  • php圖片的裁剪與縮放生成符合需求的縮略圖

    php圖片的裁剪與縮放生成符合需求的縮略圖

    用在移動設(shè)備上時顯示效果不好且流量巨大,需要對現(xiàn)有圖片庫的圖片進行一次處理,生成符合移動設(shè)備用的縮略圖,將原來客戶端JS做的工作轉(zhuǎn)移到服務器端用PHP的GD庫來集中處理,感興趣的朋友可以了解下
    2013-01-01
  • php 流程控制switch的簡單實例

    php 流程控制switch的簡單實例

    下面小編就為大家?guī)硪黄猵hp 流程控制switch的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • Symfony控制層深入詳解

    Symfony控制層深入詳解

    這篇文章主要介紹了Symfony控制層,結(jié)合大量實例代碼深入分析了Symfony控制器的常見使用技巧與相關(guān)注意事項,需要的朋友可以參考下
    2016-03-03

最新評論

翁牛特旗| 庆元县| 崇文区| 定远县| 得荣县| 都江堰市| 华容县| 闽清县| 商城县| 宁晋县| 息烽县| 大兴区| 卢氏县| 巴里| 铜鼓县| 密山市| 红河县| 嵊州市| 普兰县| 和田县| 灵丘县| 修武县| 驻马店市| 南投市| 固阳县| 光山县| 宁陵县| 临安市| 余江县| 茌平县| 漳平市| 辰溪县| 阿拉善右旗| 庄浪县| 广南县| 澎湖县| 阜城县| 花莲县| 丽水市| 鹤庆县| 正镶白旗|