选择显示字体大小

lvs集群系统网络核心原理分析

inte.net的快速增长使多媒体网络服务器面对的访问数量快速增加,服务器需要具备提供大量并发访问服务的能力,因此对于大负载的服务器来讲,cpu、i/o处理能力很快会成为瓶颈。由于单台服务器的性能总是有限的,简单的提高硬件性能并不能真正解决这个问题。为此,必须采用多服务器和负载均衡技术才能满足大量并发访问的需要。linux 虚拟服务器(linux virtual servers,lvs) 使用负载均衡技术将多台服务器组成一个虚拟服务器。它为适应快速增长的网络访问需求提供了一个负载能力易于扩展,而价格低廉的解决方案。

1.lvs结构与工作原理

lvs的结构如图1所示,它由前端的负载均衡器(load balancer,lb)和后端的真实服务器(real server,rs)群组成。rs间可通过局域网或广域网连接。lvs的这种结构对用户是透明的,用户只能看见一台作为lb的虚拟服务器(virtual server),而看不到提供服务的rs群。

如图1所示

当用户的请求发往虚拟服务器,lb根据设定的包转发策略和负载均衡调度算法将用户请求转发给rs。rs再将用户请求结果返回给用户。同请求包一样,应答包的返回方式也与包转发策略有关。

lvs的包转发策略有三种:

2、ipvs软件结构与实现

lvs软件的核心是运行在lb上的ipvs,它使用基于ip层的负载均衡方法。ipvs的总体结构如图2所示,它主要由ip包处理、负载均衡算法、系统配置与管理三个模块及虚拟服务器与真实服务器链表组成。

如图2所示

2.1 lvs对 ip包的处理模式

ip包处理用linux 2.4内核.netfilter框架完成。一个数据包通.netfilter框架的过程如图所示:

通俗的说.netfilter的架构就是在整个网络流程的若干位置放置了一些检测点(hook),而在每个检测点上上登记了一些处理函数进行处理(如包过滤,nat等,甚至可以是用户自定义的功能)。

ip层的五个hook点的位置如下图所示(copy from ) :

如图3所示

  1. nf_ip_pre_routing:刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验和等检测),源地址转换在此点进行;
  2. nf_ip_local_in:经路由查找后,送往本机的通过此检查点,input包过滤在此点进行;
  3. nf_ip_forward:要转发的包通过此检测点,forword包过滤在此点进行;
  4. nf_ip_local_out:本机进程发出的包通过此检测点,output包过滤在此点进行;
  5. nf_ip_post_routing:所有马上便要通过网络设备出去的包通过此检测点,内置的目的地址转换功能(包括地址伪装)在此点进行。

在ip层代码中,有一些带有nf_hook宏的语句,如ip的转发函数中有:

<-ipforward.c ip_forward()->  nf_hook(pf_.net, 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, okfn)(list_empty(&nf_hooks[(pf)][(hook)])? (okfn)(skb): nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn)))#else /* !config.netfilter */#define nf_hook(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)#endif /*config.netfilter*/ 

如果在编译内核时没有配.netfilter时,就相当于调用最后一个参数,此例中即执行ip_forward_finish函数;否则进入 hook点,执行通过nf_register_hook()登记的功能(这句话表达的可能比较含糊,实际是进入nf_hook_slow()函数,再由它执行登记的函数)。

nf_hook宏的参数分别为:

  1. pf:协议族名.netfilter架构同样可以用于ip层之外,因此这个变量还可以有诸如pf_.net6,pf_de.net等名字。
  2. hook:hook点的名字,对于ip层,就是取上面的五个值;
  3. skb:顾名思义
  4. indev:进来的设备,以struct.net_device结构表示;
  5. outdev:出去的设备,以struct.net_device结构表示;
  6. okfn:是个函数指针,当所有的该hook点的所有登记函数调用完后,转而走此流程。

这些点是已经在内核中定义好的,除非你是这部分内核代码的维护者,否则无权增加或修改,而在此检测点进行的处理,则可由用户指定。像 packet filter,nat,connection track这些功能,也是以这种方式提供的。正.netfilter的当初的设计目标--提供一个完善灵活的框架,为扩展功能提供方便。

如果我们想加入自己的代码,便要用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 ascending priority. */int priority;};

其实,类似lvs的做法就是生成一个struct nf_hook_ops结构的实例,并用nf_register_hook将其hook上。其中list项要初始化为{null,null};由于一般在 ip层工作,pf总是pf_.net;hooknum就是hook点;一个hook点可能挂多个处理函数,谁先谁后,便要看优先级,即priority的指定了.netfilter_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_hookfn(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处理数据报从左边进入系统,进行ip校验以后,数据报经过第一个钩子函数nf_ip_pre_routing [hook1]进行处理;然后进行路由选择,决定该数据报是需要转发还是发给本机;若该数据报是发被本机的,则该数据经过钩子函数 nf_ip_local_in[hook2]处理后传递给上层协议;若该数据报应该被转发,则它被nf_ip_forward[hook3]处理;经过转发的数据报经过最后一个钩子函数nf_ip_post_routing[hook4]处理以后,再传输到网络上。本地产生的数据经过钩子函数 nf_ip_local_out[hook5]处理后,进行路由选择处理,然后经过nf_ip_post_routing[hook4]处理后发送到网络上。

当启动ipvs加载ip_vs模块时,模块的初始化函数ip_vs_init( )注册了nf_ip_local_in[hook2]、nf_ip_forward[hook3]、nf_ip_post_routing[hook4] 钩子函数用于处理进出的数据报。

3.1 nf_ip_local_in处理过程

用户向虚拟服务器发起请求,数据报经过nf_ip_local_in[hook2],进入ip_vs_in( )进行处理。如果传入的是icmp数据报,则调用ip_vs_in_icmp( );否则继续判断是否为tcp/udp数据报,如果不是tcp/udp数据报,则函数返回nf_accept(让内核继续处理该数据报);余下情况便是处理tcp/udp数据报。首先,调用ip_vs_header_check( )检查报头,如果异常,则函数返回nf_drop(丢弃该数据报)。接着,调用ip_vs_conn_in_get( )去ip_vs_conn_tab表中查找是否存在这样的连接:它的客户机和虚拟服务器的ip地址和端口号以及协议类型均与数据报中的相应信息一致。如果不存在相应连接,则意味着连接尚未建立,此时如果数据报为tcp的sync报文或udp数据报则查找相应的虚拟服务器;如果相应虚拟服务器存在但是已经满负荷,则返回nf_drop;如果相应虚拟服务器存在并且未满负荷,那么调用ip_vs_schedule( )调度一个rs并创建一个新的连接,如果调度失败则调用ip_vs_leave( )继续传递或者丢弃数据报。如果存在相应连接,首先判断连接上的rs是否可用,如果不可用则处理相关信息后返回nf_drop。找到已存在的连接或建立新的连接后,修改系统记录的相关信息如传入的数据报的个数等。如果这个连接在创建时绑定了特定的数据报传输函数,调用这个函数传输数据报,否则返回 nf_accept。

ip_vs_in()调用的ip_vs_in_icmp( )处理icmp报文。函数开始时检查数据报的长度,如果异常则返回nf_drop。函数只处理由tcp/udp报文传送错误引起的目的不可达、源端被关闭或超时的icmp报文,其他情况则让内核处理。针对上述三类报文,首先检查检验和。如果检验和错误,直接返回nf_drop;否则,分析返回的icmp差错信息,查找相应的连接是否存在。如果连接不存在,返回nf_accept;如果连接存在,根据连接信息,依次修改差错信息包头的ip地址与端口号及 icmp数据报包头的ip地址,并重新计算和修改各个包头中的检验和,之后查找路由调用ip_send( )发送修改过的数据报,并返回nf_stolen(退出数据报的处理过程)。

ip_vs_in()调用的函数ip_vs_schedule( )为虚拟服务器调度可用的rs并建立相应连接。它将根据虚拟服务器绑定的调度算法分配一个rs,如果成功,则调用ip_vs_conn_new( )建立连接。ip_vs_conn_new( )将进行一系列初始化操作:设置连接的协议、ip地址、端口号、协议超时信息,绑定application helper、rs和数据报传输函数,最后调用ip_vs_conn_hash( )将这个连接插入哈希表ip_vs_conn_tab中。一个连接绑定的数据报传输函数,依据ipvs工作方式可分为ip_vs_nat_xmit( )、ip_vs_tunnel_xmit( )、ip_vs_dr_xmit( )。例如ip_vs_nat_xmit( )的主要操作是:修改报文的目的地址和目的端口为rs信息,重新计算并设置检验和,调用ip_send( )发送修改后的数据报。

3.2 nf_ip_forward处理过程

数据报进入nf_ip_forward后,将进入ip_vs_out( )进行处理。这个函数只在nat方式下被调用。它首先判断数据报类型,如果为icmp数据报则直接调用ip_vs_out_icmp( );其次判断是否为tcp/udp数据报,如果不是这二者则返回nf_accept。余下就是tcp/udp数据报的处理。首先,调用 ip_vs_header_check( )检查报头,如果异常则返回nf_drop。其次,调用ip_vs_conn_out_get( )判断是否存在相应的连接。若不存在相应连接:调用ip_vs_lookup_real_service( )去哈希表中查找发送数据报的rs是否仍然存在,如果rs存在且报文是tcp非复位报文或udp 报文,则调用icmp_send( )给rs发送目的不可达icmp报文并返回nf_stolen;其余情况下均返回nf_accept。若存在相应连接:检查数据报的检验和,如果错误则返回nf_drop,如果正确,修改数据报,将源地址修改为虚拟服务器ip地址,源端口修改为虚拟服务器端口号,重新计算并设置检验和,并返回 nf_accept。

ip_vs_out_icmp( )的流程与ip_vs_in_icmp( )类似,只是修改数据报时有所区别:ip报头的源地址和差错信息中udp或tcp报头的目的地址均修改为虚拟服务器地址,差错信息中udp或tcp报头的目的端口号修改为虚拟服务器的端口号。

3.3 nf_ip_post_routing处理过程

nf_ip_post_routing钩子函数只在nat方式下使用。数据报进入nf_ip_post_routing后,由 ip_vs_post_routing( )进行处理。它首先判断数据报是否经过ipvs,如果未经过则返回nf_accept;否则立刻传输数据报,函数返回nf_stolen,防止数据报被 iptable的规则修改。

4.lvs系统配置与管理

ipvs模块初始化时注册了setsockopt/getsockopt( ),ipvsadm命令调用这两个函数向ipvs内核模块传递ip_vs_rule_user结构的系统配置数据,完成系统的配置,实现虚拟服务器和rs 地址的添加、修改、删除操作。系统通过这些操作完成对虚拟服务器和rs链表的管理。

虚拟服务器的添加操作由ip_vs_add_service( )完成,该函数根据哈希算法向虚拟服务器哈希表添加一个新的节点,查找用户设定的调度算法并将此算法绑定到该节点;虚拟服务器的修改由 ip_vs_edit_service( )完成,此函数修改指定服务器的调度算法;虚拟服务器的删除由ip_vs_del_service( )完成,在删除一个虚拟服务器之前,必须先删除此虚拟服务器所带的所有rs,并解除虚拟服务器所绑定的调度算法。

与之类似,rs的添加、修改、删除操作分别由ip_vs_add_dest( )、ip_vs_edit_dest( )和ip_vs_edit_server( )完成。

4. 负载均衡调度算法

前面已经提到,用户在添加一个虚拟服务时要绑定调度算法,这由ip_vs_bind_scheduler( )完成,调度算法的查找则由ip_vs_scheduler_get( )完成。ip_vs_scheduler_get( )根据调度算法的名字,调用ip_vs_sched_getbyname( )从调度算法队列中查找此调度算法,如果没找到则加载相应调度算法模块再查找,最后返回查找结果。

目前系统有八种负载均衡调度算法,具体如下:



  


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons