tars服务端(四):链接管理

本文详细介绍了TARS服务端的链接管理,包括链接的UID生成规则、链接的刷新和超时检查机制,以及不同类型的链接关闭方式。重点讨论了UID如何由魔数和唯一ID组成,超时检查如何通过有序的超时链表高效进行,以及链接关闭时网络线程如何通知业务层。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

这里的链接管理主要关注下面几个问题:

  • 链接_uid生成规则
  • 链接刷新和超时踢掉机制
  • 链接关闭

一.ConnectionList中的_uid

1.链接管理相关的类图:

 

  • 每个网络线程都有一个独立的链接列表ConnectionList,负责管理该网络线程的所有Connection,ConnectionList继承于TC_ThreadLock,是线程安全的
  • ConnectionList的_total表示管理的最大链接数;_free里面存储的是还未使用的唯一id(用于生成链接的标识符_uid);魔数_ConnectionMagic也是用于生成链接的_uid;_tl和_vConn两个成员用于管理所有的链接
  • Connection负责socket的接收和发送。除了_socke,_ip,_recvbuffer等与接收和发送相关的成员外,每个Connection还有一个4字节大小的链接标识_uid

2._uid生成规则

每个_uid由两部分生成:魔数+唯一id:

  • 魔数的组成:高6位( 上图的x部分)来自当前时间截;网络线程索引的范围是1-15,即只有低4位为有效位,经过左移22位后作为魔数接下来的4位(图中的y部分);最后的22位都为0。因为加入了线程索引的因素,所以每个线程的魔数都不一样。实际上也可以反过来推断为什么tars限制网络线程数最多为15,因为4位二进制最大即为15。
  • 唯一id的范围:最小为1,最大为_total。这个_total为所有Adapter允许的最大连接数之和,tars把这个_total最大限制为  (1 << 22)-1了。所以唯一id的高10位全为0,低22位为有效位(上图的z部分)。
  • 一个server的_uid个数最多为_total * 网络线程数。如果不考虑文件系统fd的限制,不考虑内存,cpu等,那么这个值就是一个tars服务理论上最大的链接数。

魔数和唯一id的生成代码在ConnectionList::init(uint32_t size,uint32_t iIndex)中:

void TC_EpollServer::NetThread::ConnectionList::init(uint32_t size, uint32_t iIndex)                                           
{                                                                                                                              
    _lastTimeoutTime = TNOW;                                                                                                   
                                                                                                                               
    _total = size;                                                                                                             
                                                                                                                               
    _free_size  = 0;                                                                                                           
                                                                                                                               
    //初始化链接链表                                                                                                           
    if(_vConn) delete[] _vConn;                                                                                                
                                                                                                                               
    //分配total+1个空间(多分配一个空间, 第一个空间其实无效)                                                                    
    _vConn = new list_data[_total+1];                                                                                          
                                                                                                                               
    _iConnectionMagic   = ((((uint32_t)_lastTimeoutTime) << 26) & (0xFFFFFFFF << 26)) + ((iIndex << 22) & (0xFFFFFFFF << 22));//((uint32_t)_lastTimeoutTime) << 20;                                                                                           
                                                                                                                               
    //free从1开始分配, 这个值为uid, 0保留为管道用, epollwait根据0判断是否是管道消息                                            
    for(uint32_t i = 1; i <= _total; i++)                                                                                      
    {                                                                                                                          
        _vConn[i].first = NULL;                                                                                                
                                                                                                                               
        _free.push_back(i);                                                                                                    
                                                                                                                               
        ++_free_size;                                                                                                          
    }                                                                                                                          
}                   
  • 在init()中,生成了固定的魔数_iConnectionMagic后,把所有的唯一id按1到_total的顺序push到_free中。这个_free用来存储还没被使用的唯一id
  • 调用这个init()的地方在NetThread::createEpoll(uint32_t iIndex),在这里可以看到对_total的限制:
    void TC_EpollServer::NetThread::createEpoll(uint32_t iIndex)
    {                                                                                                                              
        省略部分代码
        ..........
           
    
        if(maxAllConn >= (1 << 22))
        {
            error("createEpoll connection num: " + TC_Common::tostr(maxAllConn) + " >= " + TC_Common::tostr(1 << 22));
            maxAllConn = (1 << 22) - 1;
        }
    
        //初始化连接管理链表
        _list.init(maxAllConn, iIndex);
        
    }
    

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值