C++ webserver项目定时器详解

定时器处理非活动连接

===============

由于非活跃连接占用了连接资源,严重影响服务器的性能,通过实现一个服务器定时器,处理这种非活跃连接,释放连接资源。利用alarm函数周期性地触发SIGALRM信号,该信号的信号处理函数利用管道通知主循环执行定时器链表上的定时任务.

> * 统一事件源

> * 基于升序链表的定时器

> * 处理非活动连接

整个流程:

1、 alarm函数 5s会发送一个SIGALARM信号

2、 统一事件源:收到ALARM信号后 通过回调函数对信号进行处理 这里的处理是往管道内写数据

3、 epoll监听的时候 会检测管道读端事件, 当检测到管道有内容可读时, 会判断是哪种信号

4、 如果是SIGTERM信号(ctrl+c) 那么会将stop_server 置为1 表示要关闭服务器

但是这里注意 置为1后并没有立马关闭 而是会继续遍历其他发生改变的文件描述符 表示有其他用户的请求 会全部处理完之后才会在while循环条件里判断, while(!stop_server) 这个时候会终止循环 服务器运行结束

5、 如果是SIGALARM信号 会将timeout置为1 也同样会等其他事件检测完毕后 才会进行判断

因为处理非活跃连接不是紧急事件 不需要实时处理

6、 如果timeout为1  开始遍历定时器链表(依据超时事件升序排列)

如果某个节点没有超时 那么后续的也不用检测了 因为是升序的

如果超时了(判断依据就是当前时间是否小于超时时间 如果小于表示不超时 break后续不用检测 如果大于表示超时 需要移除 继续向后遍历)

例如 2点14检测 而某个节点是2点13终止时间 那么表示超时了

            某个节点是15min 表示没超时

那么把该节点对应的客户端资源释放(移除epoll监听 断开连接)

最后需要重新指定SIGALARM   alarm(m_TIMESLOT) 下一个5s往管道发送数据(实际执行的时候不一定是5s)

例如 30s 指定SIGALARM信号    35s会执行回调函数往管道写入

epoll监听到了该信号 但是会处理完所有连接后才会对信号进行处理 所以可能往后延迟

ps: 如果每次收到客户端的请求 需要相等的调整对应定时器在链表中的位置


 

//expire是超时时间!这个是在每个节点创建的时候实现的 依据是当前时间+3*timeshot(这里是设置5s)

//例如14min一个用户连接了 那么超时时间就是14min15s

//14min20s又一个用户连接 超时时间就是14min35s

//定时器链表是升序排列的 所以如果检测到某个没超时 那么后续的都不会超时 直接break就好

//每隔5s会触发一个SIGALARM信号,通过捕捉信号并调用回调函数 向管道内写入信号

//这个时候epoll也检测了管道事件,如果是SIGALARM信号,那么会对链表(定时器每个节点有客户端的文件描述符)进行遍历

//比如当前时间14min25s检测(第一个超时了(14min15s) 检测到第二个 发现第二个没超时(14min35) 那后续的也不用检测了)

你可能感兴趣的:(c++)