im源码分析(teamtalk)系列:
1. im源码分析(teamtalk)–LoginServer
2. im源码分析(teamtalk)–RouteServer
3. im源码分析(teamtalk)–DbProxyServer
LoginServer
LoginServer功能介绍
登陆服务器,主要作用是实现负载均衡,分配一个负载小的MsgServer给客户端使用。这里的负载较小是指MsgServer的tcp连接数大小。
源码分析
1.交互服务
int ret = netlib_init();
if (ret == NETLIB_ERROR)
return ret;
CStrExplode client_listen_ip_list(client_listen_ip, ';');
for (uint32_t i = 0; i < client_listen_ip_list.GetItemCnt(); i++) {
ret = netlib_listen(client_listen_ip_list.GetItem(i), client_port, client_callback, NULL);
if (ret == NETLIB_ERROR)
return ret;
}
CStrExplode msg_server_listen_ip_list(msg_server_listen_ip, ';');
for (uint32_t i = 0; i < msg_server_listen_ip_list.GetItemCnt(); i++) {
ret = netlib_listen(msg_server_listen_ip_list.GetItem(i), msg_server_port, msg_serv_callback, NULL);
if (ret == NETLIB_ERROR)
return ret;
}
CStrExplode http_listen_ip_list(http_listen_ip, ';');
for (uint32_t i = 0; i < http_listen_ip_list.GetItemCnt(); i++) {
ret = netlib_listen(http_listen_ip_list.GetItem(i), http_port, http_callback, NULL);
if (ret == NETLIB_ERROR)
return ret;
}
这里一共监听三个端口,并注册了回调函数:
client_callback:监听客户端tcp请求
msg_serv_callback:监听MsgServer连接
http_callback:监听http请求
2.主要功能
主要有三个功能:
private:
// MsgServer连接请求,会把msgserver连接数和ip等信息告知Loginserver
void _HandleMsgServInfo(CImPdu* pPdu);
// 用户数更新,MsgServer新增连接或减少连接,更新LoginServer记录的个数
void _HandleUserCntUpdate(CImPdu* pPdu);
// 请求MsgServer地址,分两个接口,一个是http请求,一个是客户端的长连接请求
void _HandleMsgServRequest(CImPdu* pPdu);
看一下LoginServer这边保存的都有哪些MsgServer的信息
typedef struct {
string ip_addr1; // 电信IP
string ip_addr2; // 网通IP
uint16_t port;
uint32_t max_conn_cnt; // 最大连接数
uint32_t cur_conn_cnt; // 当前连接数,实时更新
string hostname; // 消息服务器的主机名
} msg_serv_info_t;
如何进行负载均衡
找到连接数最少的MsgServer,并且不超过该MsgServer的最大连接数:
// return a message server with minimum concurrent connection count
msg_serv_info_t* pMsgServInfo;
uint32_t min_user_cnt = (uint32_t)-1;
map<uint32_t, msg_serv_info_t*>::iterator it_min_conn = g_msg_serv_info.end(),it;
for (it = g_msg_serv_info.begin() ; it != g_msg_serv_info.end(); it++) {
pMsgServInfo = it->second;
if ( (pMsgServInfo->cur_conn_cnt < pMsgServInfo->max_conn_cnt) &&
(pMsgServInfo->cur_conn_cnt < min_user_cnt))
{
it_min_conn = it;
min_user_cnt = pMsgServInfo->cur_conn_cnt;
}
}