zoukankan      html  css  js  c++  java
  • ip_vs实现分析(9)

    本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
    msn: yfydz_no1@hotmail.com
    来源:http://yfydz.cublog.cn


    11. IPVS预估器

    IPVS预估器用的估算在一个短暂时间间隔内的连接率,可在用户空间开一个daemon定时读取预估器的值以实现较长时间的预估。
    预估算法为:
    取最后8秒钟内,每两秒取一个采样点进行平滑处理:
        avgrate = avgrate*(1-W) + rate*W
        其中 W = 2^(-2) = 0.25,速率单位是KBytes/s

    预估代码在net/ipv4/ipvs/ip_vs_est.c中实现。

    11.1 数据结构
    预估器结构定义如下:

    struct ip_vs_estimator
    {
    // 链表的下一项
     struct ip_vs_estimator *next;
    // IPVS统计
     struct ip_vs_stats *stats;
    // 上次的连接数
     u32   last_conns;
    // 上次的进入包数
     u32   last_inpkts;
    // 上次发出包数
     u32   last_outpkts;
    // 上次进入字节数
     u64   last_inbytes;
    // 上次发出字节数
     u64   last_outbytes;
    // 连接率
     u32   cps;
    // 进入的包数率
     u32   inpps;
    // 发出的包速率
     u32   outpps;
    // 进入的速率
     u32   inbps;
    // 发出的速率
     u32   outbps;
    };

    11.2 新建预估器

    int ip_vs_new_estimator(struct ip_vs_stats *stats)
    {
     struct ip_vs_estimator *est;
    // 分配空间
     est = kmalloc(sizeof(*est), GFP_KERNEL);
     if (est == NULL)
      return -ENOMEM;
     memset(est, 0, sizeof(*est));
    // 统计结构,包括IPVS服务,目的服务器等都有这个统计结构,预估器就是根据此统计值计算
     est->stats = stats;
    // 将当前统计结构中的值作为预估器中的参数初始值
     est->last_conns = stats->conns;
    // 连接率值扩大2^10
     est->cps = stats->cps<<10;
     est->last_inpkts = stats->inpkts;
    // 进入包速率值扩大2^10
     est->inpps = stats->inpps<<10;
     est->last_outpkts = stats->outpkts;
    // 发出包速率值扩大2^10
     est->outpps = stats->outpps<<10;
     est->last_inbytes = stats->inbytes;
    // 进入速率值扩大2^5
     est->inbps = stats->inbps<<5;
     est->last_outbytes = stats->outbytes;
    // 发出速率值扩大2^5
     est->outbps = stats->outbps<<5;
     write_lock_bh(&est_lock);
    // 将结构加入链表
     est->next = est_list;
     if (est->next == NULL) {
    // 初始化定时器,整个链表只有一个定时器
      init_timer(&est_timer);
    // 超时两秒
      est_timer.expires = jiffies + 2*HZ;
      est_timer.function = estimation_timer;
      add_timer(&est_timer);
     }
     est_list = est;
     write_unlock_bh(&est_lock);
     return 0;
    }
    // 定时函数,预估计算
    static void estimation_timer(unsigned long arg)
    {
     struct ip_vs_estimator *e;
     struct ip_vs_stats *s;
     u32 n_conns;
     u32 n_inpkts, n_outpkts;
     u64 n_inbytes, n_outbytes;
     u32 rate;
     read_lock(&est_lock);
    // 循环预估链表对所有预估器数据进行更新
     for (e = est_list; e; e = e->next) {
      s = e->stats;
      spin_lock(&s->lock);
    // 当前统计结构中的新数值
      n_conns = s->conns;
      n_inpkts = s->inpkts;
      n_outpkts = s->outpkts;
      n_inbytes = s->inbytes;
      n_outbytes = s->outbytes;
      /* scaled by 2^10, but divided 2 seconds */
    // 连接率计算
    // 1秒内的连接数之差,扩大2^10
      rate = (n_conns - e->last_conns)<<9;
    // 保存连接数
      e->last_conns = n_conns;
    // 预估器连接率变化
      e->cps += ((long)rate - (long)e->cps)>>2;
    // 统计结构的连接率变化
      s->cps = (e->cps+0x1FF)>>10;

    // 进入包率计算,方法和上面相同
      rate = (n_inpkts - e->last_inpkts)<<9;
      e->last_inpkts = n_inpkts;
      e->inpps += ((long)rate - (long)e->inpps)>>2;
      s->inpps = (e->inpps+0x1FF)>>10;

    // 发出包率计算,方法和上面相同
      rate = (n_outpkts - e->last_outpkts)<<9;
      e->last_outpkts = n_outpkts;
      e->outpps += ((long)rate - (long)e->outpps)>>2;
      s->outpps = (e->outpps+0x1FF)>>10;
    // 进入字节流量率计算,方法和上面相同
      rate = (n_inbytes - e->last_inbytes)<<4;
      e->last_inbytes = n_inbytes;
      e->inbps += ((long)rate - (long)e->inbps)>>2;
      s->inbps = (e->inbps+0xF)>>5;
    // 进入字节流量率计算,方法和上面相同
      rate = (n_outbytes - e->last_outbytes)<<4;
      e->last_outbytes = n_outbytes;
      e->outbps += ((long)rate - (long)e->outbps)>>2;
      s->outbps = (e->outbps+0xF)>>5;
      spin_unlock(&s->lock);
     }
     read_unlock(&est_lock);
     mod_timer(&est_timer, jiffies + 2*HZ);
    }

    11.3 删除预估器
    void ip_vs_kill_estimator(struct ip_vs_stats *stats)
    {
     struct ip_vs_estimator *est, **pest;
     int killed = 0;
     write_lock_bh(&est_lock);
    // 链表头
     pest = &est_list;
    // 循环根据参数提供的统计结构地址查找预估器
     while ((est=*pest) != NULL) {
    // 根据统计地址比对
      if (est->stats != stats) {
       pest = &est->next;
       continue;
      }
      *pest = est->next;
    // 直接释放预估器内存
      kfree(est);
      killed++;
     }
    // 预估链表为空后删除定时器
     if (killed && est_list == NULL)
      del_timer_sync(&est_timer);
     write_unlock_bh(&est_lock);
    }
     
    11.4 预估器统计值清零
    void ip_vs_zero_estimator(struct ip_vs_stats *stats)
    {
     struct ip_vs_estimator *e;
     write_lock_bh(&est_lock);
    // 循环根据参数提供的统计结构地址查找预估器
     for (e = est_list; e; e = e->next) {
      if (e->stats != stats)
       continue;
    // 将预估器参数值清空
      /* set counters zero */
      e->last_conns = 0;
      e->last_inpkts = 0;
      e->last_outpkts = 0;
      e->last_inbytes = 0;
      e->last_outbytes = 0;
      e->cps = 0;
      e->inpps = 0;
      e->outpps = 0;
      e->inbps = 0;
      e->outbps = 0;
     }
     write_unlock_bh(&est_lock);
    }
     
    12. IPVS的/proc参数
    IPVS在/proc目录下建立了以下文件:
    /proc/net:
     /proc/net/ip_vs:IPVS的规则表
     /proc/net/ip_vs_app:IPVS应用协议
     /proc/net/ip_vs_conn:IPVS当前连接
     /proc/net/ip_vs_stats:IPVS状态统计信息
    /proc/sys/net/ipv4/vs:
     /proc/sys/net/ipv4/vs/am_droprate:丢包率(缺省10)
     /proc/sys/net/ipv4/vs/amemthresh:可用内存阈值(缺省1024)
     /proc/sys/net/ipv4/vs/cache_bypass:是否建立旁路cache项
     /proc/sys/net/ipv4/vs/debug_level:调试级别
     /proc/sys/net/ipv4/vs/drop_entry:确定删除连接处理级别
     /proc/sys/net/ipv4/vs/drop_packet:丢包级别
     /proc/sys/net/ipv4/vs/expire_nodest_conn:是否删除没有目的服务器的连接
     /proc/sys/net/ipv4/vs/lblc_expiration:lblc算法的到期时间(缺省1天)
     /proc/sys/net/ipv4/vs/lblcr_expiration:lblcr算法的到期时间(缺省1天)
     /proc/sys/net/ipv4/vs/nat_icmp_send:NAT模式下连接异常时发送ICMP包
     /proc/sys/net/ipv4/vs/secure_tcp:更安全的TCP状态转换
     /proc/sys/net/ipv4/vs/sync_threshold:连接同步时的包数阈值数值
     /proc/sys/net/ipv4/vs/timeout_close:TCP sCL状态超时
     /proc/sys/net/ipv4/vs/timeout_closewait:TCP sCW状态超时
     /proc/sys/net/ipv4/vs/timeout_established:TCP sES状态超时
     /proc/sys/net/ipv4/vs/timeout_finwait:TCP sFW状态超时
     /proc/sys/net/ipv4/vs/timeout_icmp:ICMP超时
     /proc/sys/net/ipv4/vs/timeout_lastack:TCP sLA状态超时
     /proc/sys/net/ipv4/vs/timeout_listen:TCP sLI状态超时
     /proc/sys/net/ipv4/vs/timeout_synack:TCP sSA状态超时
     /proc/sys/net/ipv4/vs/timeout_synrecv:TCP sSR状态超时
     /proc/sys/net/ipv4/vs/timeout_synsent:TCP sSS状态超时
     /proc/sys/net/ipv4/vs/timeout_timewait:TCP sTW状态超时
     /proc/sys/net/ipv4/vs/timeout_udp:UDP超时
  • 相关阅读:
    简易sql拼接工具类(使用StringBuilder实现)
    缓存工具类(使用ConcurrentMap集合实现)
    properties文档读取工具类
    【Codeforces Round #655 (Div. 2)】A-D
    【2020 杭电多校第四场】Go Running 最小点覆盖
    【2020 杭电多校第四场】1002 Blow up the Enemy
    【2020 HDU 多校训练第三场 1007 Tokitsukaze and Rescue】暴力删边&最短路
    【2020杭电多校第二场】Total Eclipse 思维+并查集
    【2020HDU多校】Lead of Wisdom 暴力
    【CF-1371 C-E2】
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2587843.html
Copyright © 2011-2022 走看看