天天看點

基于LVS對LAMP做負載均衡叢集

一、簡介

   LVS是Linux Virtual Server的簡稱,也就是Linux虛拟伺服器, 是一個由章文嵩博士發起的自由軟體項目,它的官方站點是www.linuxvirtualserver.org。現在LVS已經是 Linux标準核心的一部分,在Linux2.4核心以前,使用LVS時必須要重新編譯核心以支援LVS功能子產品,但是從Linux2.4核心以後,已經完全内置了LVS的各個功能子產品,無需給核心打任何更新檔,可以直接使用LVS提供的各種功能。

   使用LVS技術要達到的目标是:通過LVS提供的負載均衡技術和Linux作業系統實作一個高性能、高可用的伺服器群集,它具有良好可靠性、可擴充性和可操作性。進而以低廉的成本實作最優的服務性能。

   LVS自從1998年開始,發展到現在已經是一個比較成熟的技術項目了。可以利用LVS技術實作高可伸縮的、高可用的網絡服務,例如WWW服務、Cache服務、DNS服務、FTP服務、MAIL服務、視訊/音頻點播服務等等,有許多比較著名網站群組織都在使用LVS架設的叢集系統,例如:Linux的門戶網站(www.linux.com)、向RealPlayer提供音頻視訊服務而聞名的Real公司(www.real.com)、全球最大的開源網站(sourceforge.net)等。

二、拓撲圖

<a href="http://s3.51cto.com/wyfs02/M02/24/3D/wKiom1NNM8HDW5YMAACXkLGNMeI888.jpg" target="_blank"></a>

   說明:1.用戶端隻知道我們的LVS的VIP的位址

         2.由于伺服器有限,此處我們的apache和php做在一台機器上

三。排程算法

   Director在接收到來自于Client的請求時,會基于"schedule"從RealServer中選擇一個響應給Client。ipvs支援以下排程算法:

   1、輪詢(round robin, rr),權重輪詢(Weighted round robin, wrr)——新的連接配接請求被輪流配置設定至各RealServer;算法的優點是其簡潔性,它無需記錄目前所有連接配接的狀态,是以它是一種無狀态排程。輪叫排程算法假設所有伺服器處理性能均相同,不管伺服器的目前連接配接數和響應速度。該算法相對簡單,不适用于伺服器組中處理性能不一的情況,而且當請求服務時間變化比較大時,輪叫排程算法容易導緻伺服器間的負載不平衡。

   2、最少連接配接(least connected, lc), 權重最少連接配接(weighted least connection, wlc)——新的連接配接請求将被配置設定至目前連接配接數最少的RealServer;最小連接配接排程是一種動态排程算法,它通過伺服器目前所活躍的連接配接數來估計伺服器的負載情況。排程器需要記錄各個伺服器已建立連接配接的數目,當一個請求被排程到某台伺服器,其連接配接數加1;當連接配接中止或逾時,其連接配接數減一。

   3、基于局部性的最少連結排程(Locality-Based Least Connections Scheduling,lblc)——針對請求封包的目标IP位址的負載均衡排程,目前主要用于Cache叢集系統,因為在Cache叢集中客戶請求封包的目标IP位址是變化的。這裡假設任何後端伺服器都可以處理任一請求,算法的設計目标是在伺服器的負載基本平衡情況下,将相同目标IP位址的請求排程到同一台伺服器,來提高各台伺服器的通路局部性和主存Cache命中率,進而整個叢集系統的處理能力。LBLC排程算法先根據請求的目标IP位址找出該目标IP位址最近使用的伺服器,若該伺服器是可用的且沒有超載,将請求發送到該伺服器;若伺服器不存在,或者該伺服器超載且有伺服器處于其一半的工作負載,則用“最少連結”的原則選出一個可用的伺服器,将請求發送到該伺服器。

   4、帶複制的基于局部性最少連結排程(Locality-Based Least Connections with Replication Scheduling,lblcr)——也是針對目标IP位址的負載均衡,目前主要用于Cache叢集系統。它與LBLC算法的不同之處是它要維護從一個目标IP位址到一組伺服器的映射,而 LBLC算法維護從一個目标IP位址到一台伺服器的映射。對于一個“熱門”站點的服務請求,一台Cache 伺服器可能會忙不過來處理這些請求。這時,LBLC排程算法會從所有的Cache伺服器中按“最小連接配接”原則選出一台Cache伺服器,映射該“熱門”站點到這台Cache伺服器,很快這台Cache伺服器也會超載,就會重複上述過程選出新的Cache伺服器。這樣,可能會導緻該“熱門”站點的映像會出現在所有的Cache伺服器上,降低了Cache伺服器的使用效率。LBLCR排程算法将“熱門”站點映射到一組Cache伺服器(伺服器集合),當該“熱門”站點的請求負載增加時,會增加集合裡的Cache伺服器,來處理不斷增長的負載;當該“熱門”站點的請求負載降低時,會減少集合裡的Cache伺服器數目。這樣,該“熱門”站點的映像不太可能出現在所有的Cache伺服器上,進而提供Cache叢集系統的使用效率。LBLCR算法先根據請求的目标IP位址找出該目标IP位址對應的伺服器組;按“最小連接配接”原則從該伺服器組中選出一台伺服器,若伺服器沒有超載,将請求發送到該伺服器;若伺服器超載;則按“最小連接配接”原則從整個叢集中選出一台伺服器,将該伺服器加入到伺服器組中,将請求發送到該伺服器。同時,當該伺服器組有一段時間沒有被修改,将最忙的伺服器從伺服器組中删除,以降低複制的程度。

   5、目标位址散列排程(Destination Hashing,dh)算法也是針對目标IP位址的負載均衡,但它是一種靜态映射算法,通過一個散列(Hash)函數将一個目标IP位址映射到一台伺服器。目标位址散列排程算法先根據請求的目标IP位址,作為散列鍵(Hash Key)從靜态配置設定的散清單找出對應的伺服器,若該伺服器是可用的且未超載,将請求發送到該伺服器,否則傳回空。

   6、源位址散列排程(Source Hashing,sh)算法正好與目标位址散列排程算法相反,它根據請求的源IP位址,作為散列鍵(Hash Key)從靜态配置設定的散清單找出對應的伺服器,若該伺服器是可用的且未超載,将請求發送到該伺服器,否則傳回空。它采用的散列函數與目标位址散列排程算法的相同。除了将請求的目标IP位址換成請求的源IP位址外,它的算法流程與目标位址散列排程算法的基本相似。在實際應用中,源位址散列排程和目标位址散列排程可以結合使用在防火牆叢集中,它們可以保證整個系統的唯一出入口。

四、實作步驟

   1.網絡規劃

用途

ip位址

版本号

系統版本号

叢集伺服器

192.168.1.202

ipvsadm1.26

centos6.5

apache+php1

192.168.1.201

apache2.4.9

php5.4.26

apache+php2

192.168.1.100

資料庫

192.168.1.200

MariaDB10.0.10

對外提供服務的ip位址

192.168.1.230

   2.本處的apache、php、MariaDB都為編譯安裝

     關于編譯安裝的操作,請移步本人的相關部落格http://wangfeng7399.blog.51cto.com/3518031/1381688,本處就不再做累贅

       特别說明,如果是編譯安裝的話應該在httpd的配置檔案中添加KeepAlive Off用來關閉httpd的會話保持

   3.叢集配置方法

     ①、前段LVS叢集伺服器的配置      

1

2

3

4

<code>在eth0:</code><code>0</code><code>上設定對外提供的位址</code>

<code>[root@localhost ~]# ifconfig eth0:</code><code>0</code> <code>192.168</code><code>.</code><code>1.230</code><code>/</code><code>24</code> <code>netmask </code><code>255.255</code><code>.</code><code>255.255</code> <code>broadcast </code><code>192.168</code><code>.</code><code>1.230</code> <code>up</code>

<code>設定路由</code>

<code>[root@localhost ~]# route add -host </code><code>192.168</code><code>.</code><code>1.230</code> <code>dev eth0:</code><code>0</code>

     ②、背景兩個Real Server伺服器的配置

5

6

7

8

<code>設定網卡隻對有eth0網卡上的ip位址做通告</code>

<code>[root@httpweb ~]# echo </code><code>1</code> <code>&gt; /proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>[root@httpweb ~]# echo </code><code>1</code> <code>&gt; /proc/sys/net/ipv4/conf/eth0/arp_ignore</code>

<code>[root@httpweb ~]# echo </code><code>2</code> <code>&gt; /proc/sys/net/ipv4/conf/eth0/arp_announce</code>

<code>[root@httpweb ~]# echo </code><code>2</code> <code>&gt; /proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>在lo上設定叢集服務的ip位址</code>

<code>[root@httpweb ~]# ifconfig lo:</code><code>0</code> <code>192.168</code><code>.</code><code>1.230</code> <code>netmask </code><code>255.255</code><code>.</code><code>255.255</code> <code>broadcast </code><code>192.168</code><code>.</code><code>1.230</code> <code>up</code>

<code>[root@httpweb ~]# route add -host </code><code>192</code><code>.l68.</code><code>1.230</code> <code>dev lo:</code><code>0</code>

     ③、兩台服務的配置均為一樣

     ④、設定叢集服務

<code>[root@localhost ~]# ipvsadm -A -t </code><code>192.168</code><code>.</code><code>1.230</code><code>:</code><code>80</code> <code>-s rr</code>

<code>[root@localhost ~]# ipvsadm -a -t </code><code>192.168</code><code>.</code><code>1.230</code><code>:</code><code>80</code> <code>-r </code><code>192.168</code><code>.</code><code>1.100</code> <code>-g</code>

<code>[root@localhost ~]# ipvsadm -a -t </code><code>192.168</code><code>.</code><code>1.230</code><code>:</code><code>80</code> <code>-r </code><code>192.168</code><code>.</code><code>1.201</code> <code>-g</code>

     ⑤、測試

<code>[root@localhost ~]# ipvsadm -L -n</code>

<code>IP Virtual Server version </code><code>1.2</code><code>.</code><code>1</code> <code>(size=</code><code>4096</code><code>)</code>

<code>Prot LocalAddress:Port Scheduler Flags</code>

<code>  </code><code>-&gt; RemoteAddress:Port           Forward Weight ActiveConn InActConn</code>

<code>TCP  </code><code>192.168</code><code>.</code><code>1.230</code><code>:</code><code>80</code> <code>rr</code>

<code>  </code><code>-&gt; </code><code>192.168</code><code>.</code><code>1.100</code><code>:</code><code>80</code>             <code>Route   </code><code>1</code>      <code>0</code>          <code>0</code>  

<code>  </code><code>-&gt; </code><code>192.168</code><code>.</code><code>1.201</code><code>:</code><code>80</code>             <code>Route   </code><code>1</code>      <code>0</code>          <code>0</code>

     我們會看到我們為兩個伺服器單獨書寫的網頁

<a href="http://s3.51cto.com/wyfs02/M01/24/51/wKioL1NOTROT5CJlAADikoUcpEE190.jpg" target="_blank"></a>

<a href="http://s3.51cto.com/wyfs02/M01/24/68/wKioL1NOdOKT5_GiAAEGCSPhYt4941.jpg" target="_blank"></a>

提供Director服務腳本

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

<code>Director腳本:</code>

<code>#!/bin/bash</code>

<code>#</code>

<code># LVS script </code><code>for</code> <code>VS/DR</code>

<code>. /etc/rc.d/init.d/functions</code>

<code>VIP=</code><code>192.168</code><code>.</code><code>0.210</code>

<code>RIP1=</code><code>192.168</code><code>.</code><code>0.221</code>

<code>RIP2=</code><code>192.168</code><code>.</code><code>0.222</code>

<code>PORT=</code><code>80</code>

<code>case</code> <code>"$1"</code> <code>in</code>

<code>start)       </code>

<code>  </code><code>/sbin/ifconfig eth0:</code><code>1</code> <code>$VIP broadcast $VIP netmask </code><code>255.255</code><code>.</code><code>255.255</code> <code>up</code>

<code>  </code><code>/sbin/route add -host $VIP dev eth0:</code><code>1</code>

<code># Since </code><code>this</code> <code>is</code> <code>the Director we must be able to forward packets</code>

<code>  </code><code>echo </code><code>1</code> <code>&gt; /proc/sys/net/ipv4/ip_forward</code>

<code># Clear all iptables rules.</code>

<code>  </code><code>/sbin/iptables -F</code>

<code># Reset iptables counters.</code>

<code>  </code><code>/sbin/iptables -Z</code>

<code># Clear all ipvsadm rules/services.</code>

<code>  </code><code>/sbin/ipvsadm -C</code>

<code># Add an IP virtual service </code><code>for</code> <code>VIP </code><code>192.168</code><code>.</code><code>0.219</code> <code>port </code><code>80</code>

<code># In </code><code>this</code> <code>recipe, we will </code><code>use</code> <code>the round-robin scheduling method.</code>

<code># In production, however, you should </code><code>use</code> <code>a weighted, </code><code>dynamic</code> <code>scheduling method.</code>

<code>  </code><code>/sbin/ipvsadm -A -t $VIP:</code><code>80</code> <code>-s wlc</code>

<code># Now direct packets </code><code>for</code> <code>this</code> <code>VIP to</code>

<code># the real server IP (RIP) inside the cluster</code>

<code>  </code><code>/sbin/ipvsadm -a -t $VIP:</code><code>80</code> <code>-r $RIP1 -g -w </code><code>1</code>

<code>  </code><code>/sbin/ipvsadm -a -t $VIP:</code><code>80</code> <code>-r $RIP2 -g -w </code><code>2</code>

<code>  </code><code>/bin/touch /</code><code>var</code><code>/lock/subsys/ipvsadm &amp;&gt; /dev/</code><code>null</code>

<code>;;</code>

<code>stop)</code>

<code># Stop forwarding packets</code>

<code>  </code><code>echo </code><code>0</code> <code>&gt; /proc/sys/net/ipv4/ip_forward</code>

<code># Reset ipvsadm</code>

<code># Bring down the VIP </code><code>interface</code>

<code>  </code><code>/sbin/ifconfig eth0:</code><code>1</code> <code>down</code>

<code>  </code><code>/sbin/route del $VIP</code>

<code>                                                                         </code> 

<code>  </code><code>/bin/rm -f /</code><code>var</code><code>/lock/subsys/ipvsadm</code>

<code>  </code><code>echo </code><code>"ipvs is stopped..."</code>

<code>status)</code>

<code>  </code><code>if</code> <code>[ ! -e /</code><code>var</code><code>/lock/subsys/ipvsadm ]; then</code>

<code>    </code><code>echo </code><code>"ipvsadm is stopped ..."</code>

<code>  </code><code>else</code>

<code>    </code><code>echo </code><code>"ipvs is running ..."</code>

<code>    </code><code>ipvsadm -L -n</code>

<code>  </code><code>fi</code>

<code>*)</code>

<code>  </code><code>echo </code><code>"Usage: $0 {start|stop|status}"</code>

<code>esac</code>

   提供Real Server啟動腳本

<code># Script to start LVS DR real server.</code>

<code># description: LVS DR real server</code>

<code>.  /etc/rc.d/init.d/functions</code>

<code>VIP=</code><code>192.168</code><code>.</code><code>0.219</code>

<code>host=`/bin/hostname`</code>

<code>start)</code>

<code>       </code><code># Start LVS-DR real server on </code><code>this</code> <code>machine.</code>

<code>        </code><code>/sbin/ifconfig lo down</code>

<code>        </code><code>/sbin/ifconfig lo up</code>

<code>        </code><code>echo </code><code>1</code> <code>&gt; /proc/sys/net/ipv4/conf/lo/arp_ignore</code>

<code>        </code><code>echo </code><code>2</code> <code>&gt; /proc/sys/net/ipv4/conf/lo/arp_announce</code>

<code>        </code><code>echo </code><code>1</code> <code>&gt; /proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>        </code><code>echo </code><code>2</code> <code>&gt; /proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>        </code><code>/sbin/ifconfig lo:</code><code>0</code> <code>$VIP broadcast $VIP netmask </code><code>255.255</code><code>.</code><code>255.255</code> <code>up</code>

<code>        </code><code>/sbin/route add -host $VIP dev lo:</code><code>0</code>

<code>        </code><code># Stop LVS-DR real server loopback device(s).</code>

<code>        </code><code>/sbin/ifconfig lo:</code><code>0</code> <code>down</code>

<code>        </code><code>echo </code><code>0</code> <code>&gt; /proc/sys/net/ipv4/conf/lo/arp_ignore</code>

<code>        </code><code>echo </code><code>0</code> <code>&gt; /proc/sys/net/ipv4/conf/lo/arp_announce</code>

<code>        </code><code>echo </code><code>0</code> <code>&gt; /proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>        </code><code>echo </code><code>0</code> <code>&gt; /proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>        </code><code># Status of LVS-DR real server.</code>

<code>        </code><code>islothere=`/sbin/ifconfig lo:</code><code>0</code> <code>| grep $VIP`</code>

<code>        </code><code>isrothere=`netstat -rn | grep </code><code>"lo:0"</code> <code>| grep $VIP`</code>

<code>        </code><code>if</code> <code>[ ! </code><code>"$islothere"</code> <code>-o ! </code><code>"isrothere"</code> <code>];then</code>

<code>            </code><code># Either the route or the lo:</code><code>0</code> <code>device</code>

<code>            </code><code># not found.</code>

<code>            </code><code>echo </code><code>"LVS-DR real server Stopped."</code>

<code>        </code><code>else</code>

<code>            </code><code>echo </code><code>"LVS-DR real server Running."</code>

<code>        </code><code>fi</code>

<code>            </code><code># Invalid entry.</code>

<code>            </code><code>echo </code><code>"$0: Usage: $0 {start|status|stop}"</code>

<code>            </code><code>exit </code><code>1</code>

   提供LVS-NET的腳本

<code># chkconfig: - </code><code>88</code> <code>12</code>

<code># description: LVS script </code><code>for</code> <code>VS/NAT</code>

<code>DIP=</code><code>192.168</code><code>.</code><code>10.10</code>

<code>RIP1=</code><code>192.168</code><code>.</code><code>10.11</code>

<code>RIP2=</code><code>192.168</code><code>.</code><code>10.12</code>

<code>  </code><code>/sbin/ifconfig eth0:</code><code>1</code> <code>$VIP netmask </code><code>255.255</code><code>.</code><code>255.0</code> <code>up</code>

<code>  </code><code>/sbin/ipvsadm -A -t $VIP:</code><code>80</code> <code>-s rr</code>

<code>  </code><code>/sbin/ipvsadm -a -t $VIP:</code><code>80</code> <code>-r $RIP1 -m</code>

<code>  </code><code>/sbin/ipvsadm -a -t $VIP:</code><code>80</code> <code>-r $RIP2 -m</code>

<code>                                                    </code> 

<code>  </code><code>/bin/touch /</code><code>var</code><code>/lock/subsys/ipvsadm.lock</code>

<code>  </code><code>ifconfig eth0:</code><code>1</code> <code>down</code>

<code>  </code><code>rm -rf /</code><code>var</code><code>/lock/subsys/ipvsadm.lock</code>

<code>  </code><code>[ -e /</code><code>var</code><code>/lock/subsys/ipvsadm.lock ] &amp;&amp; echo </code><code>"ipvs is running..."</code> <code>|| echo </code><code>"ipvsadm is stopped..."</code>

<code>  </code><code>echo </code><code>"Usage: $0 {start|stop}"</code>

本文轉自wangfeng7399 51CTO部落格,原文連結:http://blog.51cto.com/wangfeng7399/1396717,如需轉載請自行聯系原作者