对IPVS来源分析持续性参数(也称为LVS)

核心提示:近日在LVS的LB,客户发现一个问题总是出现会话丢失的问题,采用常见的配置,利用WLC的均衡策略,看到WLC战略客户可能有不同的背景相同的旋转服务器机器上有背景,也不是。

最近在LVS的LB,客户发现一个问题总是出现会话丢失的问题,采用常见的配置,利用WLC的均衡策略,看到WLC战略客户可能有不同的背景机一样旋转,在后台服务器上而不是在会话复制,从而导致客户端访问不同的服务器这导致会话的损失。

这种简单的思想通过调整均衡策略可以保证同一服务器在同一个客户均衡策略(参考地图,点击打开链接),并且只有源散列调度策略似乎能够达到这个目标,但这不是一个推荐的策略和策略。

当你看ipvsadmin参数,你找到的参数P,
- p,--持久性{ }:设置一个持久连接,它允许从客户机发送多个请求发送到同一个真正的服务器

认为p参数与源散列调度策略有点类似,或者查看代码来解决问题。

IPVS也叫LVS

LVS是内核模块,代码可以直接在内核代码,内核中的名字是IPVS,我们称它为IPVS。

IPVS的代码将被安装在/网/防火墙/ IPVS,在这里我们可以看到,IPVS是基于Linux的Netfilter框架Netfilter框架的核心模块是整个网络流量的几个地点放置一些点检测(钩),并在每个测点上的一些处理功能的注册(如包过滤、NAT、甚至是用户自定义函数)。

Netfilter的实现

Netfilter的状态图:



和Ipvs注册钩子函数的几个州的Netfilter

静态结构nf_hook_ops ip_vs_ops __read_mostly = { { { }
过滤后的包转发包,
*或VS(更改目的地),以便过滤规则可以是
*适用于IPVS。* /
{
ip_vs_in钩=,
业主= this_module,
pf_inet PF =,
hooknum = nf_inet_local_in,
优先级= 100,
},
在数据包更改源之后*只对*
{
ip_vs_out钩=,
业主= this_module,
pf_inet PF =,
hooknum = nf_inet_forward,
优先级= 100,
},
在分组过滤(但在 / ip_vs_out_icmp),抓住ICMP
*注定为0.0.0.0 / 0,这是传入的IPVS连接。
{
ip_vs_forward_icmp钩=,
业主= this_module,
pf_inet PF =,
hooknum = nf_inet_forward,
优先级= 99,
},
Netfilter连接*跟踪* / post_routing退出之前
{
ip_vs_post_routing钩=,
业主= this_module,
pf_inet PF =,
hooknum = nf_inet_post_routing,
nf_ip_pri_nat_src-1优先=,
},
平衡策略主要实现对国家nf_inet_local_in相应的钩子函数ip_vs_in


在IPVS的2层结构

1。ip_vs_conn记录客户端的地址,由IPVS虚拟地址,对应的真实服务器的地址
2。ip_vs_protocol记录不同的钩子函数在不同的协议(TCP、UDP),比如什么类型的调度使用,哪些函数接受数据
结构ip_vs_protocol ip_vs_protocol_tcp = { {
TCP/IP
ipproto_tcp协议=,
num_states = ip_vs_tcp_s_last,
dont_defrag = 0,
appcnt = atomic_init(0),
ip_vs_tcp_init init =,
退出= ip_vs_tcp_exit,
register_app = tcp_register_app,
unregister_app = tcp_unregister_app,
conn_schedule = tcp_conn_schedule,
conn_in_get = tcp_conn_in_get,
conn_out_get = tcp_conn_out_get,
snat_handler = tcp_snat_handler,
dnat_handler = tcp_dnat_handler,
csum_check = tcp_csum_check,
state_name = tcp_state_name,
state_transition = tcp_state_transition,
app_conn_bind = tcp_app_conn_bind,
debug_packet = ip_vs_tcpudp_debug_packet,
timeout_change = tcp_timeout_change,
set_state_timeout = tcp_set_state_timeout,
};
这是一个ip_vs_protocol下TCP结构,最重要的是,conn_in_get功能也是静态的unsigned int叫钩子函数ip_vs_in。
ip_vs_in(unsigned int hooknum,结构sk_buff * skb,
const struct net_device *,const struct net_device *了,
Int(* OKFN)(结构sk_buff *))
{

PP = ip_vs_proto_get(IPH。协议);
如果(不可能)!PP))
返回nf_accept;

*
*检查数据包是否属于现有连接条目。
* /
CP = PP -> conn_in_get(AF,SKB,PP,IPH,iph.len,0);

}我们使用普通的网络为例,最后调用的函数tcp_conn_in_get

ip_vs_conn的全局数组和链表的c_list ip_vs_conn_tab

这是一个全球性的ip_vs_conn数组保存所有这一切都是相连的。哈希是由客户端的IP,端口计算,计算ip_vs_conn数组保存。

ip_vs_conn本身也节省了一c_list链表,这是一个链表结构来保存ip_vs_conn

初始化

当IPVS初始化,数组的大小初始化和大小是不变的(1<<12)4096

当客户端哈希计算相同,匹配的客户是通过遍历c_list链内的ip_vs_conn发现(相同的地址和端口)

如果相应的ip_vs_conn没有发现,正是在这个时候叫

如果(!PP -> conn_schedule(AF,SKB,PP,V,CP))
返回v;和conn_schedule TCP钩子函数是tcp_conn_schedule,核心功能的调度算法,我们前面提到的


静态变量
tcp_conn_schedule(int AF,结构sk_buff * skb,结构ip_vs_protocol * PP,
int *决,结构ip_vs_conn ** CPP)
{
结构ip_vs_service * SVC;
结构tcphdr _tcph,*号;
结构ip_vs_iphdr IPH;

ip_vs_fill_iphdr(AF,skb_network_header(SKB),IPH);

= skb_header_pointer(SKB,iph.len,sizeof(_tcph),_tcph);
如果(= NULL){
*判决= nf_drop;
返回0;
}

如果(SYN)
(SVC = ip_vs_service_get(AF,SKB ->标记,iph.protocol,iph.daddr,
TH -> DEST)){
如果(ip_vs_todrop()){
*
*看来我们很有钱。
*我们必须把这个包裹寄走:
* /
ip_vs_service_put(SVC);
*判决= nf_drop;
返回0;
}

*
*让虚拟服务器选择一个真正的服务器
*传入连接,并创建连接条目。
* /
* CPP = ip_vs_schedule(SVC,SKB); / /电话ip_vs_schedule
如果(!* CPP){
*判决= ip_vs_leave(SVC,SKB,PP);
返回0;
}
ip_vs_service_put(SVC);
}
返回1;
}
功能ip_vs_schedule


结构ip_vs_conn *
ip_vs_schedule(struct ip_vs_service * SVC,const struct sk_buff * skb)
{

*
*服务持续性
* /
如果(SVC ->旗帜ip_vs_svc_f_persistent)
返回ip_vs_sched_persist(SVC,SKB,PPTR);

*
*非持久服务
* /
如果(!SVC -> fwmark PPTR { 1 }!=端口> {
如果(!SVC端口>
pr_err(时间表:端口0只支持
在持久服务中
检查你的IPVS配置;
返回null;
}
的…
返回CP;
我们看到ip_vs_svc_f_persistent },即参数的持久性


参数持久化的实现

创建一个ip_vs_conn模板

为了确保在同一时间内将同一客户机IP连接到原始服务器,则意味着将原始客户端IP的原始连接保留到真正的服务器。

在IPVS,没有其他的阵列产生的保存状态,但ip_vs_conn模板介绍。的ip_vs_conn模板仍保持在全局表中提到的ip_vs_conn_tab。

模板和常见的ip_vs_conn之间的区别是什么,因为它是保存在相同的全局表吗这很简单。只需设置客户端的端口0和节省IP从真实服务器的ip_vs_conn。

具体的参考作用:ip_vs_sched_persist

当清除ip_vs_conn模板

p参数有指定的时间。有一个在ip_vs_conn结构定时器超时时间。当函数是新连接,定时器的执行功能ip_vs_conn_expire设置。

结构ip_vs_conn *
ip_vs_conn_new(int,int const AF,原,工会nf_inet_addr * caddr,__be16 cport,
const联盟nf_inet_addr * vaddr,__be16新版vPort,
const联盟nf_inet_addr * daddr,__be16运动,符号标志,
结构ip_vs_dest * dest)
{
......
setup_timer(CP ->定时器,ip_vs_conn_expire,(长整型)CP);
......
返回CP;
}

从功能ip_vs_conn_expire ip_vs_conn_tab删除ip_vs_conn超时模板

在ip_vs_sched_persist功能,创建一个新的连接时,也更新的触发时间ip_vs_conn模板定时器(当前时间- P参数超时时间),实现的功能ip_vs_conn_put。


完整的流程图







IPVS的调试日志

配置中的参数需要从新编译的内核中设置。
config_ip_vs_debug = Y
编译后,参数也进行了修改。
/过程/系统/网络/ / / debug_level IPv4
设置为12,日志打印dmesg


在IPVS ip_vs_conn_tab入门

内容可以通过/proc / / ip_vs_conn_entries访问网