軟件開發(fā)報告_第1頁
軟件開發(fā)報告_第2頁
軟件開發(fā)報告_第3頁
軟件開發(fā)報告_第4頁
軟件開發(fā)報告_第5頁
已閱讀5頁,還剩33頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、負(fù)載均衡器軟件 開發(fā)報告 院系:班級: 成員:目錄1.可行性分析報告11.1 項目背景11.2產(chǎn)品分析11.3 結(jié)論意見22.項目開發(fā)計劃22.1 總體功能要求22.2 軟件開發(fā)平臺要求22.3 軟件項目的開發(fā)實施過程管理要求33.軟件開發(fā)33.1 軟件的需求分析 33.3軟件的詳細(xì)設(shè)計53.4 軟件的編碼63.5軟件的測試313.5.1測試計劃313.5.2 軟件測試324.項目開發(fā)總結(jié)報告33I1.可行性分析報告1.1 項目背景面對龐大的數(shù)據(jù)流量,面對集中性的訪問,是不是覺得網(wǎng)絡(luò)服務(wù)器岌岌可危呢?不用怕,負(fù)載均衡器就能幫你緩解這個問題。負(fù)載均衡器通過虛擬IP地址方法,解決了輪流排

2、程所面臨的許多問題。使用了負(fù)載均衡器集群系統(tǒng),在外部看來,像是具有一個IP地址的單一服務(wù)器一樣,當(dāng)然,這個IP地址是虛擬的,它映射了集群中的每一臺機(jī)器的地址。所以,在某種程度上,負(fù)載均衡器是將整個集群的IP地址報漏給外部網(wǎng)絡(luò)。當(dāng)請求到達(dá)負(fù)載均衡器時,它會重寫該請求的頭文件,并將之指定到集群中的機(jī)器上。如果某臺機(jī)器被從集群中移除了,請求不會別發(fā)往已經(jīng)不存在的服務(wù)器上,因為所有的機(jī)器表面上都具有同一個IP地址,即使集群中的某個節(jié)點被移除了,該地址也不會發(fā)生變化。而且,internet上緩存的DNS條目也不再是問題了。當(dāng)返回一個應(yīng)答時,客戶端看到的只是從負(fù)載均衡器上所返回的結(jié)果。也就是說,客戶端操作

3、的對象是負(fù)載均衡器,對于其更后端的操作,對客戶端來講,是完全透明的。1.2產(chǎn)品分析服務(wù)器一致性負(fù)載均衡器讀取客戶端發(fā)出的每一個請求中所包含的cookies或url解釋?;谒x出的這些信息,負(fù)載均衡器就可以重寫報頭并將請求發(fā)往集群中合適的節(jié)點上,該節(jié)點維護(hù)著相應(yīng)客戶端請求的會話信息。在HTTP通信中,負(fù)載均衡器可以提供服務(wù)器一致性,但并不是通過一個安全的途徑(例如:HTTPS)來提供這種服務(wù)。當(dāng)消息被加密后(SSL),負(fù)載均衡器就不能讀出隱藏在其中的會話信息。通過故障恢復(fù)機(jī)制獲得高可靠性故障恢復(fù)發(fā)生在當(dāng)集群中某個節(jié)點不能處理請求,需將請求重新導(dǎo)向到其他節(jié)點時。主要有兩種故障恢復(fù):請求級故障恢復(fù)

4、。當(dāng)集群中的一個節(jié)點不能處理請求時(通常是由于down機(jī)),請求被發(fā)送到其他節(jié)點。當(dāng)然,在導(dǎo)向到其他節(jié)點的同時,保存在原節(jié)點上的會話信息將會丟失。透明會話故障恢復(fù)。當(dāng)一個引用失敗后,負(fù)載均衡器會將之發(fā)送到集群中其他的節(jié)點上,以完成操作,這一點對用戶來說是透明的。由于透明會話故障恢復(fù)需要節(jié)點具備相應(yīng)的操作信息,因此為了實現(xiàn)該功能,集群中的所有節(jié)點必須具有公共存儲區(qū)域或通用數(shù)據(jù)庫,存儲會話信息數(shù)據(jù),以提供每個節(jié)點在進(jìn)行單獨進(jìn)程會話故障恢復(fù)時所需要的操作信息。既然所有的Web應(yīng)用請求都必須經(jīng)過負(fù)載均衡系統(tǒng),那么系統(tǒng)就可以確定活動會話的數(shù)量,在任何實例訪問中的活動會話的數(shù)目,應(yīng)答的次數(shù),高峰負(fù)載次數(shù),

5、以及在高峰期和低谷期的會話的數(shù)目,還有其他更多的。所有的這些統(tǒng)計信息都可以被很好的用來調(diào)整整個系統(tǒng)的性能。1.3 結(jié)論意見雖然此項目存在一定的技術(shù)難度和風(fēng)險,但我們對項目要達(dá)到的目標(biāo)十分清楚,對所要開發(fā)系統(tǒng)將要實現(xiàn)的功能也非常了解。而且有一些成品作為參考,并且在項目的實施過程中我們能夠獲得幫助,我認(rèn)為只要我們能夠認(rèn)真思考、仔細(xì)規(guī)劃、明確分工,我們可以承擔(dān)此項目的開發(fā)。2.項目開發(fā)計劃2.1 總體功能要求1.擴(kuò)展網(wǎng)絡(luò)設(shè)備和服務(wù)器的帶寬2.增加吞吐量3.加強網(wǎng)絡(luò)數(shù)據(jù)處理能力4.提高網(wǎng)絡(luò)的靈活性和可用性2.2 軟件開發(fā)平臺要求Visual c+ 6.0SQL Server 2008C+ Builde

6、r網(wǎng)絡(luò)架構(gòu):完全支持TCP/IP協(xié)議2.3 軟件項目的開發(fā)實施過程管理要求3.軟件開發(fā)3.1 軟件的需求分析 1DNS負(fù)載均衡最早的負(fù)載均衡技術(shù)是通過DNS來實現(xiàn)的,在DNS中為多個地址配置同一個名字,因而查詢這個名字的客戶機(jī)將得到其中一個地址,從而使得不同的客戶訪問不同的服務(wù)器,達(dá)到負(fù)載均衡的目的。DNS負(fù)載均衡是一種簡單而有效的方法,但是它不能區(qū)分服務(wù)器的差異,也不能反映服務(wù)器的當(dāng)前運行狀態(tài)。 2代理服務(wù)器負(fù)載均衡 使用代理服務(wù)器,可以將請求轉(zhuǎn)發(fā)給內(nèi)部的服務(wù)器,使用這種加速模式顯然可以提升靜態(tài)網(wǎng)頁的訪問速度。然而,也可以考慮這樣一種技術(shù),使用代理服務(wù)器將請求均

7、勻轉(zhuǎn)發(fā)給多臺服務(wù)器,從而達(dá)到負(fù)載均衡的目的。 3地址轉(zhuǎn)換網(wǎng)關(guān)負(fù)載均衡 支持負(fù)載均衡的地址轉(zhuǎn)換網(wǎng)關(guān),可以將一個外部IP地址映射為多個內(nèi)部IP地址,對每次TCP連接請求動態(tài)使用其中一個內(nèi)部地址,達(dá)到負(fù)載均衡的目的。 4協(xié)議內(nèi)部支持負(fù)載均衡除了這三種負(fù)載均衡方式之外,有的協(xié)議內(nèi)部支持與負(fù)載均衡相關(guān)的功能,例如HTTP協(xié)議中的重定向能力等,HTTP運行于TCP連接的最高層。 5NAT負(fù)載均衡NAT簡單地說就是將一個IP地址轉(zhuǎn)換為另一個IP地址,一般用于未經(jīng)注冊的內(nèi)部地址與合法的、已獲注冊的Internet IP地址間進(jìn)行轉(zhuǎn)換。適用于解決Internet

8、 IP地址緊張、不想讓網(wǎng)絡(luò)外部知道內(nèi)部網(wǎng)絡(luò)結(jié)構(gòu)等的場合下。 6反向代理負(fù)載均衡普通代理方式是代理內(nèi)部網(wǎng)絡(luò)用戶訪問internet上服務(wù)器的連接請求,客戶端必須指定代理服務(wù)器,并將本來要直接發(fā)送到internet上服務(wù)器的連接請求發(fā)送給代理服務(wù)器處理。反向代理(Reverse Proxy)方式是指以代理服務(wù)器來接受internet上的連接請求,然后將請求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,并將從服務(wù)器上得到的結(jié)果返回給internet上請求連接的客戶端,此時代理服務(wù)器對外就表現(xiàn)為一個服務(wù)器。反向代理負(fù)載均衡技術(shù)是把將來自internet上的連接請求以反向代理的方式動態(tài)地轉(zhuǎn)發(fā)給

9、內(nèi)部網(wǎng)絡(luò)上的多臺服務(wù)器進(jìn)行處理,從而達(dá)到負(fù)載均衡的目的。 7混合型負(fù)載均衡在有些大型網(wǎng)絡(luò),由于多個服務(wù)器群內(nèi)硬件設(shè)備、各自的規(guī)模、提供的服務(wù)等的差異,可以考慮給每個服務(wù)器群采用最合適的負(fù)載均衡方式,然后又在這多個服務(wù)器群間再一次負(fù)載均衡或群集起來以一個整體向外界提供服務(wù)(即把這多個服務(wù)器群當(dāng)做一個新的服務(wù)器群),從而達(dá)到最佳的性能。將這種方式稱之為混合型負(fù)載均衡。此種方式有時也用于單臺均衡設(shè)備的性能不能滿足大量連接請求的情況下。3.2軟件的概要設(shè)計 軟件負(fù)載均衡解決方案是指在一臺或多臺服務(wù)器相應(yīng)的操作系統(tǒng)上安裝一個或多個附加軟件來實現(xiàn)負(fù)載均衡,DNSLoadBalanceC

10、heckPointFirewall-1ConnectControl等,它的優(yōu)點是基于特定環(huán)境,配置簡單,使用靈活,成本低廉,可以滿足一般的負(fù)載均衡需求。硬件負(fù)載均衡解決方案是直接在服務(wù)器和外部網(wǎng)絡(luò)間安裝負(fù)載均衡設(shè)備,這種設(shè)備通常稱之為負(fù)載均衡器,由于專門的設(shè)備完成專門的任務(wù),獨立于操作系統(tǒng),整體性能得到大量提高,加上多樣化的負(fù)載均衡策略,智能化的流量管理,可達(dá)到最佳的負(fù)載均衡需求。一般而言,硬件負(fù)載均衡在功能、性能上優(yōu)于軟件方式,不過成本昂貴。本地負(fù)載均衡能有效地解決數(shù)據(jù)流量過大、網(wǎng)絡(luò)負(fù)荷過重的問題,并且不需花費昂貴開支購置性能卓越的服務(wù)器,充分利用現(xiàn)有設(shè)備,避免服務(wù)器單點故障造成數(shù)據(jù)流量的損

11、失。其有靈活多樣的均衡策略把數(shù)據(jù)流量合理地分配給服務(wù)器群內(nèi)的服務(wù)器共同負(fù)擔(dān)。即使是再給現(xiàn)有服務(wù)器擴(kuò)充升級,也只是簡單地增加一個新的服務(wù)器到服務(wù)群中,而不需改變現(xiàn)有網(wǎng)絡(luò)結(jié)構(gòu)、停止現(xiàn)有的服務(wù)。全局負(fù)載均衡主要用于在一個多區(qū)域擁有自己服務(wù)器的站點,為了使全球用戶只以一個IP地址或域名就能訪問到離自己最近的服務(wù)器,從而獲得最快的訪問速度,也可用于子公司分散站點分布廣的大公司通過企業(yè)內(nèi)部互聯(lián)網(wǎng)來達(dá)到資源統(tǒng)一合理分配的目的。3.3軟件的詳細(xì)設(shè)計1.輪轉(zhuǎn)法:輪轉(zhuǎn)算法是所有調(diào)度算法中最簡單也最容易實現(xiàn)的一種方法。在一個任務(wù)隊列里,隊列的每個成員(節(jié)點)都具有相同的地位,輪轉(zhuǎn)法簡單的在這組成員中順序輪轉(zhuǎn)選擇。在

12、負(fù)載平衡環(huán)境中,均衡器將新的請求輪流發(fā)給節(jié)點隊列中的下一節(jié)點,如此連續(xù)、周而復(fù)始,每個集群的節(jié)點都在相等的地位下被輪流選擇。這個算法在DNS域名輪詢中被廣泛使用。 輪轉(zhuǎn)法的活動是可預(yù)知的,每個節(jié)點被選擇的機(jī)會是1/N,因此很容易計算出節(jié)點的負(fù)載分布。輪轉(zhuǎn)法典型的適用于集群中所有節(jié)點的處理能力和性能均相同的情況,在實際應(yīng)用中,一般將它與其他簡單方法聯(lián)合使用時比較有效。2.散列法:散列法也叫哈希法(HASH),通過單射不可逆的HASH函數(shù),按照某種規(guī)則將網(wǎng)絡(luò)請求發(fā)往集群節(jié)點。哈希法在其他幾類平衡算法不是很有效時會顯示出特別的威力。例如,在前面提到的UDP會話的情況下,由于輪轉(zhuǎn)法和其他幾類基于連接信

13、息的算法,無法識別出會話的起止標(biāo)記,會引起應(yīng)用混亂。 而采取基于數(shù)據(jù)包源地址的哈希映射可以在一定程度上解決這個問題:將具有相同源地址的數(shù)據(jù)包發(fā)給同一服務(wù)器節(jié)點,這使得基于高層會話的事務(wù)可以以適當(dāng)?shù)姆绞竭\行。相對稱的是,基于目的地址的哈希調(diào)度算法可以用在Web Cache集群中,指向同一個目標(biāo)站點的訪問請求都被負(fù)載平衡器發(fā)送到同一個Cache服務(wù)節(jié)點上,以避免頁面缺失而帶來的更新Cache問題。3.最少連接法:在最少連接法中,平衡器紀(jì)錄目前所有活躍連接,把下一個新的請求發(fā)給當(dāng)前含有最少連接數(shù)的節(jié)點。這種算法針對TCP連接進(jìn)行,但由于不同應(yīng)用對系統(tǒng)資源的消耗可能差異很大,而連接數(shù)無法反映出真實的應(yīng)

14、用負(fù)載,因此在使用重型Web服務(wù)器作為集群節(jié)點服務(wù)時(例如Apache服務(wù)器),該算法在平衡負(fù)載的效果上要打個折扣。為了減少這個不利的影響,可以對每個節(jié)點設(shè)置最大的連接數(shù)上限(通過閾值設(shè)定體現(xiàn))。4.最低缺失法:在最低缺失法中,平衡器長期紀(jì)錄到各節(jié)點的請求情況,把下個請求發(fā)給歷史上處理請求最少的節(jié)點。與最少連接法不同的是,最低缺失記錄過去的連接數(shù)而不是當(dāng)前的連接數(shù)。5.最快響應(yīng)法:平衡器記錄自身到每一個集群節(jié)點的網(wǎng)絡(luò)響應(yīng)時間,并將下一個到達(dá)的連接請求分配給響應(yīng)時間最短的節(jié)點,這種方法要求使用ICMP包或基于UDP包的專用技術(shù)來主動探測各節(jié)點。 在大多數(shù)基于LAN的集群中,最快響應(yīng)算法工作的并不

15、是很好,因為LAN中的ICMP包基本上都在10ms內(nèi)完成回應(yīng),體現(xiàn)不出節(jié)點之間的差異;如果在 WAN上進(jìn)行平衡的話,響應(yīng)時間對于用戶就近選擇服務(wù)器而言還是具有現(xiàn)實意義的;而且集群的拓?fù)湓椒稚⑦@種方法越能體現(xiàn)出效果來。這種方法是高級平衡基于拓?fù)浣Y(jié)構(gòu)重定向用到的主要方法。6. 加權(quán)法:加權(quán)方法只能與其他方法合用,是它們的一個很好的補充。加權(quán)算法根據(jù)節(jié)點的優(yōu)先級或當(dāng)前的負(fù)載狀況(即權(quán)值)來構(gòu)成負(fù)載平衡的多優(yōu)先級隊列,隊列中的每個等待處理的連接都具有相同處理等級,這樣在同一個隊列里可以按照前面的輪轉(zhuǎn)法或者最少連接法進(jìn)行均衡,而隊列之間按照優(yōu)先級的先后順序進(jìn)行均衡處理。在這里權(quán)值是基于各節(jié)點能力的一個估

16、計值。3.4 軟件的編碼#include <exception>#include <errno.h>#include <string.h>#include "conn.h"#include "log.h"#include "fdwrapper.h"conn:conn() m_srvfd = -1; m_clt_buf = new char BUF_SIZE ; if( !m_clt_buf ) throw std:exception(); m_srv_buf = new char BUF_SIZE

17、; if( !m_srv_buf ) throw std:exception(); reset();conn:conn() delete m_clt_buf; delete m_srv_buf;void conn:init_clt( int sockfd, const sockaddr_in& client_addr ) m_cltfd = sockfd; m_clt_address = client_addr;void conn:init_srv( int sockfd, const sockaddr_in& server_addr ) m_srvfd = sockfd; m

18、_srv_address = server_addr;void conn:reset() m_clt_read_idx = 0; m_clt_write_idx = 0; m_srv_read_idx = 0; m_srv_write_idx = 0; m_srv_closed = false; m_cltfd = -1; memset( m_clt_buf, '0', BUF_SIZE ); memset( m_srv_buf, '0', BUF_SIZE );RET_CODE conn:read_clt() int bytes_read = 0; while

19、( true ) if( m_clt_read_idx >= BUF_SIZE ) log( LOG_ERR, _FILE_, _LINE_, "%s", "the client read buffer is full, let server write" ); return BUFFER_FULL; bytes_read = recv( m_cltfd, m_clt_buf + m_clt_read_idx, BUF_SIZE - m_clt_read_idx, 0 ); if ( bytes_read = -1 ) if( errno = EA

20、GAIN | errno = EWOULDBLOCK ) break; return IOERR; else if ( bytes_read = 0 ) return CLOSED; m_clt_read_idx += bytes_read; return ( ( m_clt_read_idx - m_clt_write_idx ) > 0 ) ? OK : NOTHING;RET_CODE conn:read_srv() int bytes_read = 0; while( true ) if( m_srv_read_idx >= BUF_SIZE ) log( LOG_ERR,

21、 _FILE_, _LINE_, "%s", "the server read buffer is full, let client write" ); return BUFFER_FULL; bytes_read = recv( m_srvfd, m_srv_buf + m_srv_read_idx, BUF_SIZE - m_srv_read_idx, 0 ); if ( bytes_read = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) break; return IOERR; else if

22、( bytes_read = 0 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "the server should not close the persist connection" ); return CLOSED; m_srv_read_idx += bytes_read; return ( ( m_srv_read_idx - m_srv_write_idx ) > 0 ) ? OK : NOTHING;RET_CODE conn:write_srv() int bytes_write = 0; while(

23、true ) if( m_clt_read_idx <= m_clt_write_idx ) m_clt_read_idx = 0; m_clt_write_idx = 0; return BUFFER_EMPTY; bytes_write = send( m_srvfd, m_clt_buf + m_clt_write_idx, m_clt_read_idx - m_clt_write_idx, 0 ); if ( bytes_write = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) return TRY_AGAIN; log( L

24、OG_ERR, _FILE_, _LINE_, "write server socket failed, %s", strerror( errno ) ); return IOERR; else if ( bytes_write = 0 ) return CLOSED; m_clt_write_idx += bytes_write; RET_CODE conn:write_clt() int bytes_write = 0; while( true ) if( m_srv_read_idx <= m_srv_write_idx ) m_srv_read_idx = 0

25、; m_srv_write_idx = 0; return BUFFER_EMPTY; bytes_write = send( m_cltfd, m_srv_buf + m_srv_write_idx, m_srv_read_idx - m_srv_write_idx, 0 ); if ( bytes_write = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) return TRY_AGAIN; log( LOG_ERR, _FILE_, _LINE_, "write client socket failed, %s",

26、strerror( errno ) ); return IOERR; else if ( bytes_write = 0 ) return CLOSED; m_srv_write_idx += bytes_write; #ifndef FDWRAPPER_H#define FDWRAPPER_H#include <unistd.h>#include <fcntl.h>#include <sys/epoll.h>int setnonblocking( int fd ) int old_option = fcntl( fd, F_GETFL ); int new

27、_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option;void add_read_fd( int epollfd, int fd ) epoll_event event; event.data.fd = fd; event.events = EPOLLIN | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd );void add_write_fd( int epo

28、llfd, int fd ) epoll_event event; event.data.fd = fd; event.events = EPOLLOUT | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd );void closefd( int epollfd, int fd ) epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 ); close( fd );void removefd( int epollfd, int fd ) epoll_ct

29、l( epollfd, EPOLL_CTL_DEL, fd, 0 );void modfd( int epollfd, int fd, int ev ) epoll_event event; event.data.fd = fd; event.events = ev | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );#endif#include <stdio.h>#include <time.h>#include <string.h>#include "log.h"

30、;static int level = LOG_INFO;static int LOG_BUFFER_SIZE = 2048;static const char* loglevels = "emerge!", "alert!", "critical!", "error!", "warn!", "notice:", "info:", "debug:"void set_loglevel( int log_level ) level = lo

31、g_level;void log( int log_level, const char* file_name, int line_num, const char* format, . ) if ( log_level > level ) return; time_t tmp = time( NULL ); struct tm* cur_time = localtime( &tmp ); if ( ! cur_time ) return; char arg_buffer LOG_BUFFER_SIZE ; memset( arg_buffer, '0', LOG_B

32、UFFER_SIZE ); strftime( arg_buffer, LOG_BUFFER_SIZE - 1, " %x %X ", cur_time ); printf( "%s", arg_buffer ); printf( "%s:%04d ", file_name, line_num ); printf( "%s ", loglevels log_level - LOG_EMERG ); va_list arg_list; va_start( arg_list, format ); memset( arg

33、_buffer, '0', LOG_BUFFER_SIZE ); vsnprintf( arg_buffer, LOG_BUFFER_SIZE - 1, format, arg_list ); printf( "%sn", arg_buffer ); fflush( stdout ); va_end( arg_list );#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#incl

34、ude <assert.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <stdlib.h>#include <sys/epoll.h>#include <signal.h>#include <sys/wait.h>#include <sys/stat.h>#include <vector>#in

35、clude "log.h"#include "conn.h"#include "mgr.h"#include "processpool.h"using std:vector;static const char* version = "1.0"static void usage( const char* prog ) log( LOG_INFO, _FILE_, _LINE_, "usage: %s -h -v -f config_file", prog );int main(

36、 int argc, char* argv ) char cfg_file1024; memset( cfg_file, '0', 100 ); int option; while ( ( option = getopt( argc, argv, "f:xvh" ) ) != -1 ) switch ( option ) case 'x': set_loglevel( LOG_DEBUG ); break; case 'v': log( LOG_INFO, _FILE_, _LINE_, "%s %s",

37、argv0, version ); return 0; case 'h': usage( basename( argv 0 ) ); return 0; case 'f': memcpy( cfg_file, optarg, strlen( optarg ) ); break; case '?': log( LOG_ERR, _FILE_, _LINE_, "un-recognized option %c", option ); usage( basename( argv 0 ) ); return 1; if( cfg_fi

38、le0 = '0' ) log( LOG_ERR, _FILE_, _LINE_, "%s", "please specifiy the config file" ); return 1; int cfg_fd = open( cfg_file, O_RDONLY ); if( !cfg_fd ) log( LOG_ERR, _FILE_, _LINE_, "read config file met error: %s", strerror( errno ) ); return 1; struct stat ret_s

39、tat; if( fstat( cfg_fd, &ret_stat ) < 0 ) log( LOG_ERR, _FILE_, _LINE_, "read config file met error: %s", strerror( errno ) ); return 1; char* buf = new char ret_stat.st_size + 1; memset( buf, '0', ret_stat.st_size + 1 ); ssize_t read_sz = read( cfg_fd, buf, ret_stat.st_size

40、 ); if ( read_sz < 0 ) log( LOG_ERR, _FILE_, _LINE_, "read config file met error: %s", strerror( errno ) ); return 1; vector< host > balance_srv; vector< host > logical_srv; host tmp_host; memset( tmp_host.m_hostname, '0', 1024 ); char* tmp_hostname; char* tmp_port;

41、char* tmp_conncnt; bool opentag = false; char* tmp = buf; char* tmp2 = NULL; char* tmp3 = NULL; char* tmp4 = NULL; while( tmp2 = strpbrk( tmp, "n" ) ) *tmp2+ = '0' if( strstr( tmp, "<logical_host>" ) ) if( opentag ) log( LOG_ERR, _FILE_, _LINE_, "%s", &quo

42、t;parse config file failed" ); return 1; opentag = true; else if( strstr( tmp, "</logical_host>" ) ) if( !opentag ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed" ); return 1; logical_srv.push_back( tmp_host ); memset( tmp_host.m_hostname, 

43、9;0', 1024 ); opentag = false; else if( tmp3 = strstr( tmp, "<name>" ) ) tmp_hostname = tmp3 + 6; tmp4 = strstr( tmp_hostname, "</name>" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed" ); return 1; *tmp4 = '0&#

44、39; memcpy( tmp_host.m_hostname, tmp_hostname, strlen( tmp_hostname ) ); else if( tmp3 = strstr( tmp, "<port>" ) ) tmp_port = tmp3 + 6; tmp4 = strstr( tmp_port, "</port>" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed"

45、 ); return 1; *tmp4 = '0' tmp_host.m_port = atoi( tmp_port ); else if( tmp3 = strstr( tmp, "<conns>" ) ) tmp_conncnt = tmp3 + 7; tmp4 = strstr( tmp_conncnt, "</conns>" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed&

46、quot; ); return 1; *tmp4 = '0' tmp_host.m_conncnt = atoi( tmp_conncnt ); else if( tmp3 = strstr( tmp, "Listen" ) ) tmp_hostname = tmp3 + 6; tmp4 = strstr( tmp_hostname, ":" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed" )

47、; return 1; *tmp4+ = '0' tmp_host.m_port = atoi( tmp4 ); memcpy( tmp_host.m_hostname, tmp3, strlen( tmp3 ) ); balance_srv.push_back( tmp_host ); memset( tmp_host.m_hostname, '0', 1024 ); tmp = tmp2; if( balance_srv.size() = 0 | logical_srv.size() = 0 ) log( LOG_ERR, _FILE_, _LINE_, &

48、quot;%s", "parse config file failed" ); return 1; const char* ip = balance_srv0.m_hostname; int port = balance_srv0.m_port; int listenfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( listenfd >= 0 ); int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) );

49、address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( listenfd, 5 ); assert( ret != -1 ); /memset( cfg_host.m_hostname, '0

50、9;, 1024 ); /memcpy( cfg_host.m_hostname, "", strlen( "" ) ); /cfg_host.m_port = 54321; /cfg_host.m_conncnt = 5; processpool< conn, host, mgr >* pool = processpool< conn, host, mgr >:create( listenfd, logical_srv.size() ); if( pool ) pool->run( logical_srv ); delete pool; close( listenfd ); return 0;#incl

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論