im源碼分析(teamtalk)--RouteServer

im源碼分析(teamtalk)系列:

1. im源碼分析(teamtalk)–LoginServer
2. im源碼分析(teamtalk)–RouteServer
3. im源碼分析(teamtalk)–DbProxyServer

RouteServer介紹

RouteServer: 路由服務器,在存在多個MsgServer的情況下,用戶可能登陸在不同的MsgServer上,這個時候就需要RouteServer進行轉發。

源碼分析

void CRouteConn::HandlePdu(CImPdu* pPdu)
{
	switch (pPdu->GetCommandId()) {
        case CID_OTHER_HEARTBEAT:
            // do not take any action, heart beat only update m_last_recv_tick
            break;
        case CID_OTHER_ONLINE_USER_INFO:
            _HandleOnlineUserInfo( pPdu );
            break;
        case CID_OTHER_USER_STATUS_UPDATE:
            _HandleUserStatusUpdate( pPdu );
            break;
        case CID_OTHER_ROLE_SET:
            _HandleRoleSet( pPdu );
            break;
        case CID_BUDDY_LIST_USERS_STATUS_REQUEST:
            _HandleUsersStatusRequest( pPdu );
            break;
        case CID_MSG_DATA:
        case CID_SWITCH_P2P_CMD:
        case CID_MSG_READ_NOTIFY:
        case CID_OTHER_SERVER_KICK_USER:
        case CID_GROUP_CHANGE_MEMBER_NOTIFY:
        case CID_FILE_NOTIFY:
        case CID_BUDDY_LIST_REMOVE_SESSION_NOTIFY:
            _BroadcastMsg(pPdu, this);
            break;
        case CID_BUDDY_LIST_SIGN_INFO_CHANGED_NOTIFY:
            _BroadcastMsg(pPdu);
            break;
        
	default:
		log("CRouteConn::HandlePdu, wrong cmd id: %d ", pPdu->GetCommandId());
		break;
	}
}

_HandleOnlineUserInfo
更新在線用戶的信息,只有變更的用戶信息,不是所有的。
_HandleUserStatusUpdate
用戶多點多端登錄的處理邏輯。
_HandleRoleSet
設置MsgServer的主路由服務
_HandleUsersStatusRequest

void CRouteConn::_HandleUsersStatusRequest(CImPdu* pPdu)
{
    IM::Buddy::IMUsersStatReq msg;
    CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength()));

	uint32_t request_id = msg.user_id();
	uint32_t query_count = msg.user_id_list_size();
	log("HandleUserStatusReq, req_id=%u, query_count=%u ", request_id, query_count);

    IM::Buddy::IMUsersStatRsp msg2;
    msg2.set_user_id(request_id);
    msg2.set_attach_data(msg.attach_data());
    list<user_stat_t> result_list;
	user_stat_t status;
    for(uint32_t i = 0; i < query_count; i++)
	{
        IM::BaseDefine::UserStat* user_stat = msg2.add_user_stat_list();
        uint32_t user_id = msg.user_id_list(i);
        user_stat->set_user_id(user_id);
        CUserInfo* pUser = GetUserInfo(user_id);
        if (pUser) {
            user_stat->set_status((::IM::BaseDefine::UserStatType) pUser->GetStatus()) ;
        }
		else
		{
            user_stat->set_status(USER_STATUS_OFFLINE) ;
		}
	}

	// send back query user status
    CImPdu pdu;
    pdu.SetPBMsg(&msg2);
    pdu.SetServiceId(SID_BUDDY_LIST);
    pdu.SetCommandId(CID_BUDDY_LIST_USERS_STATUS_RESPONSE);
	pdu.SetSeqNum(pPdu->GetSeqNum());
	SendPdu(&pdu);
}

刷新好友狀態;
_BroadcastMsg
向MsgServer廣播信息。

問題:RouteServer已經有所有用戶id的在線狀態和連接信息,爲什麼所有的消息都要廣播?

個人推測這可能是要改進的一個點,在多個MsgServer存在的情況下完全可以根據用戶id定向轉發消息,這樣能減少網絡資源的浪費。

延伸:存在多個RouteServer的情況下,如何保證消息的唯一性?

OK,這就用到_HandleRoleSet這個接口了:
MsgServer在啓動後會主動去RouteServer去註冊,並把當前所有在線的用戶信息告知RouterServer,然後在所有RouteServer列表中選擇一個主路由服務(觸發RouterServer的_HandleRoleSet接口),所有的轉發消息只走主路由服務
冗餘的RouteServer做爲備份,在主RouteServer掛掉的情況下,提高可用性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章