本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: 来源: 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超时