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群。
當用戶的請求發往虛擬服務器,LB根據設定的包轉發策略和負載均衡調度算法將用戶請求轉發給RS。RS再將用戶請求結果返回給用戶。同請求包一樣,應答包的返回方式也與包轉發策略有關。
LVS的包轉發策略有三種:
2、IPVS軟件結構與實現
LVS軟件的核心是運行在LB上的IPVS,它使用基於IP層的負載均衡方法。IPVS的總體結構如圖2所示,它主要由IP包處理、負載均衡算法、系統配置與管理三個模塊及虛擬服務器與真實服務器鏈表組成。
2.1 LVS對 IP包的處理模式
IP包處理用Linux 2.4內核的Netfilter框架完成。一個數據包通過Netfilter框架的過程如圖所示:
通俗的說,netfilter的架構就是在整個網絡流程的若干位置放置了一些檢測點(HOOK),而在每個檢測點上上登記了一些處理函數進行處理(如包過濾,NAT等,甚至可以是用戶自定義的功能)。
IP層的五個HOOK點的位置如下圖所示(copy from
在IP層代碼中,有一些帶有NF_HOOK宏的語句,如IP的轉發函數中有:
clearcase/" target="_blank" >cccccc border=1>
<-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, 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宏的參數分別為:
這些點是已經在內核中定義好的,除非你是這部分內核代碼的維護者,否則無權增加或修改,而在此檢測點進行的處理,則可由用戶指定。像 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_INET;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]處理以後,再傳輸到網絡上。本http://edu.itbulo.com/show/house/'>地產生的數據