TeamTalk-login_server学习

1、概述

LoginServer 承担登录请求分发器的角色,核心职责是为客户端匹配并返回当前负载最小的可用 MsgServer连接信息,同时实时维护集群中所有 MsgServer 的运行负载数据(含最大连接容量、当前在线用户数);当客户端发起登录请求时,若集群中无可用 MsgServer(如全部满载、无 MsgServer 接入),则向客户端返回约定的错误码,明确告知请求失败原因。

2、客户端与login_server的连接

8080端口监听客户端的连接

1、客户端点击登录

2、先连接,再发数据如下

复制代码
发送http请求,发送的报文如下:

GET /msg_server HTTP/1.1
Host:192.168.62.150:8080
Accept: */*
Connection: Keep-Alive

3、login_server,判断请求路径/msg_server,执行响应函CHttpConn::_HandleMsgServRequest

1、如果无可用msg_server,则回复客户端指定错误码

2、如果msg_server连接,找到msg_server在线用户数最少(负载最少),告诉客户端,回复数据如下:

复制代码
$2 = 0x75b080 "HTTP/1.1 200 OK\r\nConnection:close\r\nContent-Length:268\r\nContent-Type:text/html;chars
et=utf-8\r\n\r\n{\n   \"backupIP\" : \"192.168.62.150\",\n   \"code\" : 0,\n   \"discovery\" : \"http://
127.0.0.1/api/discovery\",\n   \"msfsBackup\" : \"http://192.168.62.150:8700/\",\n   \"msfsPrior\" : \"h
ttp://192.168.62.150:8700/\",\n   \"msg\" : \"\",\n   \"port\" : \"8001\",\n   \"priorIP\" : \"192.168.6
2.150\"\n}\n"

4、回复客户端数据后,立刻关闭连接

说明与客户端的http连接是短连接

3、login_server与msg_server的连接

8100端口:监听msg_server的连接

1、msg_server启动

1、init_login_serv_conn连接login_server

2、连接成功,向 LoginServer 注册自身服务信息(IP、端口、连接容量、当前在线数)

3、login_server将相关信息,保存到全局对象中

static ConnMap_t g_msg_serv_conn_map;

2、用户上下线,msg_server会通知login_server,login_server会更新msg_server在线人数

msg_server对应的代码

cpp 复制代码
   if (user_status == ::IM::BaseDefine::USER_STATUS_ONLINE) {
        IM::Server::IMUserCntUpdate msg;
        msg.set_user_action(USER_CNT_INC);
        msg.set_user_id(pImUser->GetUserId());
        CImPdu pdu;
        pdu.SetPBMsg(&msg);
        pdu.SetServiceId(SID_OTHER);
        pdu.SetCommandId(CID_OTHER_USER_CNT_UPDATE);
        send_to_all_login_server(&pdu);

Login_server对应的代码

cpp 复制代码
void CLoginConn::_HandleUserCntUpdate(CImPdu* pPdu)
{
        map<uint32_t, msg_serv_info_t*>::iterator it = g_msg_serv_info.find(m_handle);
        if (it != g_msg_serv_info.end()) {
                msg_serv_info_t* pMsgServInfo = it->second;
        IM::Server::IMUserCntUpdate msg;
        msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength());

                uint32_t action = msg.user_action();
                if (action == USER_CNT_INC) {
                        pMsgServInfo->cur_conn_cnt++;
                        g_total_online_user_cnt++;
                } else {
                        pMsgServInfo->cur_conn_cnt--;
                        g_total_online_user_cnt--;
                }

                log("%s:%d, cur_cnt=%u, total_cnt=%u ", pMsgServInfo->hostname.c_str(),
            pMsgServInfo->port, pMsgServInfo->cur_conn_cnt, g_total_online_user_cnt);
        }
}

3、其他

3.1、心跳包发送触发条件

当前时间 > 最后一次发送数据时间(m_last_send_tick) + 心跳间隔(SERVER_HEARTBEAT_INTERVAL),立即向对端发送心跳包。

3.2、连接超时关闭触发条件

当前时间 > 最后一次发送数据时间(m_last_send_tick) + 超时间隔(SERVER_TIMEOUT)

关闭连接。

cpp 复制代码
void CLoginConn::OnTimer(uint64_t curr_tick)
{
	if (m_conn_type == LOGIN_CONN_TYPE_CLIENT) {
		if (curr_tick > m_last_recv_tick + CLIENT_TIMEOUT) {
			Close();
		}
	} else {
		if (curr_tick > m_last_send_tick + SERVER_HEARTBEAT_INTERVAL) {
            IM::Other::IMHeartBeat msg;
            CImPdu pdu;
            pdu.SetPBMsg(&msg);
            pdu.SetServiceId(SID_OTHER);
            pdu.SetCommandId(CID_OTHER_HEARTBEAT);
			SendPdu(&pdu);
		}

		if (curr_tick > m_last_recv_tick + SERVER_TIMEOUT) {
			log("connection to MsgServer timeout ");
			Close();
		}
	}
}

3.3、心跳包设计

其实看源码,代码中并没有处理心跳包消息CID_OTHER_HEARTBEAT。

  • 若满足心跳发送条件,LoginServer 向 MsgServer 发送心跳包,发送成功后自动更新基类CImConnm_last_send_tick(最后一次发送数据时间)

  • MsgServer 侧遵循完全相同的逻辑:定时器触发后,满足条件则向 LoginServer 发送心跳包,同时更新自身基类的m_last_send_tick

  • 对端收到心跳包(合法 PDU)后,会自动刷新基类CImConnm_last_recv_tick(最后一次接收数据时间)

  • 定时器持续执行超时检查:若当前时间超过m_last_recv_tick + SERVER_TIMEOUT,即判定对端超长时间未发送任何数据(含心跳包、业务包),直接关闭连接

    m_last_send_tick本端发送任意数据后自动更新 (无论发送的是心跳包、业务包)

    m_last_recv_tick本端收到对端任意合法 PDU 后自动更新(无论接收的是心跳包、业务包)

相关推荐
肆忆_30 分钟前
Day 02|控制块分离架构:Boost 风格 shared_ptr 骨架落地
c++
锅包一切1 小时前
在蓝桥杯边练边学Rust:2.原生类型
开发语言·学习·蓝桥杯·rust
袁袁袁袁满1 小时前
Linux命令sudo -i和su root有什么区别吗?
linux·运维·服务器·su root·sudo -i
lightqjx1 小时前
【C++】C++11 常见特性
开发语言·c++·c++11
小嘉丶学长1 小时前
【跟小嘉学习经济学】一、微观经济学概述
学习
Full Stack Developme1 小时前
语法树与自动化技术
运维·前端·自动化
野犬寒鸦1 小时前
ArrayList扩容机制深度解析(附时序图详细讲解)
java·服务器·数据结构·数据库·windows·后端
RisunJan1 小时前
Linux命令-lvextend(扩展逻辑卷空间)
linux·运维·服务器
tankeven1 小时前
HJ92 在字符串中找出连续最长的数字串
c++·算法