歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> LVS集群系統網絡核心原理分析

LVS集群系統網絡核心原理分析

日期:2017/2/27 9:28:28   编辑:更多Linux
  摘要  本文主要介紹了LVS系統采用2.4內核的NetFilter的功能實現負載均衡的基本原理和技術手段。主要介紹了3個比較重要的NetFilter鉤子函數,最後描述了LVS的平衡算法    Internet的快速增長使多媒體網絡服務器面對的訪問數量快速增加,服務器需要具備提供大量並發訪問服務的能力,因此對於大負載的服務器來講,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的包轉發策略有三種:    NAT (Network Address Translation)模式。LB收到用戶請求包後,LB將請求包中虛擬服務器的IP地址轉換為某個選定RS的IP地址,轉發給RS;RS將應答包發給LB,LB將應答包中RS的IP轉為虛擬服務器的IP地址,回送給用戶。   IP隧道 (IP Tunneling)模式。LB收到用戶請求包後,根據IP隧道協議封裝該包,然後傳給某個選定的RS;RS解出請求信息,直接將應答內容傳給用戶。此時要求RS和LB都要支持IP隧道協議。   DR(Direct Routing)模式。LB收到請求包後,將請求包中目標MAC地址轉換為某個選定RS的MAC地址後將包轉發出去,RS收到請求包後 ,可直接將應答內容傳給用戶。此時要求LB和所有RS都必須在一個物理段內,且LB與RS群共享一個虛擬IP。   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所示    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的轉發函數中有:        NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2,ip_forward_finish);  //其中NF_HOOK宏的定義基本如下:        #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宏的參數分別為:      pf:協議族名,netfilter架構同樣可以用於IP層之外,因此這個變量還可以有諸如PF_INET6,PF_DECnet等名字。   hook:HOOK點的名字,對於IP層,就是取上面的五個值;   skb:顧名思義   indev:進來的設備,以strUCt net_device結構表示;   outdev:出去的設備,以struct net_device結構表示;   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_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]處理以後,再傳輸到網絡上。本地產生的數據經過鉤子函數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。找到已存在的連接或建立新的連接後,修改系統記錄的相關信息如傳入的數據報的




Copyright © Linux教程網 All Rights Reserved