摘要??????????????????????????????????????????????????????????????????????????
|
本文主要介绍了LVS系 手段。主要介绍了3个比较
|
统采用2.4内核的NetFilter的功 重要的NetFilter钩子函数,最
|
能实现负载均衡的基本原理和技术 后描述了LVS的平衡算法
|
Internet的快速增 提供大量并发访问服务的能 瓶颈。由于单台服务器的性 此,必须采用多服务器和负 (Linux Virtual Servers,L 应快速增长的网络访问需求
|
长使多媒体网络服务器面对的访 力,因此对于大负载的服务器来 能总是有限的,简单的提高硬件 载均衡技术才能满足大量并发访 VS) 使用负载均衡技术将多台服 提供了一个负载能力易于扩展,
|
问数量快速增加,服务器需要具备 讲,CPU、I/O处理能力很快会成为 性能并不能真正解决这个问题。为 问的需要。Linux 虚拟服务器 务器组成一个虚拟服务器。它为适 而价格低廉的解决方案。
|
1.LVS结构与工作原理??????????????????????????????????????????????????????
|
LVS的结构如图1所 务器(Real Server,RS)群 透明的,用户只能看见一台 。
|
示,它由前端的负载均衡器(Loa 组成。RS间可通过局域网或广域 作为LB的虚拟服务器(Virtual S
|
d Balancer,LB)和后端的真实服 网连接。LVS的这种结构对用户是 erver),而看不到提供服务的RS群
|
如图1所示????????????????????????????????????????????????????????????????????
|
当用户的请求发往虚拟服务器, 请求转发给RS。RS再将用户请求结果返回 发策略有关。
|
LB根据设定的包转发策略和负载均衡调度算法将用户 给用户。同请求包一样,应答包的返回方式也与包转
|
LVS的包转发策略有三种:????????????????????????????????????????????????
|
NAT (Network Address Translation 务器的IP地址转换为某个选定RS的IP地址 IP转为虚拟服务器的IP地址,回送给用户
|
)模式。LB收到用户请求包后,LB将请求包中虚拟服 ,转发给RS;RS将应答包发给LB,LB将应答包中RS的 。
|
IP隧道 (IP Tunneling 给某个选定的RS;RS解出请 道协议。
|
)模式。LB收到用户请求包后, 求信息,直接将应答内容传给用
|
根据IP隧道协议封装该包,然后传 户。此时要求RS和LB都要支持IP隧
|
DR(Direct Routing)模式。LB收到请 的MAC地址后将包转发出去,RS收到请求 有RS都必须在一个物理段内,且LB与RS群
|
求包后,将请求包中目标MAC地址转换为某个选定RS 包后 ,可直接将应答内容传给用户。此时要求LB和所 共享一个虚拟IP。
|
2、IPVS软件结构与实现????????????????????????????????????????????????????
|
LVS软件的核心是 结构如图2所示,它主要由I 与真实服务器链表组成。
|
运行在LB上的IPVS,它使用基于 P包处理、负载均衡算法、系统
|
IP层的负载均衡方法。IPVS的总体 配置与管理三个模块及虚拟服务器
|
如图2所示????????????????????????????????????????????????????????????????????
|
2.1 LVS对 IP包的处理模式????????????????????????????????????????
|
IP包处理用Linux 过程如图所示:
|
2.4内核的Netfilter框架完成。
|
一个数据包通过Netfilter框架的
|
通俗的说,netfil HOOK),而在每个检测点上 用户自定义的功能)。
|
ter的架构就是在整个网络流程 上登记了一些处理函数进行处理
|
的若干位置放置了一些检测点( (如包过滤,NAT等,甚至可以是
|
IP层的五个HOOK点的位置如下图所示(copy from ) :????????
|
如图3所示????????????????????????????????????????????????????????????????????
|
NF_IP_PRE_ROUTING:刚刚进入网络 检测),源地址转换在此点进行;
|
层的数据包通过此点(刚刚进行完版本号,校验和等
|
NF_IP_LOCAL_IN:经路由查找后,送
|
往本机的通过此检查点,INPUT包过滤在此点进行;
|
NF_IP_FORWARD:要转
|
发的包通过此检测点,FORWORD包
|
过滤在此点进行;
|
NF_IP_LOCAL_OUT:本
|
机进程发出的包通过此检测点,
|
OUTPUT包过滤在此点进行;
|
NF_IP_POST_ROUTING:所有马上便要 址转换功能(包括地址伪装)在此点进行
|
通过网络设备出去的包通过此检测点,内置的目的地 。
|
在IP层代码中,有一些带有NF_HOOK宏的语句,如IP的转发函数中有:??
|
<-ipforward.c ip_forward()->
|
NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2,ip_forward_finish);
|
//其中NF_HOOK宏的定义基本如下:??????????????????????????????????????
|
<-/include/linux/netfilter.h->
|
#ifdef CONFIG_NETFILTER????????????????????????????????
|
#define NF_HOOK(pf,
|
hook, skb, indev, outdev, ok
|
fn)
|
(list_empty(&nf_hooks[(pf)][(hook)])??????
|
? (okfn)(skb)????????????????????????????????????????????????????
|
: nf_hook_slow((pf),
|
(hook), (skb), (indev), (ou
|
tdev), (okfn)))
|
#else /* !CONFIG_NETFILTER */????????????????????
|
#define NF_HOOK(pf, hook, skb, i
|
ndev, outdev, okfn) (okfn)(skb)
|
#endif /*CONFIG_NETFILTER*/ ??????????????????????
|
如果在编译内核时 行ip_forward_finish函数 这句话表达的可能比较含糊
|
没有配置netfilter时,就相当 ;否则进入HOOK点,执行通过nf ,实际是进入nf_hook_slow()
|
于调用最后一个参数,此例中即执 _register_hook()登记的功能( 函数,再由它执行登记的函数)。
|
NF_HOOK宏的参数分别为:????????????????????????????????????????????
|
pf:协议族名,netfilter架构同样 PF_INET6,PF_DECnet等名字。
|
可以用于IP层之外,因此这个变量还可以有诸如
|
hook:HOOK点的名字,对于IP层,就是取上面的五个值; ????????????????
|
skb:顾名思义 ????????????????????????????????????????????????????????????
|
indev:进来的设备,以struct net_device结构表示; ??????
|
outdev:出去的设备,以struct net_device结构表示; ????
|
okfn:是个函数指针,
|
当所有的该HOOK点的所有登记函
|
数调用完后,转而走此流程。
|
这些点是已经在内 或修改,而在此检测点进行 track这些功能,也是以这 善灵活的框架,为扩展功能
|
核中定义好的,除非你是这部分 的处理,则可由用户指定。像pa 种方式提供的。正如netfilter 提供方便。
|
内核代码的维护者,否则无权增加 cket filter,NAT,connection 的当初的设计目标--提供一个完
|
如果我们想加入自己的代码,便
|
要用nf_register_hook函数,其函数原型为:
|
int nf_register_hook
|
(struct nf_hook_ops *reg)
|
struct nf_hook_ops://结构????????????????????????????????
|
struct nf_hook_ops??????????????????????????????????????????
|
{????????????????????????????????????????????????????????????????????????????
|
struct list_head list;??????????????????????????????????
|
/* User fills in from here down. */????????
|
nf_hookfn *hook;??????????????????????????????????????????????
|
int pf;????????????????????????????????????????????????????????????????
|
int hooknum;??????????????????????????????????????????????????????
|
/* Hooks are ordered in ascendin
|
g priority. */
|
int priority;????????????????????????????????????????????????????
|
};??????????????????????????????????????????????????????????????????????????
|
其实,类似LVS的做法就是生成 nf_register_hook将其HOOK上。其中list pf总是PF_INET;hooknum就是HOOK点;一 先级,即priority的指定了。netfilter_ 先级:
|
一个struct nf_hook_ops结构的实例,并用 项要初始化为{NULL,NULL};由于一般在IP层工作, 个HOOK点可能挂多个处理函数,谁先谁后,便要看优 ipv4.h中用一个枚举类型指定了内置的处理函数的优
|
enum nf_ip_hook_priorities {??????????????????????
|
NF_IP_PRI_FIRST = INT_MIN,??????????????????????????
|
NF_IP_PRI_CONNTRACK = -200,????????????????????????
|
NF_IP_PRI_MANGLE = -150,??????????????????????????????
|
NF_IP_PRI_NAT_DST = -100,????????????????????????????
|
NF_IP_PRI_FILTER = 0,????????????????????????????????????
|
NF_IP_PRI_NAT_SRC = 100,??????????????????????????????
|
NF_IP_PRI_LAST = INT_MAX,????????????????????????????
|
};??????????????????????????????????????????????????????????????????????????
|
hook是提供的处理函数,也就是我们的主要工作,其原型为:????????????????
|
unsigned int nf_hook
|
fn(unsigned int hooknum,
|
struct sk_buff **skb,????????????????????????????????????
|
const struct net_device *in,??????????????????????
|
const struct net_device *out,????????????????????
|
int (*okfn)(struct sk_buff *));????????????????
|
它的五个参数将由NFHOOK宏传进去。????????????????????????????????????
|
以上是NetFillter 如何实现的。
|
编写自己模块时的一些基本用法
|
,接下来,我们来看一下LVS中是
|
3.LVS中Netfiler的实现????????????????????????????????????????????
|
利用Netfilter,LVS处理数据报 个钩子函数NF_IP_PRE_ROUTING[HOOK1]进 发还是发给本机;若该数据报是发被本机 处理后传递给上层协议;若该数据报应该 发的数据报经过最后一个钩子函数NF_IP_ 本地产生的数据经过钩子函数NF_IP_LOCA NF_IP_POST_ROUTING[HOOK4]处理后发送
|
从左边进入系统,进行IP校验以后,数据报经过第一 行处理;然后进行路由选择,决定该数据报是需要转 的,则该数据经过钩子函数NF_IP_LOCAL_IN[HOOK2] 被转发,则它被NF_IP_FORWARD[HOOK3]处理;经过转 POST_ROUTING[HOOK4]处理以后,再传输到网络上。 L_OUT[HOOK5]处理后,进行路由选择处理,然后经过 到网络上。
|
当启动IPVS加载ip_vs模块时, NF_IP_LOCAL_IN[HOOK2]、NF_IP_FORWARD 于处理进出的数据报。
|
模块的初始化函数ip_vs_init( )注册了 [HOOK3]、NF_IP_POST_ROUTING[HOOK4] 钩子函数用
|
3.1 NF_IP_LOCAL_IN处理过程??????????????????????????????????
|
用户向虚拟服务器 进行处理。如果传入的是ic tcp/udp数据报,如果不是t ;余下情况便是处理tcp/ud ,则函数返回NF_DROP(丢弃 表中查找是否存在这样的连 数据报中的相应信息一致。 tcp的sync报文或udp数据报 荷,则返回NF_DROP;如果 调度一个RS并创建一个新的 报。如果存在相应连接,首 NF_DROP。找到已存在的连 个数等。如果这个连接在创 则返回NF_ACCEPT。
|
发起请求,数据报经过NF_IP_LO mp数据报,则调用ip_vs_in_icm cp/udp数据报,则函数返回NF_A p数据报。首先,调用ip_vs_hea 该数据报)。接着,调用ip_vs_c 接:它的客户机和虚拟服务器的 如果不存在相应连接,则意味着 则查找相应的虚拟服务器;如果 相应虚拟服务器存在并且未满负 连接,如果调度失败则调用ip_v 先判断连接上的RS是否可用,如 接或建立新的连接后,修改系统 建时绑定了特定的数据报传输函
|
CAL_IN[HOOK2],进入ip_vs_in( ) p( );否则继续判断是否为 CCEPT(让内核继续处理该数据报) der_check( )检查报头,如果异常 onn_in_get( )去ip_vs_conn_tab ip地址和端口号以及协议类型均与 连接尚未建立,此时如果数据报为 相应虚拟服务器存在但是已经满负 荷,那么调用ip_vs_schedule( ) s_leave( )继续传递或者丢弃数据 果不可用则处理相关信息后返回 记录的相关信息如传入的数据报的 数,调用这个函数传输数据报,否
|
ip_vs_in()调用的 如果异常则返回NF_DROP。 闭或超时的icmp报文,其他 验和错误,直接返回NF_DRO 如果连接不存在,返回NF_A ip地址与端口号及ICMP数据 找路由调用ip_send( )发送
|
ip_vs_in_icmp( )处理icmp报文 函数只处理由tcp/udp报文传送 情况则让内核处理。针对上述三 P;否则,分析返回的icmp差错 CCEPT;如果连接存在,根据连 报包头的ip地址,并重新计算和 修改过的数据报,并返回NF_STO
|
。函数开始时检查数据报的长度, 错误引起的目的不可达、源端被关 类报文,首先检查检验和。如果检 信息,查找相应的连接是否存在。 接信息,依次修改差错信息包头的 修改各个包头中的检验和,之后查 LEN(退出数据报的处理过程)。
|
ip_vs_in()调用的 接。它将根据虚拟服务器绑 建立连接。ip_vs_conn_new 、协议超时信息,绑定appl ip_vs_conn_hash( )将这个 数,依据IPVS工作方式可分 )。例如ip_vs_nat_xmit( ) 算并设置检验和,调用ip_s
|
函数ip_vs_schedule( )为虚拟 定的调度算法分配一个RS,如果 ( )将进行一系列初始化操作: ication helper、RS和数据报传 连接插入哈希表ip_vs_conn_tab 为ip_vs_nat_xmit( )、ip_vs_t 的主要操作是:修改报文的目的 end( )发送修改后的数据报。
|
服务器调度可用的RS并建立相应连 成功,则调用ip_vs_conn_new( ) 设置连接的协议、ip地址、端口号 输函数,最后调用 中。一个连接绑定的数据报传输函 unnel_xmit( )、ip_vs_dr_xmit( 地址和目的端口为RS信息,重新计
|
3.2 NF_IP_FORWARD处理过程????????????????????????????????????
|
数据报进入NF_IP_ 下被调用。它首先判断数据 判断是否为tcp/udp数据报 理。首先,调用ip_vs_head ip_vs_conn_out_get( )判 ip_vs_lookup_real_servic 报文是tcp非复位报文或udp NF_STOLEN;其余情况下均 误则返回NF_DROP,如果正 为虚拟服务器端口号,重新
|
FORWARD后,将进入ip_vs_out( 报类型,如果为icmp数据报则直 ,如果不是这二者则返回NF_ACC er_check( )检查报头,如果异 断是否存在相应的连接。若不存 e( )去哈希表中查找发送数据报 报文,则调用icmp_send( )给R 返回NF_ACCEPT。若存在相应连 确,修改数据报,将源地址修改 计算并设置检验和,并返回NF_A
|
)进行处理。这个函数只在NAT方式 接调用ip_vs_out_icmp( );其次 EPT。余下就是tcp/udp数据报的处 常则返回NF_DROP。其次,调用 在相应连接:调用 的RS是否仍然存在,如果RS存在且 S发送目的不可达icmp报文并返回 接:检查数据报的检验和,如果错 为虚拟服务器ip地址,源端口修改 CCEPT。
|
ip_vs_out_icmp( ip报头的源地址和差错信息 udp或tcp报头的目的端口号
|
)的流程与ip_vs_in_icmp( )类 中udp或tcp报头的目的地址均修 修改为虚拟服务器的端口号。
|
似,只是修改数据报时有所区别: 改为虚拟服务器地址,差错信息中
|
3.3 NF_IP_POST_ROUTING处理过程??????????????????????????
|
NF_IP_POST_ROUTING钩子函数只 后,由ip_vs_post_routing( )进行处理。 NF_ACCEPT;否则立刻传输数据报,函数
|
在NAT方式下使用。数据报进入NF_IP_POST_ROUTING 它首先判断数据报是否经过IPVS,如果未经过则返回 返回NF_STOLEN,防止数据报被iptable的规则修改。
|
4.LVS系统配置与管理??????????????????????????????????????????????????????
|
IPVS模块初始化时 向IPVS内核模块传递ip_vs_ 器和RS地址的添加、修改、
|
注册了setsockopt/getsockopt( rule_user结构的系统配置数据 删除操作。系统通过这些操作完
|
),ipvsadm命令调用这两个函数 ,完成系统的配置,实现虚拟服务 成对虚拟服务器和RS链表的管理。
|
虚拟服务器的添加 务器哈希表添加一个新的节 器的修改由ip_vs_edit_ser 删除由ip_vs_del_service( 带的所有RS,并解除虚拟服
|
操作由ip_vs_add_service( )完 点,查找用户设定的调度算法并 vice( )完成,此函数修改指定 )完成,在删除一个虚拟服务器 务器所绑定的调度算法。
|
成,该函数根据哈希算法向虚拟服 将此算法绑定到该节点;虚拟服务 服务器的调度算法;虚拟服务器的 之前,必须先删除此虚拟服务器所
|
与之类似,RS的添加、修改、删 ip_vs_edit_dest( )和ip_vs_edit_serve
|
除操作分别由ip_vs_add_dest( )、 r( )完成。
|
4. 负载均衡调度算法????????????????????????????????????????????????????????
|
前面已经提到,用 _vs_bind_scheduler( )完 ip_vs_scheduler_get( )根 列中查找此调度算法,如果
|
户在添加一个虚拟服务时要绑定 成,调度算法的查找则由ip_vs_ 据调度算法的名字,调用ip_vs_ 没找到则加载相应调度算法模块
|
调度算法,这由ip scheduler_get( )完成。 sched_getbyname( )从调度算法队 再查找,最后返回查找结果。
|
目前系统有八种负载均衡调度算法,具体如下:????????????????????????????????????
|
rr:轮循调度(Round-Robin) 它将请 算法简单,但是只适合于RS处理性能相差
|
求依次分配不同的RS,也就是在RS中均摊请求。这种 不大的情况。
|
wrr:加权轮循调度(We 的RS将优先获得任务,并且 目的连接数。
|
ighted Round-Robin) 它将依据 分配到的连接数将比权值较低的
|
不同RS的权值分配任务。权值较高 RS更多。相同权值的RS得到相同数
|
dh:目的地址哈希调度 表来获得需要的RS。
|
(Destination Hashing) 以目
|
的地址为关键字查找一个静态hash
|
sh:源地址哈希调度(Source Hashin 要的RS。
|
g) 以源地址为关键字查找一个静态hash表来获得需
|
Lc:最小连接数调度(L 请求发送到当前连接数最小
|
east-Connection) IPVS表存储 的RS。
|
了所有的活动的连接。把新的连接
|
Wlc:加权最小连接数调度(Weighted I = 1..n),当前的TCP连接数依次为Ti 分配的RS。
|
Least-Connection) 假设各台RS的权值依次为Wi( (I=1..n),依次选取Ti/Wi为最小的RS作为下一个
|
Lblc:基于地址的最小连接数调度(L 地址的请求分配给同一台RS如果这台服务 为下一次分配的首先考虑。
|
ocality-Based Least-Connection) 将来自同一目的 器尚未满负荷,否则分配给连接数最小的RS,并以它
|
Lblcr:基于地址的带 Replication) 对于某一目 接数最小的RS;如果子集中 器,将它加入到此子集并分 载最大的节点从子集删除。
|
重复最小连接数调度(Locality- 的地址,对应有一个RS子集。对 所有的服务器均已满负荷,则从 配连接;若一定时间内,这个子
|
Based Least-Connection with 此地址的请求,为它分配子集中连 集群中选择一个连接数较小的服务 集未被做任何修改,则将子集中负 |
|