亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

動(dòng)手寫一個(gè)OpenVPN的wrapper來優(yōu)化OpenVPN性能

系統(tǒng) 5194 0
OpenVPN,一個(gè)讓人想說愛你不容易的VPN,曾經(jīng)耗費(fèi)了我大量精力的VPN,其性能,...最終還是不咋地!以下是一個(gè)大致的統(tǒng)計(jì)數(shù)據(jù):
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN使用BF-CBC加密,SHA1摘要,OpenVPN不綁定特定CPU,帶寬可達(dá)20-30MB/s;
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN不加密,不摘要,OpenVPN不綁定特定CPU,帶寬可達(dá)40-45MB/s;
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN不加密,不摘要,OpenVPN綁定特定CPU,帶寬可達(dá)45-55MB/s;
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN使用BF-CBC加密,不摘要,OpenVPN綁定特定CPU,帶寬可達(dá)35-40MB/s;
純千兆環(huán)境,綁定OpenVPN到特定CPU,該CPU會(huì)跑滿,帶寬無法提升受制于CPU;
純千兆環(huán)境,不綁定OpenVPN到特定CPU,沒有一個(gè)CPU跑滿,帶寬無法提升受制于OpenVPN的單進(jìn)程模型以及操作系統(tǒng)多處理器調(diào)度開銷;
百兆環(huán)境,無論如何,OpenVPN的加密隧道帶寬基本接近物理網(wǎng)卡的百兆帶寬。

既然是OpenVPN的軟件模型遠(yuǎn)遠(yuǎn)跟不上硬件的提升,那么就要想辦法以量取勝,辦法是運(yùn)行多個(gè)OpenVPN進(jìn)程,每一個(gè)CPU上綁定一個(gè),通過Linux的內(nèi)核接口可以很容易做到這一點(diǎn):
1.首先mount一個(gè)cpuset,創(chuàng)建3個(gè)set
    mount -t cpuset none /mnt
mkdir /mnt/{vpn1,vpn2,vpn3}
  
2.簡(jiǎn)單配置一個(gè)cpuset
    echo 0 > /mnt/vpn1/cpus
echo 0 > /mnt/vpn1/mems
echo 1 > /mnt/vpn2/cpus
echo 0 > /mnt/vpn2/mems
echo 2 > /mnt/vpn3/cpus
echo 0 > /mnt/vpn3/mems
  
3.以不同端口號(hào)和虛擬網(wǎng)段啟動(dòng)3個(gè)不同的OpenVPN進(jìn)程
    openvpn --config cfg1 --port 1234 --server 121.121.0.0 255.255.0.0
openvpn --config cfg2 --port 2234 --server 122.122.0.0 255.255.0.0
openvpn --config cfg3 --port 3234 --server 123.123.0.0 255.255.0.0
  
4.綁定上述3個(gè)openvpn進(jìn)程到不同的cpuset
    i=1;for pid in $(ps -e|grep openvpn|awk -F ' ' '{print $1}');do echo $pid > /mnt/vpn$i/tasks; ((i=i+1)); done
  
5.將多個(gè)客戶端連接在這不同的三個(gè)OpenVPN進(jìn)程上,拉取大文件,測(cè)試OpenVPN服務(wù)器的tap0-tap2的總流量
經(jīng)過上述配置后,新的統(tǒng)計(jì)數(shù)據(jù)如下:
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN使用BF-CBC加密,SHA1摘要,帶寬可達(dá)35-40MB/s;
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN不加密,不摘要,帶寬可達(dá)75-80MB/s;
純千兆環(huán)境,4核心至強(qiáng)3.0GHZ處理器,OpenVPN使用BF-CBC加密,不摘要,帶寬可達(dá)50-55MB/s;
純千兆環(huán)境,3個(gè)CPU會(huì)跑滿,帶寬無法再提升受制于CPU;
純千兆環(huán)境,將物理網(wǎng)卡中斷(同時(shí)也是協(xié)議棧接收處理的軟中斷)釘在第四個(gè)CPU上,上述值再有5左右的提升。

可見,多個(gè)處理進(jìn)程會(huì)帶來帶寬的大幅提升。實(shí)際上上述的方案完全可以通過虛擬網(wǎng)卡bondding或者多VPN進(jìn)程共享虛擬網(wǎng)卡的方式做到,然而這些配置都不簡(jiǎn)單,有時(shí)還要修改虛擬網(wǎng)卡的驅(qū)動(dòng)程序,可擴(kuò)展性很不好,因此簡(jiǎn)單的以多OpenVPN實(shí)例來說明問題是再好不過的了,如需bonding方案或者shared-tap方案,請(qǐng)參考《 關(guān)于OpenVPN文章的目錄 》。
雖然上述方案解決了部分性能問題,然而配置還是比較復(fù)雜,能不能通過一個(gè)wrapper將上述的操作包裝起來呢?既能做到多實(shí)例并行-綁定特定CPU,又能做到OpenVPN客戶端動(dòng)態(tài)自動(dòng)獲取OpenVPN服務(wù)器端口號(hào)和虛擬網(wǎng)段。這需要增加一個(gè)層次,就是在OpenVPN連接之前增加一個(gè)“端口/虛擬網(wǎng)段”協(xié)商的層。該包裝器的使用如下:
服務(wù)器端:openvpn-wrapper -t server -p 1111 -v /usr/sbin/openvpn -c /home/zy/cfg ....
客戶端:openvpn-wrapper -t client -p 1111 -a 192.168.1.23 -v /usr/sbin/openvpn -c /home/zy/cfg-client
參數(shù)意義如下:
-t:類型,分為server和client,和openvpn一樣
-p:wrapper服務(wù)器監(jiān)聽的TCP端口號(hào)
-v:openvpn的路徑
-c:openvpn配置文件的路徑,該文件中沒有那些自動(dòng)協(xié)商出來的配置,比如openvpn的端口,虛擬網(wǎng)段等等。

openvpn-wrapper的代碼結(jié)構(gòu)如下:
    struct vpn_opt {
    char vpn_path[255]; //openvpn的路徑
    char cfg_path[255]; //openvpn配置文件路徑,配置文件不含server指令和port指令
    int port_base;      //起始端口號(hào)
    int num_process;    //openvpn進(jìn)程數(shù)量
    int num_cpu;        //CPU數(shù)量
    int sintr_cpu;      //單獨(dú)分配的處理物理網(wǎng)卡軟中斷的CPU
};

struct vpn_opt vopt;
int vpn_servers()
{
    int pid;
    int ps = vopt.num_process;
    //創(chuàng)建ps個(gè)openvpn服務(wù)器進(jìn)程
    while (ps--) {
        pid = fork();
        if (pid == 0) {
            //每一個(gè)openvpn服務(wù)器進(jìn)程綁定在一個(gè)CPU上
            sched_setaffinity(getpid(), ..., ps%vopt.num_cpu);
            execve(vopt.vpn_path --config vopt.cfg_path --port vopt.port_base+ps --server $不同虛擬網(wǎng)段...);
        } else if (pid > 0) {
        } else {
        }
    }
}
 
int accept_clients()
{
    //創(chuàng)建TCP服務(wù)器,接收client請(qǐng)求,回送端口信息
    //端口調(diào)度算法:
    //1.輪轉(zhuǎn)調(diào)度:N個(gè)客戶端按照先后順序在vopt.num_process個(gè)進(jìn)程之間輪轉(zhuǎn)
    //2.空閑優(yōu)先:紀(jì)錄M個(gè)VPN進(jìn)程之間的負(fù)載情況或client連接數(shù),取最小值
    //3.其它的算法...

    //對(duì)應(yīng)客戶端的wrapper先連接這個(gè)TCP server,得到VPN端口信息后調(diào)用exec啟動(dòng)
    //openvpn客戶端進(jìn)程。
}
 
int main(int argc, char **argv)
{
    char c;
    while ((c = getopt (argc, argv, "")) != -1)
        switch (c)
        {
        case 'v':
            strcpy(vopt.vpn_path, optarg);
            break;
        case 'c':
            strcpy(vopt.cfg_path, optarg);
            break;
        //可供配置的其它參數(shù),比如CPU數(shù)量,中斷處理均衡等
        default:
            abort ();
    }
    //下述參數(shù)必須由命令行提供:
    //vopt.port_base = 61195;
    //vopt.num_process = 2;
    //vopt.num_cpu = 2;
    vpn_servers();
    accept_clients();
}
  
有了這個(gè)wrapper,就可以將之直接替代openvpn了,但是對(duì)于大網(wǎng)對(duì)大網(wǎng)的拓?fù)洌绱嘶靵y的虛擬網(wǎng)段讓客戶端怎么管理呢?這可以通過將所有的配置全部集中在OpenVPN服務(wù)器端來解決,客戶端需要怎么配置全由服務(wù)器端來推送,涉及到自定義信息的推送,請(qǐng)參考push setenv-safe這個(gè)指令。如果涉及到全網(wǎng)互通的路由配置,你就不能單靠OpenVPN的client-to-client了,還要在不同的虛擬子網(wǎng)之間配置路由,怎么辦呢?還記得ICMP Redirect嗎?統(tǒng)一配置默認(rèn)網(wǎng)關(guān)(注意單加物理網(wǎng)段互通的路由)該虛擬網(wǎng)段的OpenVPN服務(wù)器的虛擬IP,如果目標(biāo)屬于同一個(gè)OpenVPN實(shí)例管轄,那么tap模式下OpenVPN服務(wù)器會(huì)直接發(fā)送ICMP Redirect,如果不是由同一個(gè)OpenVPN實(shí)例管轄,那么確保OpenVPN服務(wù)器上擁有管轄目標(biāo)網(wǎng)段的OpenVPN實(shí)例即可,一切都可以靠單點(diǎn)路由配置搞定。
總之一,將配置集中于一個(gè)點(diǎn),最終由同一個(gè)人來配置,這樣最不容易引起混亂,剩下的全部由機(jī)器來做。能推送下去的盡量推送下去,做到單點(diǎn)配置。OpenVPN提供了豐富的可推送的配置,實(shí)在滿足不了的可以使用setenv-safe這個(gè)。
總之二,優(yōu)化無極限,如果你單看多個(gè)OpenVPN實(shí)例運(yùn)行帶來了性能提升就沾沾自喜了,那么你就會(huì)錯(cuò)過綁定單個(gè)實(shí)例到一個(gè)CPU上帶來的進(jìn)一步性能提升,如果你有幸看到了這一點(diǎn),不要停步,看看top輸出,你會(huì)發(fā)現(xiàn)軟中斷可能在和OpenVPN搶奪CPU,因此你會(huì)進(jìn)入/proc/interrupts看個(gè)究竟,于是你可以通過設(shè)置/proc/irq/smp_affinity文件來分離中斷,突然,你看到了以下信息:
95: 18250769 193538 28997 45831 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-1
96: 4115 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-2
97: 52535493 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-3
98: 75459635 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-4
99: 4115 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-5
100: 44074216 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-6
101: 20545603 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth3-TxRx-7
于是你不得不拿起千兆以太網(wǎng)卡的手冊(cè)看看多隊(duì)列相關(guān)的內(nèi)容。這樣完了嗎?虛擬網(wǎng)卡帶寬之和已經(jīng)接近物理網(wǎng)卡的千兆帶寬了--98MB/s,不要止步,記得Linux有一個(gè)renice命令,提升一下OpenVPN的優(yōu)先級(jí)試一下...105MB/s。我想還可以更好,只是時(shí)間來不及了...出事了!
如果你只是看到了這,那么你可能錯(cuò)過了一件大事。重新看上面的eth3-TxRx-1信息,然后思考結(jié)果。當(dāng)我將每一個(gè)OpenVPN綁定于特定的不同CPU之后,所有的網(wǎng)卡TxRx隊(duì)列卻還只是由一個(gè)CPU處理,這就形成了一個(gè)多對(duì)一的關(guān)系,考慮如下的拓?fù)洌?
動(dòng)手寫一個(gè)OpenVPN的wrapper來優(yōu)化OpenVPN性能
服務(wù)器端每一個(gè)VPN進(jìn)程由一個(gè)單獨(dú)的CPU來處理,它們很顯然都會(huì)將包發(fā)往網(wǎng)卡ETH3,而該網(wǎng)卡ETH3的中斷卻只由一個(gè)CPU來處理,不管是發(fā)送中斷還是接收中斷。能不能均分一下任務(wù)呢?在均分之前,先要想一個(gè)方案。我有8個(gè)CPU核心,分別處于兩個(gè)封裝上,每個(gè)封裝4個(gè)核心,于是我啟動(dòng)6個(gè)VPN實(shí)例,分別綁定在編號(hào)(從0開始)為1,2,3,4,5,6的CPU上,然后讓CPU0和CPU1各自處理一半的軟中斷(大多數(shù)是接收中斷的軟中斷),這是因?yàn)橐粋€(gè)封裝內(nèi)部的Cache親和性以及CPU核心親和性要比屬于不同封裝的核心好很多,因此兩個(gè)封裝中各自都有一個(gè)核心處理軟中斷,可以高效地將數(shù)據(jù)踢給綁定于同一封裝核心的VPN實(shí)例。測(cè)試下來雖然性能提升不顯著,但是畢竟有了3MB/s的提升。
說了這么多,所謂的OpenVPN的優(yōu)化都是在OpenVPN外部進(jìn)行的,要知道其本身也有很多的參數(shù)可以調(diào)節(jié)性能,比如sndbuf和rcvbuf以及txqueuelen這三個(gè)參數(shù),如果rcvbuf和sndbuf不一致相差太多的話,會(huì)造成UDP以及ICMP的大量丟包,雖然TCP能調(diào)節(jié)自身的速率,但是當(dāng)rcvbuf小到比TCP管道最細(xì)的部位還要小的時(shí)候,丟包就顯著了,比如rcvbuf是M,而TCP的慢啟動(dòng)閥值為N,且N遠(yuǎn)大于M,這就會(huì)導(dǎo)致TCP頻繁大量丟包,然后慢啟動(dòng),然后再丟包,再慢啟動(dòng)...此時(shí)要么調(diào)小慢啟動(dòng)閥值,要么調(diào)小TCP發(fā)送緩沖區(qū),對(duì)于Linux則是tcp_wmem,不過最好的辦法就是調(diào)整sndbuf和rcvbuf,將其調(diào)整為一樣大,并且適當(dāng)比TCP管道更寬一些,讓TCP可以在其中自由發(fā)揮流控以及擁塞控制,而不是將OpenVPN模擬成一段及其惡劣的線路,如果你將sndbuf設(shè)置成了30000,將rcvbuf設(shè)成了1234567,那么雖然TCP也能進(jìn)入VPN隧道,但是這條隧道太惡劣了,有效速率將會(huì)很低很低。
可是還有個(gè)小問題,為何不把中斷均分到VPN實(shí)例所在的CPU呢?這是可行的,然而必須用測(cè)試結(jié)果說話,有一點(diǎn)可以確定的是,如果那樣的話,雖然可能會(huì)得益于千兆網(wǎng)卡的DCA,然而VPN實(shí)例和軟中斷將會(huì)搶奪CPU,搶奪的激烈程度不僅僅受制于CPU的性能,還要受制于時(shí)間的串行性的本質(zhì),畢竟同一時(shí)刻一個(gè)CPU只能做一件事,因此有時(shí)候,你用top發(fā)現(xiàn)每一個(gè)CPU都沒有泡滿,然而性能卻反而因?yàn)橹袛嗑侄陆盗耍档米⒁獾氖牵珻ache親和性雖然很重要,但是相比訪問同一個(gè)核心的Cache的開銷,訪問同一顆封裝的Cache的開銷也不會(huì)差太多,畢竟現(xiàn)代超猛的多核心處理器的每個(gè)封裝,甚至封裝之間都有共享Cache的。于是這又扯到了一級(jí)Cache,二級(jí)Cache,...內(nèi)存,磁盤,網(wǎng)絡(luò)等存儲(chǔ)設(shè)備的大小和層次問題了...
通過測(cè)試終端的TCP重傳次數(shù)計(jì)算,上述的結(jié)果非常不錯(cuò),優(yōu)化無極限,如果考慮到一路統(tǒng)一MTU,那將必須又是一個(gè)優(yōu)化切入點(diǎn),另外還有e1000e千兆網(wǎng)卡驅(qū)動(dòng)的很多參數(shù)還沒有調(diào)整,另外,如果你的CPU核心在綁了一個(gè)OpenVPN實(shí)例且滿數(shù)據(jù)跑時(shí)top顯示其idle百分比仍然很高,那么就在其上綁定兩個(gè)或者多個(gè)OpenVPN實(shí)例,總之,CPU利用率達(dá)到90%以上并不是壞事,而是好事,這個(gè)和桌面系統(tǒng)是完全不同的...
如果CPU跑不滿,先別急著綁多個(gè)VPN實(shí)例,還有一招,那就是壓縮,在OpenVPN配置中增加comp-lzo即可,非常簡(jiǎn)單,理論和測(cè)試結(jié)果均證明,啟用壓縮可以大大減少丟包率,且使得吞吐量得到大幅提高。最基本的一點(diǎn),對(duì)于TCP而言,我覺得多個(gè)OpenVPN載荷包打包壓縮要比單個(gè)載荷包單獨(dú)壓縮效果更好些,OpenVPN隧道一端對(duì)多個(gè)TCP包進(jìn)行壓縮,另一端簡(jiǎn)單進(jìn)行解壓縮,隧道途中,壓縮包中載荷數(shù)據(jù)包順序決不會(huì)亂掉,因此也就使得串行的協(xié)議比如TCP的順序性得到了加強(qiáng),多包加密隧道不但封裝了數(shù)據(jù)加密了數(shù)據(jù),還帶著串行的TCP數(shù)據(jù)走過了最坎坷的一段路使它們不會(huì)亂序。下圖說明了這一點(diǎn):
動(dòng)手寫一個(gè)OpenVPN的wrapper來優(yōu)化OpenVPN性能
但是,即使是單包壓縮,也會(huì)使隧道傳輸速率提高,因?yàn)樗淼纼?nèi)的數(shù)據(jù)包尺寸減小了,更有利于傳輸(轎車要比卡車快...?),同時(shí)通過調(diào)節(jié)中途設(shè)備的網(wǎng)卡驅(qū)動(dòng)參數(shù)還能將隧道傳輸速率進(jìn)一步提高,舉個(gè)例子,Intel千兆網(wǎng)卡就有可以調(diào)節(jié)的參數(shù)使它更有利于小包的收發(fā),或者更有利于大包的收發(fā),或者折中。MTU導(dǎo)致的IP分段也是使用壓縮的重要理由。壓縮可以將包壓小,如果傳輸文件,發(fā)送數(shù)據(jù)塊而不是小包的可能性較大(相反的則是ssh之類的延遲敏感的程序,它們一般使用小包通信),那么起始端可能根據(jù)網(wǎng)卡的MTU來截取數(shù)據(jù)包,然而OpenVPN在用戶態(tài)使用socket為其進(jìn)行封裝,肯定會(huì)超過MTU值,因此OpenVPN的封裝對(duì)于端到端的MTU發(fā)現(xiàn)是不可見的,所以IP分段并沒有發(fā)生在端到端的載荷包上,而是發(fā)生在OpenVPN的數(shù)據(jù)傳輸本身。通過抓包,發(fā)現(xiàn)大量:
10:07:26.243655 IP (tos 0x0, ttl 64, id 50897, offset 0, flags [+], proto UDP (17), length 1500)
172.16.2.1.61195 > 172.16.2.2.43050: UDP, length 1529
10:07:26.243659 IP (tos 0x0, ttl 64, id 50897, offset 1480, flags [none], proto UDP (17), length 77)
172.16.2.1 > 172.16.2.2: udp

因此很大一部分開銷花在了IP分段/重組上,故采用壓縮是明智的。一個(gè)等價(jià)的解決方案是不使用壓縮(畢竟它消耗了CPU),取而代之的是將OpenVPN兩個(gè)端點(diǎn)之間的所有鏈路的MTU調(diào)大那么一點(diǎn)點(diǎn)(多處一個(gè)OpenVPN協(xié)議頭以及OpenVPN使用的TCP/UDP頭等協(xié)議頭)。
做到這一步,現(xiàn)實(shí)意義上已經(jīng)夠了,剩下的就全屬業(yè)余愛好了...
最后要說的是,雖然以上的方式有效的提升了OpenVPN構(gòu)建的VPN隧道性能,然而卻不能將所有多條隧道的帶寬全部供給一個(gè)OpenVPN客戶端,只是說它們的和是一個(gè)不小的值,如果想實(shí)現(xiàn)單條隧道的帶寬提升,那就需要多實(shí)例bonding或者多實(shí)例路由負(fù)載均衡了。本文所寫的其實(shí)不是什么創(chuàng)新,很多Linux發(fā)行版自帶的OpenVPN本身就提供了多實(shí)例OpenVPN并行的配置,只需要service包裝命令啟動(dòng)一下即可。

動(dòng)手寫一個(gè)OpenVPN的wrapper來優(yōu)化OpenVPN性能


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 一本大道高清香蕉中文大在线 | 日韩欧美一区二区在线观看 | 日韩国产片| 91久久香蕉国产线看 | 欧美一级网址 | 久久综合九色综合欧洲 | 夜夜嗨影院 | 亚洲精国产一区二区三区 | 日韩精品第三页 | 奇米视频在线观看 | 免费xxx | 97午夜影院 | 欧美成人精品一区二三区在线观看 | 五月天婷婷免费观看视频在线 | 成人一区专区在线观看 | 免费的一级毛片 | 天天做天天爱天天影视综合 | 日本乱人伦片中文字幕三区 | 亚洲国产高清在线精品一区 | 婷婷五 在线播放 | 欧美激情伦妇在线观看 | 亚洲性视频网站 | 一级一级一级一级毛片 | 日韩毛片| 9999热| 久久久网 | 日本一区二区三区在线观看 | 久久精品国产精品青草 | 国产精品国产亚洲精品看不卡 | 国产97公开成人免费视频 | 五月四房婷婷 | 男女羞羞免费视频 | 亚洲精品美女久久久aaa | 女人18毛片a级毛片免费看一 | 久久青青视频 | 久久国产免费一区二区三区 | 特级女人十八毛片a级 | 99精品视频在线观看 | 亚洲第一成年免费网站 | 亚洲精品亚洲九十七页 | 日本一级www乱码在线 |