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挂掉的情况下,提高可用性。

发布了59 篇原创文章 · 获赞 22 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Martin_chen2/article/details/90913102
IM