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