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 后自动更新(无论接收的是心跳包、业务包)

相关推荐
weixin_458872618 分钟前
东华复试OJ二刷复盘7
学习
筱砚.8 分钟前
C++——lambda
开发语言·c++·算法
linux修理工12 分钟前
下载亚马逊Corretto 17的方法(OpenJDK 17发行版)
java·运维·服务器
gbling19 分钟前
网页多次重定向问题
运维·nginx
Xi-Xu20 分钟前
在云服务器上安全运行 OpenClaw:从安装到加固的完整指南
运维·服务器·人工智能·安全
孫治AllenSun41 分钟前
【Linux】配置服务自启动
linux·运维·服务器
盐水冰43 分钟前
【Redis】学习(2)Redis常见命令
数据库·redis·学习
adore.9681 小时前
3.13 复试学习
学习
SteveSenna1 小时前
机械臂模仿学习2.3:生成式对抗模仿学习GAIL
学习