(TeamTalk服务端源码分析三)route_server源码分析

route_server源码分析

     Route_Server是路由服务器,当存在多个MsgServer时,用户可能登陆在不同的MsgServer上(由Login_Server进行负载均衡),那么对于连接在不同的Msg_Server上的两个用户A和B如何进行消息转发呢,这个时候就需要用到Route_Server。
     上一节分析Login_Server时已经介绍了服务端的基本通信结构,TeamTalk的服务端都使用相同的通信方式,因此后续的系列文章不再重复介绍。我们主要看一下Route_Server的业务逻辑:

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:	//msg_server连接上route_server后,将当前msg_server上的用户登录情况通知过来
            _HandleOnlineUserInfo( pPdu );
            break;
        case CID_OTHER_USER_STATUS_UPDATE:	//当msg_server上有用户上下线时,msg_server会给route_server发送自己最近的用户数量和在线用户id信息
            _HandleUserStatusUpdate( pPdu );
            break;
        case CID_OTHER_ROLE_SET:			//当存在多个route_server时,对于msg_server而言,要确定一个主路由,消息只会发到主路由
            _HandleRoleSet( pPdu );
            break;
        case CID_BUDDY_LIST_USERS_STATUS_REQUEST:	//获取用户各个端的登录状态
            _HandleUsersStatusRequest( pPdu );
            break;
        case CID_MSG_DATA:					//这几个都是往外广播消息(A给B发了一条消息,必须广播在各个msg_server 才能知道B到底在哪个msg_server上。)
        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;
	}
}

(1) CID_OTHER_HEARTBEAT
     心跳消息,这里没有做任何处理,是因为定时任务中已经帮我们做了心跳超时校验:
在这里插入图片描述
设计心跳时,心跳消息并不能只是单纯的多少秒发送一笔,而要结合实际的业务情况。如果在心跳等待发送过程中,有业务已经通过传输到了对端,那么此时应该更新上一次的心跳发送时间为最近一次的网络传输时间。

(2) CID_OTHER_ONLINE_USER_INFO
     当msg_server连接上route_server后,会将当前msg_server上的用户登录情况通知过来。主要包括用户id,用户登录状态,用户登录设备类型。

(3) CID_OTHER_USER_STATUS_UPDATE
     当msg_server上有用户上下线时,msg_server会将该用户的信息发送给route_server。主要包括用户id,用户登录状态,用户登录设备类型

(4) CID_OTHER_ROLE_SET
     当存在多个route_server时,对于msg_server而言,要确定一个主路由,消息只会发到主路由服务器。msg_server确定了主路由后,会发送该消息到主route_server。route_server代码中也只是存一下这个标志,并没有用到。

(5) CID_BUDDY_LIST_USERS_STATUS_REQUEST
     Msg_Server发送请求到route_server上查询用户的在线状态。主要用于发送离线文件时,获取对端用户的pc登录状态,只有pc端在线,才推送离线文件。

(6) 其他消息
     其它的业务消息,比如发送文件,刷新好友状态等等,都通过route_server转发给所有连接到当前路由服务器的msg_server上。个人觉得这个地方的处理可以改进:由于route_server上已经有用户id和对应的msg_server信息,完全可以根据对端id进行指定msg_server发送消息,而不用广播给所有的msg_server。

改进:
     从login_server以及route_server的源码分析中,我们可以看到,TeamTalk服务端采用的都是epoll模型,在主线程中通过while循环,来执行epoll_wait等待触发,触发后,再调用各个已触发的描述符对应的业务类CimConn的实现接口。这种设计模式并不是很完美,因为直接在epoll_wait触发后进行业务的轮询处理,此处可以加入一个线程池,将接收到的数据(此处不要将fd放入线程池中,避免多线程处理同一个fd)都丢入到线程池中进行分发处理。如果业务较少的情况下,也可以根据业务类型分发到不同的业务线程,以提高CPU的利用率。这也就是I/O复用+多线程的设计思想。

发布了78 篇原创文章 · 获赞 79 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/bajianxiaofendui/article/details/103465129