lvs+srs(dr模型)
參考:
https://my.oschina.net/fengjihu/blog/416883 (srs集群模式)
http://blog.csdn.net/reblue520/article/details/50857078 (lvs負載均衡)
http://www.cnblogs.com/lgfeng/archive/2012/10/16/2726308.html (arp_ignore和arp_announce)
http://www.linuxvirtualserver.org/docs/arp.html (lvs arp問題)
http://www.linuxvirtualserver.org/VS-DRouting.html (lvs dr模式)
目的:
通過lvs推流到多個流服務器以緩解服務器壓力,利用邊緣服務器的功能可以訪問到所有流,又可以節約帶寬,因為是直播,所以推過來的流都是不同ip的,所以可以利用lvs hash ip的功能將同一流的包轉發到同一流服務器,這樣就解決了流的存放問題。
lvs dr模式原理簡介:
在dr模式下,director、real server和vip都在同一網段中,這就帶來了幾個問題:
1.在此模式下,vip接收到的請求不能簡單地通過轉發給real server,因為當請求過來的時候,如果簡單地轉發,因為三臺都能連外網,所以轉發的時候real server會直接回復給請求方,而請求方收到ip,發現不是自己請求的會丟棄。
所以,每個real server上面都綁定了vip,當收到vip來的請求包的時候,real server 用vip作為源地址回復。
2.我們解決了1的問題,但是這又帶來了新的問題:director和real server都有vip,而且在同一網段中,所以vip請求到來的時候,網關會廣播請求,所以不管是director還是realserver他們都會收到請求,假設我們director先收到了,它是怎麽進行負載均衡調度的呢?
利用ip是不行的,如果用realserver的真實ip,那麽就會回到1的問題上去,所以只能用vip作為目的ip。事實上,dr模式下,lvs是根據mac地址來進行負載均衡調度的,因為每臺的mac地址都不同,所以只有對應mac的rs(realserver簡寫,懶得打)會收到請求,並且因為自己確實有vip,所以能響應請求。
3.那麽,我們又怎麽確保director第一個收到呢?在同一網段中,每臺服務器都會收到vip請求廣播包,我們怎麽保證rs既能響應這些請求又不首先響應?這就要用到arp_ignore和arp_announce或者hidden interface的功能。
在dr模式下,rs的配置是有些特殊的。比較常見的一種是把vip綁定到lo口上,因為大多數linux內核版本不會響應回環口ip的arp報文請求,所以當收到vip廣播請求報文的時候,rs不會響應。因為director是把vip綁定到某個非回環口上的,所以director可以第一個收到並響應vip請求報文。 另一種常見的做法是,rs把vip綁定到某個不在使用中的接口上,然後利用hidden interface的功能禁掉此接口的arp響應,因為沒有arp響應,所以這個端口必須不使用,否則影響正常通信。
我們的案例使用的是第三種常見的方法:設置arp_ignore 為1,這個參數的作用是只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求
舉個例子,假設本機上兩個網口,eth0上綁定的ip為1.1.1.1,eth1上綁定的是2.2.2.2,那麽設置arp_ignore為1後,當eth0收到2.2.2.2的arp請求報文後不會響應,同理eth1收到1.1.1.1的arp請求報文不會響應(eth0:0子網卡不確定可不可以,待測試)
然後,設置arp_announce為2,這個的作用是使用出口網口的mac作為源mac。
舉個例子,假設本機有eth0:1.1.1.1,eth1:2.2.2.2 ,假設本機收到了1.1.1.1的請求包,卻從eth1口發送包,那麽數據幀的源mac應該是寫eth0的mac還是eth1的mac? 正常情況下是寫eth1的,但是linux比較特殊,默認是寫eth0的,設為2,是讓它默認寫eth1的。
為什麽這裏需要用到呢?因為vip包是director第一個響應的,所以網關的arp表保留的是director的mac,假設rs,eth0配的真實ip,eth1配的vip,那麽,當收到director改寫mac的vip請求包後,它響應並從eth0回送包(我們不應該讓eth1接受到包,否則又回到2),如果此時填的是eth1,也就是vip所在的mac,那麽網關發現這個是vip的新mac就會更新arp表,從而造成vip搶占(這個是別人的說法,我不太認同,因為就算用eth0的mac也會被更新,一樣搶占,待我找到靠譜的答案再更新此問題)
架構:
director ip:192.168.2.119(lvs調度器服務器ip)
virtual ip:192.168.2.111(調度用的虛擬ip)
real1 ip:192.168.2.127(srs源端服務器ip1)
real2 ip:192.168.2.138(srs源端服務器ip2)
srs ip:192.168.2.221 (此為srs邊緣服務器ip)
為了實驗方便,默認都關閉iptables和selinux
real1:
echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
cd /etc/sysconfig/network-scripts/
cp ifcfg-lo ifcfg-lo:0
vi ifcfg-lo:0 內容如下:
DEVICE=lo:0
IPADDR=192.168.2.111
NETMASK=255.255.255.255
BROADCAST=192.168.2.111
BROADCAST=127.255.255.255
ONBOOT=yes
NAME=loopback
service network restart
vi /usr/local/srs/conf/edge.conf 內容如下:
listen 1935;
max_connections 1000;
pid objs/edge.pid;
srs_log_file ./objs/edge.log;
vhost __defaultVhost__ {
}
service srs restart
route add -host 192.168.2.111 dev lo:0 #加這條是為了保證本機響應包的源ip為vip不變
real2:
配置和real1一樣,略
srs 邊緣服務器的配置:
vi /usr/local/srs/conf/edge.conf
listen 1935;
max_connections 1000;
pid objs/edge.pid;
srs_log_file ./objs/edge.log;
vhost __defaultVhost__ {
mode remote;
origin 192.168.2.138:1935 192.168.2.127:1935; (經測試,當192.168.2.138和192.168.2.127存在不同流的時候,
} 用這種配置邊緣服務器可以訪問兩臺服務器上的所有流)
service srs restart
direct 的配置:
vi /etc/sysctl.conf
net.ipv4.ip_forward = 1 (lvs轉發包,所以這個要為1,開啟轉發功能)
sysctl -p
yum install ipvsadm -y (lvs是通過ipvsadm這個軟件包管理的,就類似於netfiter和iptables的關系)
cd /etc/sysconfig/network-scripts/
cp ifcfg-eth0 ifcfg-eth0:0
vi ifcfg-eth0:0 內容如下:
DEVICE=eth0:0
BOOTPROTO=static
HWADDR=00:0C:29:5B:58:99
ONBOOT=yes
IPADDR=192.168.2.111
GATEWAY=192.168.2.1
NETMASK=255.255.255.0
service network restart
route add 192.168.2.111 dev eth0:0
ipvsadm -A -t 192.168.2.111:1935 -s sh (添加服務,-s指定調度算法,sh是source_hash的意思,根據來源ip調度到同一臺服務器)
ipvsadm -a -t 192.168.2.111:1935 -r 192.168.2.138:1935 -m (添加後端服務器)
ipvsadm -a -t 192.168.2.111:1935 -r 192.168.2.127:1935 -m
ipvsadm -Ln (這個命令可以查看ipvs當前的狀態)
推流測試:
/usr/local/src/srs/trunk/objs/ffmpeg/bin/ffmpeg -re -i test.flv -vcodec copy -acodec copy -f flv -y rtmp://192.168.2.111/live/livestream1
/usr/local/src/srs/trunk/objs/ffmpeg/bin/ffmpeg -re -i test2.flv -vcodec copy -acodec copy -f flv -y rtmp://192.168.2.111/live/livestream2
通過rtmp://192.168.2.221/live/livestream1和rtmp://192.168.2.221/live/livestream2 查看確認視頻可正常播放
lvs+srs(dr模型)