国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

基于wokerman實現即時消息推送

JellyBool / 1684人閱讀

摘要:目前網站有兩個用到實時消息推送的功能,源碼最新動態,實時顯示用戶的操作行為消息推送,如重要消息通知,任務指派等等考慮的問題既然要實現即時,那就少不了。

目前網站有兩個用到實時消息推送的功能,源碼:https://github.com/wuzhc/team

最新動態,實時顯示用戶的操作行為

消息推送,如重要消息通知,任務指派等等

考慮的問題

既然要實現即時,那就少不了socketio。因為項目是PHP寫的,所以服務端直接用phpsocket.io

我們應該保存離線消息,否則如果用戶不在線,那就接受不到消息。這里我用mongodb來存儲消息。

一是消息不需要關聯表,一條消息一個文檔

二是mongodb適合做海量數據存儲,并且分片也很簡單

三是消息不需要永久存儲,隨著時間推移,消息的價值性越低,可以用固定集合來存儲消息,當數據量達到一定值時覆蓋最久的消息

一個頁面連接一個socket,若用戶同時打開了多個頁面(即一個用戶會對應多個socketID),那么消息應該推送到用戶每一個打開的頁面。一個簡單的做法就是把用戶多個sockID加到group分組(socket.emit("group")),group分組名稱可以是"uid:1",表示userID為1的用戶,然后socket.broadcast.to("uid:1").emit("event_name", data);

就可以實現對多個頁面推送消息

實時動態

實時消息推送

客戶端
        // 初始化io對象
        var socket = io("http://" + document.domain + ":2120");
        // 當socket連接后發送登錄請求
        socket.on("connect", function () {
            socket.emit("login", {
                uid: "user->id?>",
                companyID: "user->identity->fdCompanyID?>"
            });
        });
        // 實時消息,當服務端推送來消息時觸發
        socket.on("new_msg", function (msg) {
            if (msg.typeID == "") {
                var html = "
  • " + "" + "
    " + "" + "
    " + "

    " + msg.title + "

    " + "

    " + msg.content + "

    " + "
    " + "
  • "; $("#msg-handle").prepend(html); var num = $(".msg-handle-num").eq(1).text() * 1; $(".msg-handle-num").text(num + 1); } }); // 實時動態,當服務端推送來消息時觸發 socket.on("update_dynamic", function (msg) { var html = "
  • " + "" + "User Image" + "
    " + "" + "" + msg.date + "" + "

    " + "" + msg.operator + "" + "" + msg.title + "" + "

    " + "
    " + msg.content + "
    " + "
    " + "
  • "; $("#dynamic-list").prepend(html); }); // 在線人數 socket.on("update_online_count", function (msg) { $("#online-people").html(msg); });
    服務端
        /**
         * 消息推送
         */
        public function actionStart()
        {
            // PHPSocketIO服務
            $io = new SocketIO(2120);
            // 客戶端發起連接事件時,設置連接socket的各種事件回調
            $io->on("connection", function ($socket) use ($io) {
    
                /** @var Connection $redis */
                $redis = Yii::$app->redis;
    
                // 當客戶端發來登錄事件時觸發
                $socket->on("login", function ($data) use ($socket, $redis, $io) {
    
                    $uid = isset($data["uid"]) ? $data["uid"] : null;
                    $companyID = isset($data["companyID"]) ? $data["companyID"] : null;
    
                    // uid和companyID應該做下加密 by wuzhc 2018-01-28
                    if (empty($uid) || empty($companyID)) {
                        return ;
                    }
                    $this->companyID = $companyID;
    
                    // 已經登錄過了
                    if (isset($socket->uid)) {
                        return;
                    }
    
                    $key = "socketio:company:" . $companyID;
                    $field = "uid:" . $uid;
    
                    // 用hash方便統計用戶打開頁面數量
                    if (!$redis->hget($key, $field)) {
                        $redis->hset($key, $field, 0);
                    }
    
                    // 同個用戶打開新頁面時加1
                    $redis->hincrby($key, $field, 1);
    
                    // 加入uid分組,方便對同個用戶的所有打開頁面推送消息
                    $socket->join("uid:". $uid);
    
                    // 加入companyID,方便對整個公司的所有用戶推送消息
                    $socket->join("company:".$companyID);
    
                    $socket->uid = $uid;
                    $socket->companyID = $companyID;
    
                    // 整個公司在線人數更新
                    $io->to("company:".$companyID)->emit("update_online_count", $redis->hlen($key));
                });
    
                // 當客戶端斷開連接是觸發(一般是關閉網頁或者跳轉刷新導致)
                $socket->on("disconnect", function () use ($socket, $redis, $io) {
                    if (!isset($socket->uid)) {
                        return;
                    }
    
                    $key = "socketio:company:" . $socket->companyID;
                    $field = "uid:" . $socket->uid;
                    $redis->hincrby($key, $field, -1);
    
                    if ($redis->hget($key, $field) <= 0) {
                        $redis->hdel($key, $field);
    
                        // 某某下線了,刷新整個公司的在線人數
                        $io->to("company:".$socket->companyID)->emit("update_online_count", $redis->hlen($key));
                    }
                });
            });
    
            // 開始進程時,監聽2121端口,用戶數據推送
            $io->on("workerStart", function () use ($io) {
                /** @var Connection $redis */
                $redis = Yii::$app->redis;
    
                $httpWorker = new Worker("http://0.0.0.0:2121");
                // 當http客戶端發來數據時觸發
                $httpWorker->onMessage = function ($conn, $data) use ($io, $redis) {
                    $_POST = $_POST ? $_POST : $_GET;
                    switch (@$_POST["action"]) {
                        case "message":
                            $to = "uid:" . @$_POST["receiverID"];
                            $_POST["content"] = htmlspecialchars(@$_POST["content"]);
                            $_POST["title"] = htmlspecialchars(@$_POST["title"]);
    
                            // 有指定uid則向uid所在socket組發送數據
                            if ($to) {
                                $io->to($to)->emit("new_msg", $_POST);
                            }
    
                            $companyID = @$_POST["companyID"];
                            $key = "socketio:company:" . $companyID;
                            $field = "uid:" . $to;
    
                            // http接口返回,如果用戶離線socket返回fail
                            if ($to && $redis->hget($key, $field)) {
                                return $conn->send("offline");
                            } else {
                                return $conn->send("ok");
                            }
                            break;
                        case "dynamic":
                            $to = "company:" . @$_POST["companyID"];
                            $_POST["content"] = htmlspecialchars(@$_POST["content"]);
                            $_POST["title"] = htmlspecialchars(@$_POST["title"]);
    
                            // 有指定uid則向uid所在socket組發送數據
                            if ($to) {
                                $io->to($to)->emit("update_dynamic", $_POST);
                            }
    
                            $companyID = @$_POST["companyID"];
                            $key = "socketio:company:" . $companyID;
    
                            // http接口返回,如果用戶離線socket返回fail
                            if ($to && $redis->hlen($key)) {
                                return $conn->send("offline");
                            } else {
                                return $conn->send("ok");
                            }
                    }
    
                    return $conn->send("fail");
                };
    
                // 執行監聽
                $httpWorker->listen();
            });
    
            // 運行所有的實例
            global $argv;
            array_shift($argv);
    
            if (isset($argv[2]) && $argv[2] == "daemon") {
                $argv[2] = "-d";
            }
    
            Worker::runAll();
        }
    例子
        /**
         * 新建任務
         * @param $projectID
         * @param $categoryID
         * @return string
         * @throws ForbiddenHttpException
         * @since 2018-01-26
         */
        public function actionCreate($projectID, $categoryID)
        {
            $userID = Yii::$app->user->id;
    
            if (!Yii::$app->user->can("createTask")) {
                throw new ForbiddenHttpException(ResponseUtil::$msg[1]);
            }
    
            if ($data = Yii::$app->request->post()) {
                if (empty($data["name"])) {
                    ResponseUtil::jsonCORS(["status" => Conf::FAILED, "msg" => "任務標題不能為空"]);
                }
    
                // 保存任務
                $taskID = TaskService::factory()->save([
                    "name"       => $data["name"],
                    "creatorID"  => $userID,
                    "companyID"  => $this->companyID,
                    "level"      => $data["level"],
                    "categoryID" => $categoryID,
                    "projectID"  => $projectID,
                    "content"    => $data["content"]
                ]);
    
                if ($taskID) {
                    $url = Url::to(["task/view", "taskID" => $taskID]);
                    $portrait = UserService::factory()->getUserPortrait($userID);
                    $username = UserService::factory()->getUserName($userID);
                    $title = "創建了新任務";
                    $content = $data["name"];
    
                    // 保存操作日志
                    LogService::factory()->saveHandleLog([
                        "objectID"   => $taskID,
                        "companyID"  => $this->companyID,
                        "operatorID" => $userID,
                        "objectType" => Conf::OBJECT_TASK,
                        "content"    => $content,
                        "url"        => $url,
                        "title"      => $title,
                        "portrait"   => $portrait,
                        "operator"   => $username
                    ]);
    
                    // 動態推送
                    MsgService::factory()->push("dynamic", [
                        "companyID"  => $this->companyID,
                        "operatorID" => $userID,
                        "operator"   => $username,
                        "portrait"   => $portrait,
                        "title"      => $title,
                        "content"    => $content,
                        "url"        => $url,
                        "date"       => date("Y-m-d H:i:s"),
                    ]);
    
                    ResponseUtil::jsonCORS(null, Conf::SUCCESS, "創建成功");
                } else {
                    ResponseUtil::jsonCORS(null, Conf::FAILED, "創建失敗");
                }
            } else {
                return $this->render("create", [
                    "projectID" => $projectID,
                    "category"  => TaskCategory::findOne(["id" => $categoryID]),
                ]);
            }
        }
    調用保存操作日志底層接口
    LogService::factory()->saveHandleLog($args)
    參數說明
    參數 說明
    operatorID 操作者ID,用于用戶跳轉鏈接
    companyID 公司ID,用于該公司下的動態
    operator 操作者姓名
    portrait 操作者頭像
    receiver 接受者,可選
    title 動態標題,例如創建任務
    content 動態內容,例如創建任務的名稱
    date 動態時間
    url 動態跳轉鏈接
    token 驗證
    objectType 對象類型,例如任務,文檔等等
    objectID 對象ID,例如任務ID,文檔ID等等

    companyID 用于查詢該公司下的動態

    objectType和objectID組合可以查詢某個對象的操作日志,例如一個任務被操作的日志

    保存消息
    參數 說明
    senderID 發送者ID,用于用戶跳轉鏈接
    companyID 公司ID,用于該公司下的動態
    sender 發送者姓名
    portrait 發送者頭像
    receiverID 接受者ID
    title 動態標題,例如創建任務
    content 動態內容,例如創建任務的名稱
    date 動態時間
    url 動態跳轉鏈接
    typeID 消息類型,1系統通知,2管理員通知,3操作通知

    receiverID和typeID和isRead組合可以查詢用戶未讀消息

    請求接口
    MsgService::factory()->push($action, $args)
    即時動態
    參數 說明
    operatorID 操作者ID,用于用戶跳轉鏈接
    companyID 公司ID,用于給該公司的所有socket推送
    operator 操作者姓名
    portrait 操作者頭像
    receiver 接受者,可選
    title 動態標題,例如創建任務
    content 動態內容,例如創建任務的名稱
    date 動態時間
    url 動態跳轉鏈接
    即時消息
    參數 說明
    senderID 發送者ID,用于用戶跳轉鏈接
    sender 發送者姓名
    receiverID 接受者ID,用于給接受者的所有socket推送消息
    typeID 消息類型,1系統通知,2管理員通知,3操作通知
    portrait 發送者頭像
    title 消息標題
    content 消息內容
    url 消息跳轉鏈接
    完整代碼參考:https://github.com/wuzhc/team

    文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

    轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/28194.html

    相關文章

    • 打造你的Laravel即時應用(二)-消息推送與監聽

      摘要:打造你的即時應用二消息推送與監聽年月日接于上篇博客打造你的即時應用一項目初始化構建在上一篇博客中介紹了項目的基本構建現在進入實戰操作一消息推送創建事件類的廣播推送通過來實現下面通過命令來創建一個事件類為了配合我們的廣播系統使用需要實現接 打造你的Laravel即時應用(二)-消息推送與監聽 2019年08月04日20:16:21 XXM 接于上篇博客: 打造你的Laravel即時應用(...

      omgdog 評論0 收藏0
    • 搭建IM服務 so easy

      摘要:現在很多網站都通過服務來實現消息推送及數據即時同步功能,即時通訊組件逐漸成為產品的標配。目前國內有很多成熟穩定的第三方即時通訊服務廠家,比如融云。 現在很多網站、APP都通過IM服務來實現消息推送及數據即時同步功能,即時通訊組件逐漸成為產品的標配。目前國內有很多成熟穩定的第三方即時通訊服務廠家,比如:融云。使用這些專業的服務可以提高開發效率而且服務穩定有保障。 如果自己DIY或者需要在...

      imccl 評論0 收藏0

    發表評論

    0條評論

    最新活動
    閱讀需要支付1元查看
    <