版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
ApacheWeb服務(wù)器簡(jiǎn)史Apache1ApacheWeb服務(wù)器誕生于1995年。它起源于早期的由NCSA編寫(xiě)的NCSA服務(wù)器,并在其基礎(chǔ)上進(jìn)行構(gòu)建。第一個(gè)以Apache命名的服務(wù)器產(chǎn)品發(fā)布于1999年12月,版本為1.0.0。作為Web服務(wù)器,Apache隨即取得成功。到1996年4月,Apache已經(jīng)取代NCSA服務(wù)器,成為Internet上使用最廣泛的Web服務(wù)器,至今依然如此。Apache并不是通常意義上的應(yīng)用平臺(tái):原生API非常有限,同其他產(chǎn)品具有的高級(jí)別編程層次相比,Apache需要開(kāi)發(fā)人員付出更多的努力來(lái)達(dá)到同樣的效果。然而,在一些非常有用的功能模塊中最值得一提的是已經(jīng)開(kāi)發(fā)出來(lái)的十分優(yōu)秀的mod_rewrite模塊。Apache引起第一次比較大的反響的應(yīng)用開(kāi)發(fā)框架是Perl語(yǔ)言,由CGI和mod_perl支持。由于mod_perl第一次采用了真正有用而且容易使用的API,大量的編程書(shū)籍和開(kāi)發(fā)人員都集中在Perl上。很快,JavaServlet及大量的腳本語(yǔ)言,包括如今的市場(chǎng)領(lǐng)頭羊PHP等,都發(fā)布了各自的API。Apache1服務(wù)器的最后一個(gè)主要版本為1.3,發(fā)布于1998年6月。盡管新的開(kāi)發(fā)工作移植到Apache2已經(jīng)很長(zhǎng)時(shí)間,但Apache1.3仍然處于維護(hù)模式,至今依然流行。Apache2Apache的開(kāi)發(fā)人員認(rèn)識(shí)到Apache最初的架構(gòu)具有局限性,比較粗糙,于是在2000年開(kāi)始建立新的代碼倉(cāng)庫(kù)(codebase)主分支,并在此代碼倉(cāng)庫(kù)的基礎(chǔ)上于2002年4月創(chuàng)建了Apache2.0的第一個(gè)發(fā)布版本。Apache2包括以下優(yōu)良特性:原生API得到很大幅度改進(jìn),使APR庫(kù)成為單獨(dú)的實(shí)體。這在很大程度上幫助開(kāi)發(fā)人員克服了C語(yǔ)言編程的缺陷,特別是交叉編譯平臺(tái)和資源管理方面的缺陷。通過(guò)使用Apache2,C程序員可以達(dá)到通常被認(rèn)為是高層次語(yǔ)言和腳本語(yǔ)言才能達(dá)到的高效率。新的拓展架構(gòu)帶來(lái)了全新層次的應(yīng)用程序開(kāi)發(fā),同時(shí)也為以前的模塊和應(yīng)用程序提供了更為簡(jiǎn)潔的實(shí)現(xiàn)方法。本書(shū)將會(huì)詳細(xì)介紹如何利用這個(gè)新的拓展架構(gòu)。新的內(nèi)核架構(gòu)讓Apache2成為真正的跨平臺(tái)服務(wù)器。操作系統(tǒng)層自身成為一個(gè)模塊(MPM),使得該模塊可以被各種操作系統(tǒng)裝載。Apache1是一個(gè)UNIX應(yīng)用程序,移植到其他平臺(tái)上會(huì)受到很多的限制,一些UNIX特性使得Apache1在其他平臺(tái)(如Windows和Netware)上性能較差,而Apache2擺脫了這些特性的限制,使其成為一個(gè)真正的跨平臺(tái)服務(wù)器。基于線(xiàn)程的MPM模塊的引入也增強(qiáng)了UNIX上很多應(yīng)用程序的可擴(kuò)展性。Apache2的缺點(diǎn)在于它的API不能向前兼容Apache1,因此一些第三方的模塊和應(yīng)用程序需要緩慢地升級(jí)到Apache2。作為一個(gè)穩(wěn)定版本,Apache2.2于2005年12月發(fā)布,相比之前版本具有一些較大的改進(jìn)。Apache2.2保留并拓展了Apache2.0的API,因此,為Apache2.0所編寫(xiě)的模塊和應(yīng)用程序同樣適用于Apache2.2。Apache2.2版本對(duì)可擴(kuò)展性和應(yīng)用程序架構(gòu)等方面進(jìn)行了顯著改進(jìn)。如果說(shuō)Apache2.0提供了功能強(qiáng)大的應(yīng)用平臺(tái)基礎(chǔ),那么Apache2.2則在此基礎(chǔ)上進(jìn)行了添磚加瓦。Apache軟件基金會(huì)Apache軟件基金會(huì)(ASF)為一系列應(yīng)用范圍廣泛的開(kāi)源軟件項(xiàng)目提供組織上、法律上和財(cái)政上的支持。Apache軟件基金會(huì)建立了一整套框架來(lái)管理知識(shí)產(chǎn)權(quán)和財(cái)政捐獻(xiàn),同時(shí),限制捐獻(xiàn)者潛在的、合法的資源泄漏。通過(guò)精誠(chéng)合作的項(xiàng)目開(kāi)發(fā)流程,Apache項(xiàng)目交付了企業(yè)級(jí)的、免費(fèi)獲取的軟件產(chǎn)品,吸引大量的社區(qū)用戶(hù)使用。注重實(shí)效的Apache許可證(ApacheLicense)使得無(wú)論是商業(yè)用戶(hù)還是個(gè)人用戶(hù)都易于部署Apache的產(chǎn)品。Apache軟件基金會(huì)的前身是Apache組織(ApacheGroup)。Apache軟件基金會(huì)是一個(gè)非盈利的組織,基于成員制,以保證Apache項(xiàng)目在個(gè)人志愿者參與之外能夠繼續(xù)存在。如果個(gè)人承諾與開(kāi)源軟件開(kāi)發(fā)項(xiàng)目合作,并不斷地參與和貢獻(xiàn)Apache軟件基金會(huì)的項(xiàng)目,那么他(她)就有資格成為Apache軟件基金會(huì)的成員。通過(guò)Apache基金會(huì)現(xiàn)有大部分成員的贊同和任命,個(gè)人才能成為軟件基金會(huì)的成員。因此,Apache軟件基金會(huì)為它所直接服務(wù)的社區(qū)所掌控,成員都為社區(qū)內(nèi)的項(xiàng)目進(jìn)行協(xié)作。Apache軟件基金會(huì)的成員按照基金會(huì)的規(guī)章制度,每隔一段時(shí)間選舉一個(gè)董事會(huì),管理基金會(huì)的組織事務(wù),由董事會(huì)任命成員監(jiān)管基金會(huì)的日常事務(wù)。社區(qū)可以公開(kāi)獲取Apache基金會(huì)運(yùn)作的記錄。功績(jī)組織模式(Meritocracy)很多軟件產(chǎn)品都是在一個(gè)開(kāi)放源代碼的許可證之下進(jìn)行開(kāi)發(fā)的,ApacheWeb服務(wù)器則與此不同°Apache不是由某個(gè)開(kāi)發(fā)者發(fā)起的(而Linux內(nèi)核、Perl語(yǔ)言和Python語(yǔ)言都是由某個(gè)人發(fā)起的),而是一個(gè)由各種各樣的人所組成的團(tuán)隊(duì)發(fā)起的,這些人具有相同的興趣愛(ài)好,通過(guò)交換信息、補(bǔ)丁和各種建議認(rèn)識(shí)彼此。當(dāng)Apache開(kāi)發(fā)團(tuán)隊(duì)不再延續(xù)NCSA版本,而是轉(zhuǎn)向開(kāi)發(fā)Apache自己的版本時(shí),越來(lái)越多的人被這個(gè)項(xiàng)目所吸引,加入這個(gè)團(tuán)隊(duì)進(jìn)行開(kāi)發(fā)。最初,他們可能是發(fā)布一些小的補(bǔ)丁,給出一些開(kāi)發(fā)建議,或者在郵件列表上回復(fù)一些問(wèn)題,逐步貢獻(xiàn)更多的力量,在開(kāi)發(fā)中發(fā)揮著越來(lái)越重要的作用。當(dāng)Apache開(kāi)發(fā)團(tuán)隊(duì)覺(jué)得某個(gè)人已經(jīng)獲得足夠的權(quán)限成為開(kāi)發(fā)社區(qū)的一部分時(shí),開(kāi)發(fā)團(tuán)隊(duì)將授予這個(gè)人直接訪(fǎng)問(wèn)代碼倉(cāng)庫(kù)的權(quán)限。這個(gè)方法不僅能夠擴(kuò)充團(tuán)隊(duì)力量,增強(qiáng)開(kāi)發(fā)Apache的能力,而且能夠使開(kāi)發(fā)團(tuán)隊(duì)運(yùn)作的效率更高。我們把這個(gè)方法稱(chēng)為功績(jī)組織模式。這種模式使得開(kāi)發(fā)團(tuán)隊(duì)不斷壯大,而且沒(méi)有內(nèi)部矛盾和紛爭(zhēng)。在其他模式下,權(quán)利可能是稀缺和保留的資源,而在Apache開(kāi)發(fā)團(tuán)隊(duì)中,開(kāi)發(fā)團(tuán)隊(duì)的新成員被看作是希望幫助團(tuán)隊(duì)進(jìn)行開(kāi)發(fā)的志愿者,而不是想占據(jù)權(quán)位的投機(jī)者。同時(shí),由于Apache團(tuán)隊(duì)從不缺乏希望加入的新成員,因此,它不會(huì)因?yàn)樵谝粋€(gè)充滿(mǎn)競(jìng)爭(zhēng)的環(huán)境中缺乏優(yōu)秀人才而盲目地?cái)U(kuò)充團(tuán)隊(duì),從而導(dǎo)致開(kāi)發(fā)團(tuán)隊(duì)成員良莠不齊。相反地,它嚴(yán)格對(duì)待團(tuán)隊(duì)的每個(gè)成員,要求每個(gè)成員都具備有據(jù)可尋的貢獻(xiàn)和積極向上的態(tài)度。Apache團(tuán)隊(duì)是一個(gè)虛擬社區(qū),因此它是一個(gè)全球范圍的社區(qū),不受地域限制。角色Apache開(kāi)發(fā)團(tuán)隊(duì)具有以下的一些角色。用戶(hù)用戶(hù)是指使用Apache軟件的人。用戶(hù)以缺陷報(bào)告和功能建議的形式向Apache項(xiàng)目的開(kāi)發(fā)人員提供反饋,從而對(duì)開(kāi)發(fā)團(tuán)隊(duì)做出貢獻(xiàn)。用戶(hù)也可以參與Apache社區(qū),通過(guò)郵件列表和用戶(hù)支持論壇幫助其他用戶(hù)。開(kāi)發(fā)者開(kāi)發(fā)者通過(guò)提交代碼和文檔的方式為項(xiàng)目做貢獻(xiàn)。開(kāi)發(fā)者比用戶(hù)的工作要多,他們活躍在開(kāi)發(fā)郵件列表上,積極參與討論,提供補(bǔ)丁、文檔、建議和批評(píng)。開(kāi)發(fā)人員也被當(dāng)作是貢獻(xiàn)者。提交者提交人員是開(kāi)發(fā)者,他被賦予了代碼倉(cāng)庫(kù)的寫(xiě)權(quán)限,并且簽署了貢獻(xiàn)者許可證協(xié)議(Contributor
LicenseAgreement,CLA)。所有的提交者都有的郵件地址。提交者在處理補(bǔ)丁時(shí)不需要依靠
其他人,可以獨(dú)自做出短期的決定,并服從項(xiàng)目管理委員會(huì)(ProjectManagementCommittee,PMC)的監(jiān)項(xiàng)目管理委員會(huì)成員項(xiàng)目管理委員會(huì)成員是由開(kāi)發(fā)者或者提交者通過(guò)功績(jī)選舉產(chǎn)生的,作為其為項(xiàng)目進(jìn)展所承擔(dān)任務(wù)的酬勞。項(xiàng)目管理委員會(huì)成員具有代碼倉(cāng)庫(kù)的寫(xiě)權(quán)限、的郵件地址、社區(qū)相關(guān)決定的投票權(quán),以及建議把某個(gè)活躍用戶(hù)提升為提交者的權(quán)利。項(xiàng)目管理委員會(huì)是總體上實(shí)施項(xiàng)目控制的實(shí)體。Apache軟件基金會(huì)成員Apache軟件基金會(huì)成員是根據(jù)其在基金會(huì)中的角色進(jìn)展和演變,以及每個(gè)角色所取得的功績(jī),由Apache軟件基金會(huì)的現(xiàn)有成員選擇并任命的。Apache軟件基金會(huì)成員負(fù)責(zé)管理基金會(huì),如項(xiàng)目相關(guān)的核心事務(wù)、交叉項(xiàng)目活動(dòng)等。從法律上來(lái)說(shuō),Apache軟件基金會(huì)成員是基金會(huì)的股東之一?;饡?huì)成員擁有選舉董事會(huì)的權(quán)利、成為董事會(huì)候選人的權(quán)利、建議提升某個(gè)提交者成為基金會(huì)成員的權(quán)利,以及廣泛參與基金會(huì)內(nèi)部其他角色的權(quán)利。哲學(xué)理念盡管這不是官方的列表,但其中的信念已經(jīng)被認(rèn)為是Apache基金會(huì)的核心哲學(xué)理念。這些理念有時(shí)候被引用為“Apache方法”:協(xié)作化的軟件開(kāi)發(fā)商業(yè)友好的標(biāo)準(zhǔn)許可證永遠(yuǎn)保證高質(zhì)量的軟件成員之間的交往要互相尊重,誠(chéng)實(shí),以技術(shù)為主依據(jù)標(biāo)準(zhǔn)的忠實(shí)實(shí)現(xiàn)強(qiáng)制的安全特性Apache開(kāi)發(fā)流程Apache的開(kāi)發(fā)流程既可以是自上而下的,也可以是自下而上的。采用自上而下的設(shè)計(jì)方法時(shí),可以增加一些很棒的想法,如需要代碼重寫(xiě)或者新的組件所帶來(lái)的關(guān)鍵新特性、新功能,這些想法可能需要幾個(gè)月甚至幾年才能從概念變?yōu)槌墒飚a(chǎn)品。而采用自下而上的設(shè)計(jì)方法時(shí),可以增加一些小的補(bǔ)丁,用來(lái)修改一些軟件Bug或者增加一些新的特性,這些小的補(bǔ)丁很容易融合到目前的軟件版本中。模塊式開(kāi)發(fā)方法通常介于軟件開(kāi)發(fā)的宏觀(guān)方法和微觀(guān)方法之間。模塊是一個(gè)自包含的插件,通常是開(kāi)發(fā)者(大多數(shù)情況下是其他人)基于某種興趣而實(shí)現(xiàn)的新特性。一個(gè)模塊可能實(shí)現(xiàn)了Web服務(wù)器的核心功能,也可能實(shí)現(xiàn)了一個(gè)通用的服務(wù),還可能實(shí)現(xiàn)了一個(gè)較小但是較為重要的功能,甚至只是一個(gè)單一目的的應(yīng)用。如果某個(gè)模塊實(shí)現(xiàn)了大家都比較感興趣的功能,而且作者愿意公布,就可以集成到Apache的核心發(fā)布版本中。但是,如果該模塊需要額外的支持(如第三方的庫(kù)),或者可能會(huì)涉及該模塊的許可甚至是知識(shí)產(chǎn)權(quán)的因素,那么,該模塊可能就不會(huì)被集成到Apache的核心發(fā)布版本中,而是通過(guò)它的開(kāi)發(fā)者或者第三方獨(dú)立地發(fā)布,就像支持Apache的公司或者Linux版本的發(fā)行商那么做。Apache代碼倉(cāng)庫(kù)和其他的軟件項(xiàng)目一樣,Apache也維護(hù)著一個(gè)代碼倉(cāng)庫(kù)。這個(gè)代碼倉(cāng)庫(kù)以項(xiàng)目為單位,和Web服務(wù)器相關(guān)的是httpd項(xiàng)目(包括代碼、文檔和編譯文件)和apr項(xiàng)目。Subversion所有的Apache代碼都保存在代碼倉(cāng)庫(kù)中,可以通過(guò)進(jìn)行訪(fǎng)問(wèn)。代碼使用SVN進(jìn)行管理,它是最近(2004年)開(kāi)始使用的,之前我們使用的是和其功能類(lèi)似、歷史悠久的CVS系統(tǒng)。代碼倉(cāng)庫(kù)的讀取權(quán)限是公開(kāi)的,但是寫(xiě)權(quán)限只有提交者才擁有。讀權(quán)限允許任何人查看Apache開(kāi)發(fā)過(guò)程中所走過(guò)的足跡,包括回顧任何單一或者累計(jì)的修改,針對(duì)這些修改所作的簡(jiǎn)要的解釋?zhuān)ɡ缧薷腂ug、新的功能、內(nèi)部改進(jìn)等),以及修改的日期和參與修改的人員。分支:主線(xiàn)、開(kāi)發(fā)版本和穩(wěn)定版本代碼倉(cāng)庫(kù)中包含一個(gè)主線(xiàn)和幾個(gè)分支,其中的任何文件的默認(rèn)版本都是主線(xiàn)。在Apache項(xiàng)目中,主線(xiàn)代表正在進(jìn)行中的工作。從定義上可以看出,它是未經(jīng)過(guò)測(cè)試的版本,一般都包括一些實(shí)驗(yàn)性的代碼。Apache當(dāng)前的穩(wěn)定分支是Apachehttpd2.2,可以在/branches/2.2.x/目錄下找到。比較老的版本(如2.0和1.3)盡管已經(jīng)不再是主要的開(kāi)發(fā)方向,但是它們的分支還在維護(hù)中(盡管是精簡(jiǎn)地維護(hù))。有時(shí)候也會(huì)為一些實(shí)驗(yàn)代碼特別地創(chuàng)建一些分支,作為測(cè)試的基礎(chǔ)。例如,當(dāng)Apache2.2處于beta版測(cè)試時(shí),為了支持異步I/O,需要對(duì)內(nèi)核代碼進(jìn)行一些實(shí)質(zhì)性的重寫(xiě)。這些修改后的代碼對(duì)于主線(xiàn)來(lái)說(shuō)過(guò)于實(shí)驗(yàn)化,因此,開(kāi)發(fā)者決定創(chuàng)建一個(gè)新的開(kāi)發(fā)分支來(lái)處理它們。這個(gè)新的分支隨后逐漸地穩(wěn)定下來(lái)并融入到主線(xiàn)中,并最終被包含在下一個(gè)穩(wěn)定版本(2.4版)中。審查和通過(guò)Apache的開(kāi)發(fā)人員針對(duì)穩(wěn)定版本和開(kāi)發(fā)版本的代碼采用不同的開(kāi)發(fā)策略進(jìn)行處理。穩(wěn)定版本的代碼總是遵從審閱并提交的方式(Review-Then-Commit,RTC),這就意味著任何將要加入到標(biāo)記為穩(wěn)定版本分支的代碼,即使是最微不足道的補(bǔ)丁,也必須通過(guò)一個(gè)嚴(yán)格的審閱過(guò)程。開(kāi)發(fā)版本的代碼遵從提交并審閱的方式(Commit-Then-Review,CTR),這就意味著代碼可能被某個(gè)提交者單方面地進(jìn)行了增加、修改和刪除,然后在恰當(dāng)?shù)臅r(shí)期由其他開(kāi)發(fā)者進(jìn)行審閱(當(dāng)然,SVN使得對(duì)某個(gè)改變進(jìn)行逆向操作變得非常容易)。不過(guò),一些主要的變動(dòng)需要在提交之前就進(jìn)行審閱,或者使用單獨(dú)的開(kāi)發(fā)分支進(jìn)行處理。1?3?1.4增加新的功能(backport)新的代碼首先加入主線(xiàn)。如果某個(gè)開(kāi)發(fā)人員想讓這個(gè)代碼成為穩(wěn)定分支的一部分(通常是修改了Bug或是做了一點(diǎn)改進(jìn)),那么這個(gè)代碼就將進(jìn)入backporting階段。該階段使用一個(gè)叫做STATUS的狀態(tài)文件,包含了backporting的當(dāng)前情況列表,如為backport進(jìn)行的投票情況等。為了保證backporting的質(zhì)量,代碼的任何變動(dòng)必須從提交者那里得到至少三張支持票。一張支持票意味著投票人已經(jīng)審閱了這個(gè)變動(dòng),并對(duì)此表示認(rèn)可,因此,三張支持票就明確意味著這個(gè)變動(dòng)確實(shí)不錯(cuò)即使是最簡(jiǎn)單的Bug修改也要遵守這個(gè)規(guī)則,這就是說(shuō)為了得到足夠多提交者的同意,有時(shí)候一個(gè)不是很重要的Bug修改也得需要很長(zhǎng)時(shí)間。如果收到了三張支持票并且沒(méi)有反對(duì)票,這個(gè)變動(dòng)就可以加入到下一個(gè)穩(wěn)定分支中了。可能審閱了這個(gè)變動(dòng)的提交者對(duì)此并不滿(mǎn)意,他將對(duì)此保留意見(jiàn),甚至投反對(duì)票。投反對(duì)票的規(guī)則是必須附帶一個(gè)說(shuō)明,以及(或者)一個(gè)能夠?qū)崿F(xiàn)該變動(dòng)目標(biāo)的可選方案。被投了反對(duì)票的變動(dòng)要么被放棄了,要么把其中的錯(cuò)誤修正之后再次提交進(jìn)行重新投票。反對(duì)票和保留意見(jiàn)通常會(huì)在開(kāi)發(fā)者論壇中進(jìn)行相關(guān)的討論之后被進(jìn)行處理。發(fā)布Apache有時(shí)會(huì)發(fā)布新的版本。當(dāng)前穩(wěn)定代碼版本(在本書(shū)正在寫(xiě)作時(shí)為2.2.x版)的發(fā)布使得用戶(hù)可以感受到Apache的最新進(jìn)展,也修改了一些Bug。這些發(fā)布版本將會(huì)打上最佳版本的標(biāo)簽并推薦給用戶(hù)。通常由于開(kāi)發(fā)者覺(jué)得已經(jīng)有足夠多的小變動(dòng)積聚起來(lái)了,達(dá)到了新版本發(fā)布的要求,這樣一個(gè)新的版本就發(fā)布了。不過(guò)有時(shí)候一個(gè)新的版本可能是因?yàn)槟硞€(gè)安全問(wèn)題引起開(kāi)發(fā)者的注意而匆忙發(fā)布的。發(fā)布負(fù)責(zé)人通常由開(kāi)發(fā)者志愿擔(dān)任,負(fù)責(zé)管理發(fā)布流程并創(chuàng)建發(fā)布版本,其他的開(kāi)發(fā)者將會(huì)全神貫注于開(kāi)發(fā)在STATUS文件中已經(jīng)核準(zhǔn)的、但還沒(méi)有解決的更新,并將其融入到穩(wěn)定版本中。目前的策略是偶數(shù)版本的分支是穩(wěn)定的,而奇數(shù)版本的分支打算供開(kāi)發(fā)使用。因此2.0.x版本(2002年4月發(fā)布)和2.2.x版本都是穩(wěn)定的,而2.1.x發(fā)布版供Apache2.2版本的alpha測(cè)試和beta測(cè)試使用。Apache2.1版本經(jīng)過(guò)接近10個(gè)月的alpha測(cè)試和3個(gè)月的beta測(cè)試之后才成為最終的2.2穩(wěn)定版本。一個(gè)發(fā)布版需要在每一個(gè)支持的平臺(tái)上經(jīng)過(guò)編譯、安裝、運(yùn)行的測(cè)試。這些步驟對(duì)于穩(wěn)定的發(fā)布版本來(lái)說(shuō)是必需的。對(duì)于開(kāi)發(fā)版本,盡管不是那么嚴(yán)格,也是應(yīng)當(dāng)如此。為了保證發(fā)布版本滿(mǎn)足這些要求,發(fā)布負(fù)責(zé)人首先通過(guò)一個(gè)合適的SVN分支為這個(gè)版本創(chuàng)建一個(gè)Build版本,然后把這個(gè)版本告知Apache的開(kāi)發(fā)者和測(cè)試者。這就在其發(fā)布之前提供足夠的時(shí)間,讓更多的開(kāi)發(fā)者和測(cè)試者對(duì)其在不同的硬件環(huán)境、操作系統(tǒng)和應(yīng)用環(huán)境上進(jìn)行安裝和測(cè)試。如果在測(cè)試中發(fā)現(xiàn)了一個(gè)嚴(yán)重問(wèn)題,那么這個(gè)Build版將不被發(fā)布。所有的發(fā)布版本都由發(fā)布管理人進(jìn)行可靠的PGP簽名。很多Apache開(kāi)發(fā)者的公鑰,包括所有發(fā)布管理人的,都可以在ht,t,p:///dist,/ht,t,pd/KEY獲得。開(kāi)發(fā)者論壇ApacheWeb服務(wù)器最主要的開(kāi)發(fā)者論壇就是dev@郵件列表。所有和Apache開(kāi)發(fā)相關(guān)的技術(shù)細(xì)節(jié)都在這里討論。一個(gè)與此類(lèi)似的開(kāi)發(fā)者郵件列表dev@是針對(duì)APR開(kāi)發(fā)的。這些論壇都是100%對(duì)外開(kāi)放的,所有的討論都被歸檔在一些地方(本章結(jié)尾部分的參考地址)。另外一個(gè)比較流行的開(kāi)發(fā)者論壇是互聯(lián)網(wǎng)中繼聊天(InternetRelayChat,IRC)。關(guān)于Apache的開(kāi)發(fā)者頻道是上的#httpd-dev和#apr。這些討論地點(diǎn)都是完全對(duì)外開(kāi)放的。在/的ApacheBugzilla是一個(gè)可以搜索的數(shù)據(jù)庫(kù),包括Bug報(bào)告、提升要求和補(bǔ)丁,也包括目前的和歷史的數(shù)據(jù)。這個(gè)數(shù)據(jù)庫(kù)也是完全對(duì)外開(kāi)放的。不過(guò)要注意的是,既然是一個(gè)完全開(kāi)放的數(shù)據(jù)庫(kù),它會(huì)含有很多的虛假報(bào)告(有些由于不能被結(jié)束而顯示為“再次開(kāi)放”)和不能被驗(yàn)證真?zhèn)蔚膱?bào)告。考慮到某些補(bǔ)丁可能對(duì)用戶(hù)有用,但是這些補(bǔ)丁卻沒(méi)有被標(biāo)準(zhǔn)的Apache發(fā)布版包括進(jìn)來(lái),因此這個(gè)數(shù)據(jù)庫(kù)也包含了一些故意保留下來(lái)的、標(biāo)記為“補(bǔ)丁可獲取”(PatchAvailable)的報(bào)告。包含所有代碼和變動(dòng)的最完整、最精確的歸檔是位于的Subversion代碼倉(cāng)庫(kù)。這個(gè)代碼倉(cāng)庫(kù)隨著代碼的變化而實(shí)時(shí)地被更新。讀權(quán)限是開(kāi)放和公開(kāi)的,而寫(xiě)權(quán)限只授予認(rèn)證過(guò)的提交者。在Subversion中值得注意的是STATUS文件和CHANGES文件,前者包括了目前的討論和投票情況,而后者則提供了針對(duì)某個(gè)穩(wěn)定/發(fā)布版本的變動(dòng)的執(zhí)行總結(jié)。開(kāi)發(fā)人員Apache很重要的一個(gè)特點(diǎn)就是用戶(hù)群體的多樣性和開(kāi)發(fā)群體的多樣性oApache項(xiàng)目不存在由某個(gè)公司或者某些公司主導(dǎo)的問(wèn)題。有些開(kāi)發(fā)者(包括作者在內(nèi))既是一個(gè)自由職業(yè)的顧問(wèn),也是一個(gè)小公司的員工。其他的開(kāi)發(fā)者有些來(lái)自像IBM、RedHat和Novell這樣的大公司,有些來(lái)自像Google、Yahoo!和AskJeeves這樣的大型客戶(hù),也有些來(lái)自科研院校和其他的非商業(yè)組織。雖然大部分開(kāi)發(fā)者都是企業(yè)的員工,但是自由職業(yè)者的數(shù)量超過(guò)了任何一個(gè)公司的人數(shù)。更為重要的是,開(kāi)發(fā)者的多樣性反映了Apache廣泛的應(yīng)用范圍。那些超級(jí)繁忙的站點(diǎn)(如CNN和HEAnet)需要用24X7的時(shí)間承擔(dān)成千上萬(wàn)的并發(fā)用戶(hù)負(fù)載,主要關(guān)注性能、擴(kuò)展性和穩(wěn)定性;而某些應(yīng)用站點(diǎn),例如作者的網(wǎng)站Valet,主要關(guān)注如何把Apache從它最初的Web服務(wù)器的角色拓展為應(yīng)用服務(wù)器;電子商務(wù)網(wǎng)站主要關(guān)注安全性和可靠性;主機(jī)托管公司需要在維護(hù)安全和穩(wěn)定的同時(shí)支持需求差異巨大的用戶(hù)和代理控制。擁有數(shù)量眾多來(lái)自各行各業(yè)的、活躍的開(kāi)發(fā)者,使得Apache在所有這些應(yīng)用環(huán)境下都能工作得很好。最后,Apache開(kāi)發(fā)者社區(qū)決不是一個(gè)排外的黑客社區(qū)。盡管軟件開(kāi)發(fā)和維護(hù)是Apache開(kāi)發(fā)者所有活動(dòng)中最重要的,但仍然有人在沒(méi)有寫(xiě)過(guò)一行C語(yǔ)言代碼的情況下被提拔到Apache組織的高層,因?yàn)榧夹g(shù)支持、文檔編寫(xiě)和行政等工作與開(kāi)發(fā)工作一樣重要。參與Apache工作所有的社區(qū)論壇都是對(duì)公眾開(kāi)放的,這里歡迎任何一個(gè)想為Apache貢獻(xiàn)力量的人。有很多種方式可以加入Apache,而每一種工作都很有意義。動(dòng)手編碼。歡迎為Bugzilla提出的Bug提供補(bǔ)丁。開(kāi)發(fā)者可在列表上正在爭(zhēng)論的主題或者在STATUS文件中突出強(qiáng)調(diào)的主題做出貢獻(xiàn)。如果某位開(kāi)發(fā)者想加入工作,可以到位于SVN的代碼倉(cāng)庫(kù)中搜索TODO記錄和FIXME記錄。如果一個(gè)補(bǔ)丁能夠干凈地集成(通過(guò)diff-u或者svn-diff方式),并且有比較清晰的動(dòng)機(jī)和功能描述,那么這個(gè)補(bǔ)丁是受歡迎的。補(bǔ)丁便可以通過(guò)開(kāi)發(fā)者列表或Bugzilla發(fā)布。撰寫(xiě)文檔。文檔存放在SVN中。所有的原始文檔都是XML格式的,該格式是DocBook的一個(gè)子集。歡迎撰寫(xiě)新的文檔,或者對(duì)原有的文檔進(jìn)行修訂(添加補(bǔ)?。?。文檔翻譯。文檔一般都具有多個(gè)語(yǔ)言的版本。但不是文檔中每一頁(yè)都具有不同語(yǔ)言的版本,而且文檔的翻譯版本也不一定都是最新的。因此如果你具有語(yǔ)言天賦,那么就去找到缺失的或者過(guò)時(shí)的文檔并修正它們吧。測(cè)試軟件。在你的平臺(tái)上構(gòu)建并測(cè)試代碼,特別是當(dāng)你具有一個(gè)與眾不同的平臺(tái)時(shí)。使用不尋常的環(huán)境和工具構(gòu)建Apache,它能夠干凈地構(gòu)建和安裝嗎?可以使用你所有不尋常的任務(wù)對(duì)它進(jìn)行壓力測(cè)試。如果它失敗了,或者你發(fā)現(xiàn)它相對(duì)于之前的版本有一個(gè)意想不到的變化,試著去診斷究竟發(fā)生了什么。把你找到的任何Bug都通過(guò)開(kāi)發(fā)者列表和Bugzilla報(bào)告出來(lái)。努力保證你所描述的情況是清晰明了并且可重現(xiàn)的。構(gòu)建軟件。維護(hù)Apache的構(gòu)建和安裝是一個(gè)很重要的任務(wù),但是直到本書(shū)寫(xiě)作為止我們都沒(méi)有很好地處理它。即使是在UNIX/Linux家族平臺(tái)上最廣泛使用的GNU基于自動(dòng)配置的安裝,檢查一下都是有好處的。1.4Apache和知識(shí)產(chǎn)權(quán)所有的Apache項(xiàng)目的版權(quán)都?xì)wApache軟件基金會(huì)所有,并使用Apache許可證進(jìn)行許可。同時(shí),Apache軟件基金會(huì)和項(xiàng)目管理委員會(huì)采用各種方法來(lái)保證當(dāng)沒(méi)有合法綁定時(shí),Apache的代碼中不包含第三方的有知識(shí)產(chǎn)權(quán)的代碼,并且用來(lái)發(fā)布的寫(xiě)權(quán)限處于Apache許可證的保護(hù)之下。不過(guò),值得注意的是,雖然Apache掌握一個(gè)項(xiàng)目的整體版權(quán),但是項(xiàng)目中某個(gè)部分的版權(quán)可能歸個(gè)人貢獻(xiàn)者所有,并基于Apache軟件基金會(huì)的條款進(jìn)行許可。Apache許可證Apache許可證(可以在附錄A中找到)是一個(gè)自由的軟件許可證,基于傳統(tǒng)的BSD和MIT軟件許可證,增加了適合我們時(shí)代要求的一些重要條款。它滿(mǎn)足自由軟件和開(kāi)源軟件所有已經(jīng)被接受的定義。可能自由軟件的術(shù)語(yǔ)讓一些讀者感到迷惑,我們暫且對(duì)其中的某些重要部分進(jìn)行澄清。值得注意的是,這只是一些基本的背景信息,可能對(duì)任何一個(gè)特定國(guó)家的讀者來(lái)說(shuō)不是法律忠告。自由的言論,不是免費(fèi)啤酒免費(fèi)的啤酒是美妙的,但是自由的言論更加重要。當(dāng)我們談到軟件自由時(shí),一般都會(huì)有自由言論的感覺(jué)。軟件自由主要體現(xiàn)在任何人都有想做什么就做什么的自由(當(dāng)然,可以自己去做,也可以雇人去做)。源代碼開(kāi)放也是軟件自由的一個(gè)必要組成部分。價(jià)格和軟件自由不相關(guān)。Apache可以通過(guò)各種價(jià)格獲得,從免費(fèi)的下載,到捆綁在一個(gè)商業(yè)Linux版本的軟件包,甚至是由商業(yè)組織開(kāi)發(fā)的全額軟件產(chǎn)品。非公開(kāi)領(lǐng)域和其他很多自由軟件類(lèi)似,Apache不是一個(gè)公開(kāi)領(lǐng)域。Apache的版權(quán)為Apache軟件基金會(huì)所擁有,并具有許可證。和那些商業(yè)軟件的許可證相比,Apache的許可證顯得更加友好,并且沒(méi)有那么多的限制。不是共享軟件和廣告軟件共享軟件(包括Nagware、廣告軟件等)概念上和自由軟件類(lèi)似。它們通常(盡管不是全部)都被認(rèn)為是質(zhì)量較差的、比較業(yè)余的產(chǎn)品,如今通常都是受商業(yè)驅(qū)使開(kāi)發(fā),而不是受技術(shù)驅(qū)使。不是GPL由自由軟件基金會(huì)(FreeSoftwareFoundation)編寫(xiě)并擁有的GNU通用公眾許可證GPL(GeneralPublicLicense),是最老的也是最廣為人知的(同時(shí)也是最誤傳的)自由軟件許可證。GPL引入的一個(gè)概念稱(chēng)為copyleft(和copyright對(duì)應(yīng)),它的基本理念可以總結(jié)如下:“我們授予你這些自由,而你不能把這些自由從其他人手里拿走。”這個(gè)策略有時(shí)候被認(rèn)為是商業(yè)不友好的,因?yàn)閏opyleft軟件不管愿意不愿意,是不能被融入到非自由軟件中的。Apache許可證明顯是商業(yè)友好的,它不是copyleft。事實(shí)上,Apache許可證甚至和GPL是互不兼容的。這是因?yàn)槊恳粋€(gè)許可證都有一些規(guī)定,這些規(guī)定和其他的許可證是互不兼容的:GPL軟件使用Apache軟件基金會(huì)條款進(jìn)行發(fā)布,因?yàn)閏opyleft的限制導(dǎo)致和Apache軟件基金會(huì)策略不兼容。Apache軟件基金會(huì)許可的軟件也不能使用GPL條款進(jìn)行發(fā)布。關(guān)于這個(gè)問(wèn)題我們可以看看自由軟件基金會(huì)是如何說(shuō)明的:Apache許可證是一個(gè)自由軟件許可證,但是它和GPL不兼容。Apache許可證之所以和GPL不兼容是因?yàn)樗哂幸粋€(gè)特別的要求,而GPL沒(méi)有:它具有一些專(zhuān)利終止的情況,而GPL不需要。(我們不認(rèn)為具有這些專(zhuān)利終止情況就不好,但是它們和GNU的GPL不兼容。)但是這些因素對(duì)于終端用戶(hù)和第三方(如模塊開(kāi)發(fā)者或發(fā)布者)來(lái)說(shuō)并不是問(wèn)題。Linux(GPL)廠(chǎng)商例行公事地在他們的產(chǎn)品中包括了Apache,也有很多的Apache模塊是GPL許可的。Linux發(fā)布者同時(shí)遵守兩種許可,模塊開(kāi)發(fā)者為他們的工作選擇遵從某個(gè)許可,這些都沒(méi)有問(wèn)題。即使是最崇尚單一的、對(duì)法律最小心翼翼的Debian發(fā)布版本也為Apache發(fā)布了GPL的模塊。當(dāng)和GPL軟件進(jìn)行接口時(shí),許可的不兼容會(huì)導(dǎo)致一些問(wèn)題。以MySQL的實(shí)現(xiàn)為例,MySQL是一個(gè)GPL許可下的SQL數(shù)據(jù)庫(kù)軟件包,為了遵從MySQL的GPL許可要求,MySQL的Apache/APR驅(qū)動(dòng)也是GPL許可的,因此不能被ASF集成在Apache中進(jìn)行發(fā)布。作為替代選擇,它可以從其作者的網(wǎng)站上進(jìn)行單獨(dú)下載,或者從第三方作為一個(gè)單獨(dú)的軟件包獲取。這就只和自己編譯Apache的用戶(hù)相關(guān),而那些使用軟件包安裝的用戶(hù)就永遠(yuǎn)不需要關(guān)注這些細(xì)節(jié)問(wèn)題。專(zhuān)利和反強(qiáng)盜條款對(duì)于技術(shù)開(kāi)發(fā)者來(lái)說(shuō),當(dāng)今最大的危險(xiǎn)就來(lái)自于專(zhuān)利,這種情況在美國(guó)尤為突出。在美國(guó),專(zhuān)利系統(tǒng)一直被看作是維護(hù)經(jīng)濟(jì)壟斷的工具:為“我們”的公司申請(qǐng)成千上萬(wàn)的專(zhuān)利,然后通過(guò)世界貿(mào)易組織(WorldTradeOrganization,WTO)的條約將這些專(zhuān)利執(zhí)行,以期獲得全球競(jìng)爭(zhēng)優(yōu)勢(shì)。結(jié)果就是,美國(guó)的專(zhuān)利局要處理大量的專(zhuān)利事務(wù),導(dǎo)致沒(méi)有辦法對(duì)每個(gè)專(zhuān)利進(jìn)行詳細(xì)審查和質(zhì)量控制。很多這樣的專(zhuān)利就掌握在對(duì)技術(shù)沒(méi)有絲毫興趣的人手上,他們期望從合法的商業(yè)中勒索錢(qián)財(cái)。切實(shí)的感受就是:這就是當(dāng)今的強(qiáng)盜。在過(guò)去,某個(gè)國(guó)家、省或者城市的統(tǒng)治者會(huì)為“他們的”海進(jìn)行圈地聲明,向每一個(gè)經(jīng)過(guò)他們領(lǐng)地的外來(lái)船只收取一定數(shù)量的過(guò)路費(fèi),并且允許私掠船(戰(zhàn)時(shí)特準(zhǔn)攻擊敵方商船)保護(hù)他們的財(cái)產(chǎn)權(quán)利,查封任何經(jīng)過(guò)而沒(méi)交費(fèi)的船只。類(lèi)似的,如今的專(zhuān)利持有人向合法的商業(yè)索取費(fèi)用,雇傭律師來(lái)強(qiáng)化他們的財(cái)產(chǎn)。事實(shí)上,如今的這種強(qiáng)盜行徑比過(guò)去更為惡劣:如今專(zhuān)利的數(shù)量比過(guò)去海上的強(qiáng)盜數(shù)目多得多,也不再存在安全的航線(xiàn)了。Apache許可證的一個(gè)非同尋常的限制就是盡可能地處理這種情況。接受Apache的許可意味著不能有任何反對(duì)Apache軟件基金會(huì)和Apache用戶(hù)的專(zhuān)利權(quán)限。據(jù)我所知,Apache從沒(méi)有卷入到知識(shí)產(chǎn)權(quán)的法律案件中。這和在SCO案件中Linux面臨的情況形成了鮮明的對(duì)比(盡管看起來(lái)Linux很可能會(huì)辯護(hù)成功),更不用提和微軟所面臨情況的對(duì)比:微軟的用戶(hù)已經(jīng)為微軟軟件中由于違反專(zhuān)利而向第三方支付了大量的補(bǔ)償,。第三方知識(shí)產(chǎn)權(quán)Apache的知識(shí)產(chǎn)權(quán)通過(guò)版權(quán)和許可證進(jìn)行保護(hù)。當(dāng)然,Apache也不會(huì)侵犯其他人的知識(shí)產(chǎn)權(quán),這點(diǎn)也很重要。這就意味著所有對(duì)Apache的重要貢獻(xiàn)都必須使用正確的方式進(jìn)行捐贈(zèng)。在一個(gè)開(kāi)發(fā)人員成為提交者之前,他(她)必須簽署一份貢獻(xiàn)者許可協(xié)議(ContributorLicenseAgreement,CLA),使得Apache軟件基金會(huì)被授予所有必需的權(quán)利來(lái)使用這個(gè)開(kāi)發(fā)者的貢獻(xiàn),并將其通過(guò)Apache軟件基金會(huì)條款向第三方進(jìn)行許可。貢獻(xiàn)者許可協(xié)議使得開(kāi)發(fā)者在加入Apache之前,限制他們承認(rèn)所有的貢獻(xiàn)不是他們自己的原創(chuàng)工作,而是簽字移交給Apache。貢獻(xiàn)者許可協(xié)議的全文可以參考附錄B。如果一個(gè)開(kāi)發(fā)者自己不能決定(例如,一個(gè)雇員的雇主可能對(duì)他或她的工作擁有權(quán)利)時(shí),需要該開(kāi)發(fā)者的授權(quán)上級(jí)領(lǐng)導(dǎo)(例如,首席技術(shù)官或者IT主管)簽發(fā)一個(gè)企業(yè)貢獻(xiàn)者許可協(xié)議(CorporateCLA,CCLA),企業(yè)貢獻(xiàn)者許可協(xié)議的全文可以參考附錄B。在開(kāi)發(fā)者可以被授予提交訪(fǎng)問(wèn)權(quán)限之前,所有的貢獻(xiàn)者許可協(xié)議、企業(yè)貢獻(xiàn)者許可協(xié)議必須形成文檔并保留在Apache軟件基金會(huì)。這些協(xié)議被用來(lái)保證提交者和他們的雇主不能阻止Apache軟件基金會(huì)或Apache的用戶(hù)使用他們的貢獻(xiàn)。職責(zé)首先,每一個(gè)提交者都必須保證他(她)的貢獻(xiàn)沒(méi)有侵犯第三方的知識(shí)產(chǎn)權(quán),這是他們的職責(zé)。全面的職責(zé)是屬于項(xiàng)目管理委員會(huì)的,它將質(zhì)疑任何出現(xiàn)可疑情況的貢獻(xiàn),特別是主要的新貢獻(xiàn)。審計(jì)盡管所有都考慮到了,仍然可能出現(xiàn)第三方知識(shí)產(chǎn)權(quán)的問(wèn)題。Apache有一條完整的審計(jì)鏈,由Subversion管理。因此,即使在最壞的情況下,任何有問(wèn)題的代碼都可以被查出來(lái)并刪除。交互式在線(xiàn)論壇公共郵件列表Apache模塊開(kāi)發(fā)者列表modules-dev@httpd.apache.or是一個(gè)討論任何和模塊開(kāi)發(fā)相關(guān)問(wèn)題的好地方。這個(gè)列表在2006年9月移到apache-modules@covalent.ne,t因此可以查看這兩個(gè)列表上的資料。ApacheWeb服務(wù)器的官方開(kāi)發(fā)者列表是dev@歡迎大家參與,不過(guò)請(qǐng)不要離題。Apache可移植運(yùn)行時(shí)庫(kù)(ApachePortableRuntime,APR)的官方開(kāi)發(fā)者列表是dev@歡迎大家參與,不過(guò)請(qǐng)不要離題。Apache的用戶(hù)列表是users@httpd.apache.or,g是一個(gè)討論各種問(wèn)題和進(jìn)行用戶(hù)支持的論壇。用戶(hù)組systems.www.servers[unix|windows|mac|mis]新聞組是一個(gè)對(duì)不同平臺(tái)上Apache的各種問(wèn)題進(jìn)行討論的好地方。在線(xiàn)交談在irc://irc.freenode.ne上有幾個(gè)頻道和Apache相關(guān)。#apache:通用支持/非官方的幫助臺(tái)頻道。可以問(wèn)一些有意義的問(wèn)題并等待答案。但是首先你必須做功課,特別是要看錯(cuò)誤日志。注意fajita,它是#apache的機(jī)器人程序,它將做很多的常規(guī)工作如回答你的問(wèn)題,或者貼出一些相關(guān)的文檔頁(yè)面地址。#apache-modules針對(duì)模塊開(kāi)發(fā)的頻道。這個(gè)頻道非常適合本書(shū)的讀者。#apr:APR半官方的頻道,包括自動(dòng)的、對(duì)APR代碼倉(cāng)庫(kù)變動(dòng)的實(shí)時(shí)通告。#httpd-dev:Web服務(wù)器開(kāi)發(fā)的半官方頻道,包括自動(dòng)的、對(duì)代碼倉(cāng)庫(kù)變動(dòng)的實(shí)時(shí)通告,以及文檔和網(wǎng)站。#asfinfra:Apache的架構(gòu)頻道。會(huì)議Apache軟件基金會(huì)為專(zhuān)注于Apache軟件基金會(huì)項(xiàng)目的開(kāi)發(fā)者組織了ApacheCon會(huì)議。這些會(huì)議將很多的開(kāi)發(fā)人員聚集到一起(這些開(kāi)發(fā)人員在網(wǎng)上論壇中互相都比較熟悉,但是他們中間很多人都不曾面對(duì)面相聚過(guò))。用戶(hù)也許只是過(guò)來(lái)學(xué)習(xí)的,但是他們有時(shí)也會(huì)給開(kāi)發(fā)者帶來(lái)一些新的見(jiàn)解。會(huì)上有開(kāi)發(fā)者和用戶(hù)共同參與的教程和報(bào)告,可能是官方組織的,也可能是非正式的社會(huì)事務(wù),安排得非常緊湊。網(wǎng)站官方和半官方的Apache網(wǎng)站/Apache軟件基金會(huì)/ApacheWeb月服務(wù)器http://apr.apa,/APR主站/Apache代碼倉(cāng)庫(kù)/Bug數(shù)據(jù)庫(kù)/Apache模塊注冊(cè)/modules/更新的模塊注冊(cè)(正在建設(shè)中)http://mail—/由E件歹U表文檔/Apache提交者的個(gè)人主頁(yè)/ApacheCon會(huì)議/mod_perl/(Apache的PerlAPI)/mod_python(Apache的PythonAPI)/Apache中的TCL語(yǔ)言/cli/mod_aspdotnet(微軟的ASP.Net)第三方擴(kuò)展/筆者所編寫(xiě)的20多個(gè)模塊http://www.outoforder.cc/其他工作的12個(gè)有特色的模塊/PHP語(yǔ)言/RubyonRails開(kāi)發(fā)者文檔/API參考http://www.apachetutor,org/dev/筆者創(chuàng)建和維護(hù)的開(kāi)發(fā)者教程http://dev.ariel—/apr/aptutorial/html/aptutorial.ht針對(duì)APR的有用教程,將它的角色從Web服務(wù)器中剝離出來(lái)http://www.apache—modules.qm/本書(shū)的官方網(wǎng)站,還沒(méi)有完成其他的教程、新聞和文章/pub/q/all_apache_article丈量的文章http:///新聞網(wǎng)站,也是Windows二進(jìn)制程序的下載站點(diǎn)(通常比“官方”要早一些發(fā)布)http://marc.theaimsgroup.郵件列表文檔1.6小結(jié)本章介紹了Apache的社會(huì)背景、歷史背景和法律背景,以及Apache的文化。第1章特別介紹了以下幾個(gè)方面:Apachehttpd的發(fā)展歷史Apache軟件基金會(huì)和它的文化Apache的開(kāi)發(fā)者、流程、開(kāi)發(fā)和技術(shù)支持的資源,包括如何參與ApacheApache對(duì)待知識(shí)產(chǎn)權(quán)的方法,包括Apache許可證和避免誤用第三方知識(shí)產(chǎn)權(quán)的安全機(jī)制第1章是與技術(shù)無(wú)關(guān)的,而本書(shū)后續(xù)部分將全部是關(guān)于Apache開(kāi)發(fā)的。本書(shū)以容易理解的概述開(kāi)始,然后將轉(zhuǎn)向?qū)δK和應(yīng)用程序開(kāi)發(fā)進(jìn)行實(shí)際操作訓(xùn)練。Apache作為常駐的后臺(tái)任務(wù)運(yùn)行:在UNIX系統(tǒng)中為守候進(jìn)程(Daemon),在Windows系統(tǒng)中為服務(wù)(Service)。由于Apache服務(wù)器的啟動(dòng)階段比較耗費(fèi)時(shí)間和資源,因此它一般在操作系統(tǒng)啟動(dòng)時(shí)被啟動(dòng)并一直運(yùn)行。Apache的早期版本曾支持inetd模式,但是該模式已經(jīng)不再適合實(shí)際的應(yīng)用??v覽Apache的HTTP服務(wù)器由一個(gè)相對(duì)較小的內(nèi)核及一些模塊組成,如圖2.1所示。模塊可以靜態(tài)的編譯到服務(wù)器中,但是通常都把模塊放在/Modules/目錄或者/libexec/目錄下面,服務(wù)器運(yùn)行時(shí)這些模塊被動(dòng)態(tài)加載。另外,Apache服務(wù)器依賴(lài)底層的可移植運(yùn)行時(shí)庫(kù)(ApachePortableRuntime,APR)。可移植運(yùn)行時(shí)庫(kù)提供跨平臺(tái)的操作系統(tǒng)抽象層和功能函數(shù),為上層模塊提供統(tǒng)一的接口,這樣模塊可以避免受到不可移植的操作系統(tǒng)調(diào)用的影響。多處理模塊(Multi-ProcessingModule,MPM)是一個(gè)特殊的功能模塊,用來(lái)根據(jù)底層的操作系統(tǒng)來(lái)優(yōu)化Apache。多處理模塊通常是唯一直接訪(fǎng)問(wèn)操作系統(tǒng)的模塊,其他模塊可以通過(guò)可移植運(yùn)行時(shí)庫(kù)來(lái)訪(fǎng)問(wèn)操作系統(tǒng)。圖2.1Apache架構(gòu)Apache運(yùn)行的兩個(gè)階段Apache的運(yùn)行分為啟動(dòng)階段和運(yùn)行階段。啟動(dòng)階段時(shí),Apache以特權(quán)用戶(hù)root啟動(dòng),進(jìn)行解析配置文件、加載模塊和初始化一些系統(tǒng)資源(例如日志文件、共享內(nèi)存段、數(shù)據(jù)庫(kù)連接)等操作。處于運(yùn)行階段時(shí),Apache放棄特權(quán)用戶(hù)級(jí)別,使用非特權(quán)用戶(hù)來(lái)接收和處理網(wǎng)絡(luò)中用戶(hù)的服務(wù)請(qǐng)求。這種基本安全機(jī)制可以阻止Apache中由于一個(gè)簡(jiǎn)單軟件錯(cuò)誤(也可能是模塊或腳本)而導(dǎo)致的嚴(yán)重系統(tǒng)安全漏洞,例如微軟的IIS就曾遭受“紅色代碼(CodeRed)”和“尼姆達(dá)(Nimda)”等惡意代碼的溢出攻擊。Apache的這種兩個(gè)階段的運(yùn)行方式對(duì)應(yīng)用程序的架構(gòu)具有一定影響。首先,任何需要系統(tǒng)級(jí)權(quán)限的操作都必須在系統(tǒng)啟動(dòng)時(shí)運(yùn)行。其次,最好在啟動(dòng)階段進(jìn)行盡可能多的初始化工作來(lái)簡(jiǎn)化處理每個(gè)請(qǐng)求時(shí)的工作量。這樣做帶來(lái)的影響就是:由于耗費(fèi)很多時(shí)間和資源的操作都集中在啟動(dòng)階段完成,因此Apache以inetd或tcpserver模式運(yùn)行時(shí)效率就會(huì)非常低。Apache的架構(gòu)有一個(gè)不符合常規(guī)的古怪之處:配置代碼實(shí)際上在啟動(dòng)階段執(zhí)行了兩次(盡管不是重新啟動(dòng))。第一次,檢查服務(wù)器配置是否正確(至少,Apache能夠成功啟動(dòng));第二次是真正的系統(tǒng)啟動(dòng),然后引導(dǎo)至運(yùn)行階段。這種啟動(dòng)執(zhí)行兩次的行為大多數(shù)模塊都能忽略(如APR池能夠保證不會(huì)引起資源的泄漏),但是,對(duì)某些模塊還是有影響的。例如,某些模塊在系統(tǒng)啟動(dòng)階段動(dòng)態(tài)加載新的代碼,如果想要這些代碼只加載一次,那么就需要采用某些技巧(例如采用檢查全局標(biāo)志位的方法)來(lái)保證加載操作只做了一次。啟動(dòng)階段Apache在啟動(dòng)階段讀取配置文件、加載模塊和函數(shù)庫(kù),以及分配資源。每個(gè)模塊可能都需要資源,并在啟動(dòng)階段對(duì)這些資源進(jìn)行初始化。Apache在啟動(dòng)階段擁有系統(tǒng)最高權(quán)限,以單進(jìn)程、單線(xiàn)程方式運(yùn)行。配置Apache的主配置文件通常為httpd.conf。但是由于這種命名方式為一般慣例,并非強(qiáng)制要求,因此提供.rpm或者.deb包的第三方,Apache發(fā)行版本可能使用不同的命名機(jī)制。另外,httpd.conf文件可能是單一文件,也可能是通過(guò)使用Include指令包含不同配置文件的多個(gè)文件集合。有些發(fā)行版本的配置非常復(fù)雜。例如DebianGNU/Linux的Apache配置需要對(duì)Debian非常熟悉而不是Apache。本書(shū)并不探討不同配置設(shè)計(jì)的優(yōu)缺點(diǎn),因此,為了簡(jiǎn)化,我們認(rèn)為配置文件為httpd.conf。httpd.conf文件是一個(gè)文本文件,在系統(tǒng)啟動(dòng)時(shí)被逐行解析。該文件由指令、容器和注釋組成。配置文件內(nèi)允許有空行和空格,它們?cè)诮馕鰰r(shí)被忽略不計(jì)。指令(Directives)httpd.conf文件中大多數(shù)內(nèi)容是指令。指令可以沒(méi)有參數(shù),也可以有多個(gè)參數(shù),參數(shù)之間用空格隔開(kāi)。每一個(gè)指令有自己的語(yǔ)法格式,不同的指令允許不同的參數(shù)個(gè)數(shù)和參數(shù)類(lèi)型(有字符串、數(shù)字、枚舉、布爾或文件名等)。指令是在內(nèi)核或者一些模塊中實(shí)現(xiàn)的,我們將在第9章中介紹。以下是幾個(gè)指令的實(shí)例。LoadModulefoo_modulemodules/mod_foo.so這個(gè)指令由mod_so模塊實(shí)現(xiàn),用來(lái)加載一個(gè)模塊。第一個(gè)參數(shù)是模塊名(字符與數(shù)字組成的字符串),第二個(gè)參數(shù)是文件名,可以是服務(wù)器根目錄的絕對(duì)路徑或者相對(duì)路徑。DocumentRoot/usr/local/Apache/htdocs這個(gè)指令由內(nèi)核實(shí)現(xiàn)的,用來(lái)設(shè)置網(wǎng)頁(yè)所在主文檔樹(shù)的根目錄。SetEnvhello“Hello,World!這個(gè)指令由mod_env模塊實(shí)現(xiàn),用設(shè)置環(huán)境變量。注意,由于第二個(gè)參數(shù)包含空格,我們必須用雙引號(hào)把它包含起來(lái)。ChoicesOn這個(gè)指令由mod_choices(將在第6章介紹)實(shí)現(xiàn),用來(lái)激活模塊的選項(xiàng)。容器(Containers)容器是一系列指令的集合,語(yǔ)法和標(biāo)記語(yǔ)言很相像,使用尖括號(hào)進(jìn)行歸類(lèi)。容器在語(yǔ)義上和其他指令不同,具有一個(gè)開(kāi)始和結(jié)束的分隔行,在分隔行之間的指令為容器內(nèi)部的指令。例如由內(nèi)核模塊中的〈VirtualHost〉容器如下所示,該容器定義了一個(gè)虛擬主機(jī)。<VirtualHost39>ServerNameDocumentRoot/usr/www/exampleServerAdminWebma.ster@CustomLog/var/log/www/example.log〈/VirtualHost〉容器為里面的指令提供了上下文。在上面這個(gè)例子中,指令只對(duì)訪(fǎng)問(wèn)www.example.co的請(qǐng)求進(jìn)行響應(yīng)。容器可以被嵌套使用,除非某個(gè)模塊顯式地聲明容器不能嵌套。所有用到的指令,包括容器,都可能是上下文相關(guān)的,因此它們?cè)谀承┚唧w的上下文中才有效。注釋?zhuān)–omments)如果一行語(yǔ)句以#號(hào)開(kāi)頭,那么該行被認(rèn)為是注釋語(yǔ)句。例如下面的語(yǔ)句為注釋。#thislineisacomment行中的#一般不會(huì)被認(rèn)為是注釋?zhuān)悄K明確地在實(shí)現(xiàn)該指令時(shí)支持行中注釋。如果模塊沒(méi)有被加載,那么該模塊所實(shí)現(xiàn)的指令就不能被識(shí)別。遇到這種情況時(shí),Apache執(zhí)行停止并返回一個(gè)語(yǔ)法錯(cuò)誤。因此mod_so模塊必須用靜態(tài)的方式進(jìn)行鏈接來(lái)加載其他模塊。這一點(diǎn)非常重要!當(dāng)你開(kāi)發(fā)新的模塊時(shí)沒(méi)有靜態(tài)地鏈接mod.so,那么每次在修正該模塊時(shí)必須重新編譯整個(gè)服務(wù)器程序。運(yùn)行階段在啟動(dòng)階段末期,程序的控制轉(zhuǎn)向多處理模塊MPM(見(jiàn)2.3節(jié))。MPM模塊在系統(tǒng)級(jí)管理Apache的運(yùn)行。它根據(jù)操作系統(tǒng)和應(yīng)用的約束(如一些特殊場(chǎng)景的應(yīng)用)維護(hù)進(jìn)程池和/或線(xiàn)程池。MPM的進(jìn)程作為控制者,管理一系列子工作進(jìn)程。子工作進(jìn)程用來(lái)處理接入請(qǐng)求,而控制者進(jìn)程負(fù)責(zé)創(chuàng)建和刪除子工作進(jìn)程以及處理信號(hào)量(如停止或者重啟)。MPM的架構(gòu)導(dǎo)致不可能在有限的的范圍內(nèi)描述運(yùn)行階段。盡管標(biāo)準(zhǔn)的MPM采用工作子進(jìn)程的方式,但是MPM并沒(méi)有被限制只能使用這一種方式。理論上MPM可以在系統(tǒng)層上實(shí)現(xiàn)其他完全不同的服務(wù)器架構(gòu)。停止階段雖然沒(méi)有明確的停止階段,但是需要在服務(wù)停止的時(shí)候完成的工作應(yīng)被注冊(cè)為清除操作(在第3章中介紹)。當(dāng)Apache停止的時(shí)候,所有注冊(cè)的清除操作都將運(yùn)行。多處理模塊MPM在啟動(dòng)階段的末期,當(dāng)所有的配置信息被讀取之后,Apache的控制轉(zhuǎn)到多處理模塊MPM°MPM提供Apache服務(wù)程序和其所在的操作系統(tǒng)之間的接口。該模塊的主要職責(zé)是根據(jù)所在的操作系統(tǒng)平臺(tái)來(lái)優(yōu)化Apache,提高Apache的效率,保證Apache的安全。MPM自身也是一個(gè)模塊,這點(diǎn)我們能夠從它的命名看出。值得注意的是,MPM是Apache中唯一的一個(gè)系統(tǒng)層模塊(因此開(kāi)發(fā)MPM已經(jīng)超出本書(shū)關(guān)于應(yīng)用程序開(kāi)發(fā)的范圍)。同樣一個(gè)Apache實(shí)例只能有一個(gè)在編譯時(shí)所選擇的MPM。為什么需要MPM老版本的NCSAserver和Apache1是在UNIX系統(tǒng)中成長(zhǎng)起來(lái)的。當(dāng)時(shí)Apache是一個(gè)多進(jìn)程服務(wù)器,一個(gè)服務(wù)進(jìn)程處理一個(gè)用戶(hù)請(qǐng)求,如果當(dāng)前并發(fā)客戶(hù)訪(fǎng)問(wèn)數(shù)量大于服務(wù)進(jìn)程數(shù),Apache便會(huì)增加新的服務(wù)進(jìn)程來(lái)處理當(dāng)前請(qǐng)求。在正常情況下,Apache會(huì)維護(hù)一定數(shù)量的服務(wù)進(jìn)程來(lái)處理用戶(hù)的請(qǐng)求。盡管這種多進(jìn)程服務(wù)機(jī)制在Unix類(lèi)系統(tǒng)中能夠很好地工作,但是在其他的平臺(tái)上效率卻很低,如在Windows中產(chǎn)生一個(gè)進(jìn)程是非常費(fèi)時(shí)的。因此,讓Apache真正實(shí)現(xiàn)跨平臺(tái)還需要其他的方法。Apache2采用的方法是把核心任務(wù)處理作為一個(gè)可插拔的模塊,即MPM,使其能針對(duì)不同的環(huán)境進(jìn)行優(yōu)化。MPM架構(gòu)允許不同的Apache模塊在一個(gè)操作系統(tǒng)平臺(tái)下共存,能夠?yàn)橛脩?hù)根據(jù)不同應(yīng)用做出選擇。在實(shí)際應(yīng)用中,只有UNIX類(lèi)操作系統(tǒng)有其他的選擇,而其他系統(tǒng)平臺(tái)(Windows、Netware、OS/2、BeOS)則只有唯一的根據(jù)操作系統(tǒng)優(yōu)化的MPM。在UNIX平臺(tái)上,Apache2.2目前已經(jīng)有兩種高質(zhì)量的、作為標(biāo)準(zhǔn)的MPM(Prefork和Worker),第三種(Eevent方式)在不使用SSL的情況下也是穩(wěn)定可靠的。另外還有一些MPM可以實(shí)驗(yàn)應(yīng)用,暫時(shí)不適合產(chǎn)品應(yīng)用。其他第三方的MPM模塊也是可用的。UNIX類(lèi)的MPM模塊PreforkMPM基于非線(xiàn)程模型,和Apache1.x版本中的MPM很相似。PreforkMPM在所有情況下都很安全,對(duì)運(yùn)行非線(xiàn)程安全(non-thread-safe)模式的軟件如PHP,它是唯一的安全選擇。對(duì)于某些應(yīng)用程序,包括在Apache1.3上非常流行的程序(如簡(jiǎn)單靜態(tài)頁(yè)面、CGI腳本等),PreforkMPM是最好的選擇。WorkerMPM基于線(xiàn)程模式,具有內(nèi)存消耗低(對(duì)繁忙的服務(wù)很重要)、擴(kuò)展性在某些特定應(yīng)用情況下比Prefork更好等優(yōu)點(diǎn)。在稍后介紹SQL數(shù)據(jù)庫(kù)支持和mod_dbd模塊時(shí)我們會(huì)討論其中一些內(nèi)容。以上兩種穩(wěn)定的MPM方式在非常繁忙的服務(wù)器應(yīng)用下都有些不足。盡管HTTP的Keepalive方式能減少TCP連接數(shù)量和網(wǎng)絡(luò)負(fù)載,但是Keepalive需要和服務(wù)進(jìn)程或者線(xiàn)程綁定,這就導(dǎo)致一個(gè)繁忙的服務(wù)器會(huì)耗光所有的線(xiàn)程。EventMPM是解決這個(gè)問(wèn)題的一種新模型,它把服務(wù)進(jìn)程從連接中分離出來(lái)。在服務(wù)器處理速度很快,同時(shí)具有非常高的點(diǎn)擊率時(shí),可用的線(xiàn)程數(shù)量就是關(guān)鍵的資源限制,此時(shí)EventMPM方式是最有效的。一個(gè)以WorkerMPM方式工作的繁忙服務(wù)器能夠承受每秒好幾萬(wàn)次的訪(fǎng)問(wèn)量(例如在大型新聞服務(wù)站點(diǎn)的高峰時(shí)),而EventMPM可以用來(lái)處理更高負(fù)載。值得注意的是,EventMPM不能在安全HTTP(HTTPS)訪(fǎng)問(wèn)下工作。還有一些針對(duì)UNIX系統(tǒng)的、處于實(shí)驗(yàn)中的MPM,在本書(shū)編寫(xiě)過(guò)程中,它們?cè)诶^續(xù)開(kāi)發(fā),有的可能已經(jīng)實(shí)現(xiàn)了。PerchildMPM具有一個(gè)非常好的特性:以不用的用戶(hù)ID為不同的虛擬主機(jī)運(yùn)行Apache服務(wù)器。其他的一些MPM也提供類(lèi)似的功能,包括第三方的Metux和Peruser,以及mod_ruid(只支持Linux)。為了運(yùn)行外部程序,還可選擇fastcgi/mod_fcgid和suexec(CGI)。作者對(duì)第三方的解決方案沒(méi)有相應(yīng)的了解,因此不能作出相應(yīng)的評(píng)價(jià)。MPM模塊和操作系統(tǒng)一言以蔽之:對(duì)應(yīng)用程序來(lái)說(shuō),MPM方式很少見(jiàn),應(yīng)該忽略!既然MPM內(nèi)部機(jī)制不是應(yīng)用程序接口的一部分,Apache的應(yīng)用開(kāi)發(fā)者不需要知道MPM的細(xì)節(jié)。這里就簡(jiǎn)單帶過(guò)。一些為應(yīng)用開(kāi)發(fā)者提供的最佳實(shí)踐的基本規(guī)則(命名機(jī)制、編寫(xiě)安全線(xiàn)程、交叉進(jìn)程安全、代碼重入)將會(huì)在第4章中簡(jiǎn)單介紹。這里主要介紹開(kāi)發(fā)平臺(tái)無(wú)關(guān)代碼。事實(shí)上,有時(shí)應(yīng)用程序的開(kāi)發(fā)平臺(tái)更要考慮MPM而不是操作系統(tǒng)。有時(shí)一個(gè)應(yīng)用程序更加適應(yīng)于某個(gè)MPM。例如,數(shù)據(jù)庫(kù)驅(qū)動(dòng)或者負(fù)載均衡應(yīng)用程序得益于threadMPM方式的連接池(在本書(shū)稍后討論)。反之,產(chǎn)生子進(jìn)程(原始的CGI實(shí)現(xiàn)或者mod_ext_filter)在一個(gè)基于線(xiàn)程的程序中會(huì)產(chǎn)生巨大開(kāi)銷(xiāo),因此在PreforkMPM方式下工作得更好。然而,除非某些特殊限制,應(yīng)用程序應(yīng)該考慮如何適應(yīng)在非首選的MPM下工作。如果你想讓Apache運(yùn)行在現(xiàn)在還不支持Apache的操作系統(tǒng)上,那么首要的任務(wù)是在APR庫(kù)中增加對(duì)目標(biāo)平臺(tái)的支持。APR庫(kù)用來(lái)提供操作系統(tǒng)層的支持。一個(gè)定制的MPM不是必需的,但是它很可能比已有的MPM提供更好的性能。從Apache的角度出發(fā),這是一個(gè)系統(tǒng)編程的任務(wù),因此它已經(jīng)超出一本應(yīng)用程序開(kāi)發(fā)書(shū)籍的介紹范圍。基本概念和數(shù)據(jù)結(jié)構(gòu)要想在Apache平臺(tái)上做開(kāi)發(fā),我們需要對(duì)Web服務(wù)器運(yùn)行的基本單元和Apache的內(nèi)核結(jié)構(gòu)有大致的了解。其中最重要的概念是服務(wù)器、TCP連接和HTTP請(qǐng)求。進(jìn)程作為Apache中第4個(gè)基本對(duì)象,是操作系統(tǒng)的一個(gè)執(zhí)行單元,而不屬于應(yīng)用程序架構(gòu)。每一個(gè)基本單元由一個(gè)在httpd.h頭文件中定義的內(nèi)核數(shù)據(jù)結(jié)構(gòu)表示。與在應(yīng)用程序開(kāi)發(fā)中我們遇到的其他內(nèi)核對(duì)象一樣,這些基本單元在應(yīng)用時(shí)和MPM無(wú)關(guān)。在描述這些內(nèi)核數(shù)據(jù)結(jié)構(gòu)之前,我們需要介紹貫穿在整個(gè)Apache當(dāng)中并且和體系結(jié)構(gòu)緊密關(guān)聯(lián)的概念。APR池(apr_pool_t)是Apache中資源管理的核心。當(dāng)一個(gè)資源被動(dòng)態(tài)分配時(shí),在APR池中注冊(cè)一個(gè)清理操作,保證資源在不再需要的時(shí)候能夠被釋放掉。APR池將資源綁定到一個(gè)內(nèi)核對(duì)象的生命周期當(dāng)中。我們將在第3章中深入討論APR池。配置記錄被每一個(gè)模塊用來(lái)將自己的數(shù)據(jù)綁定到一個(gè)內(nèi)核對(duì)象中。內(nèi)核數(shù)據(jù)結(jié)構(gòu)包含配置向量(ap_conf_vector_t)。每一個(gè)模塊在配置向量中有自己的入口。配置向量有兩種用途:一是設(shè)置和獲取全局的配置數(shù)據(jù);二是將臨時(shí)數(shù)據(jù)保存到臨時(shí)的對(duì)象中。在一個(gè)模塊中應(yīng)該盡量避免使用不安全的靜態(tài)變量和全局變量,這點(diǎn)將在第4章和第9章中討論。在介紹完APR池和配置數(shù)據(jù)之后,我們接下來(lái)看Apache的內(nèi)核對(duì)象。按照對(duì)模塊的重要性排列,它們是:request_recserver_recconn_recprocess_rec在應(yīng)用程序開(kāi)發(fā)中,前兩種對(duì)象是經(jīng)常遇到的。request_recrequest_rec對(duì)象在Apache接受連接請(qǐng)求的時(shí)候創(chuàng)建,并在處理完請(qǐng)求之后馬上銷(xiāo)毀。為了處理連接請(qǐng)求(在第5章和第6章中討論),request_rec對(duì)象被傳遞給所有模塊的處理例程句柄。request_rec對(duì)象擁有所有涉及處理該HTTP請(qǐng)求的內(nèi)部數(shù)據(jù),也包括Apache用來(lái)維護(hù)中間狀態(tài)和客戶(hù)端信息的一系列字段。管理在處理請(qǐng)求周期中的對(duì)象的請(qǐng)求池。用來(lái)管理在處理請(qǐng)求期間的資源分配。靜態(tài)請(qǐng)求配置(在httpd.conf或者.htaccess中指定的目錄訪(fǎng)問(wèn)權(quán)限)的配置記錄向量。處理請(qǐng)求過(guò)程中用來(lái)管理臨時(shí)數(shù)據(jù)的配置記錄向量。HTTP輸入報(bào)頭表,輸出報(bào)頭表和錯(cuò)誤信息報(bào)頭表。以及一個(gè)類(lèi)似的記Apache環(huán)境變量表(SSI、CGI、mod_rewrite、PHP腳本處理擴(kuò)展中用到的環(huán)境變量),以及一個(gè)類(lèi)似的記錄請(qǐng)求數(shù)據(jù)的表,該表對(duì)腳本不可見(jiàn)。指向其他相關(guān)對(duì)象的指針。包括connection、server和任何一個(gè)相關(guān)的請(qǐng)求對(duì)象。指向輸入輸出過(guò)濾鏈(在第8章中討論)。URI請(qǐng)求及其中間解析形式,包括處理例程(見(jiàn)第5章)和文件系統(tǒng)映射(見(jiàn)第6章)這是摘自于httpd.h文件中對(duì)request_rec對(duì)象的完整定義:/**表示當(dāng)前請(qǐng)求的結(jié)構(gòu)*/structrequest_rec{/**和該請(qǐng)求相關(guān)聯(lián)的池*/apr_pool_t*pool;/**到客戶(hù)端的連接*/conn_rec*connection;/**處理本連接的虛擬主機(jī)*/server_rec*server;/**如果有外部重定向,指向請(qǐng)求重定向的指針*/request_rec*next;/**如果是內(nèi)部重定向,指向前一個(gè)請(qǐng)求的指針*/request_rec*prev;/**如果是一個(gè)子請(qǐng)求,指向主請(qǐng)求的指針*(參見(jiàn)http_request.h)*/request_rec*main;/*請(qǐng)求自身的信息...我們從protocol.c能夠涉及的項(xiàng)開(kāi)始*//**請(qǐng)求的第一行*/char*the_request;/**HTTP/0.9,簡(jiǎn)單的請(qǐng)求(例如,GET/foo\nw/noheaders)*/intassbackwards;/**一個(gè)代理請(qǐng)求(在post_read_request/translate_name過(guò)程中計(jì)算)可能的值有:PROXYREQ_NONE、PROXYREQ_PROXY、PROXYREQ_REVERSE、PROXYREQ_RESPONSE*/intproxyreq;/**HEAD請(qǐng)求,和GET相反*/intheader_only;/**協(xié)議字符串,我們可以指定,或者為HTTP/0.9*/char*protocol;/**協(xié)議的版本號(hào);1.1=1001*/intproto_num;/**主機(jī),使用URI或者Host設(shè)定*/constchar*hostname;/**請(qǐng)求開(kāi)始的時(shí)間*/apr_time_trequest_time;/**狀態(tài)行,如果被腳本設(shè)定*/constchar*status_line;/**狀態(tài)行*/intstatus;/*請(qǐng)求的方法,雙向的;在protocol.c的外面,*只參考,不要修改。*//**請(qǐng)求的方法(例如GET、HEAD、POST等)*/constchar*method;/**M_GET、M_POST等*/intmethod_number;/**“allowed”是一個(gè)允許方法的位向量。*處理函數(shù)必須保證請(qǐng)求方法是可以被處理的。任何模塊應(yīng)當(dāng)拒絕它們不能處理的任何請(qǐng)求方法。*在終止處理函數(shù)之前,處理函數(shù)應(yīng)當(dāng)為每一個(gè)它愿意處理的請(qǐng)求方法設(shè)置r-〉allowed。這個(gè)位向量用來(lái)確認(rèn)"Allow"OPTIONS請(qǐng)求、HTTP_METHOD_NOT_ALLOWED、HTTP_NOT_IMPLEMENTED狀態(tài)碼。**既然默認(rèn)的處理函數(shù)處理OPTIONS,那么其他的模塊一般拒絕處理OPTIONSo*TRACE總是“Allowed”。模塊不需要顯式地設(shè)置它。**既然默認(rèn)的處理函數(shù)總是處理GET,那么*一個(gè)沒(méi)有實(shí)現(xiàn)GET的模塊可以返回HTTP_METHOD_NOT_ALLOWED,*不過(guò)這也意味著一個(gè)腳本GET處理函數(shù)不能被mod_actions安裝。*/apr_int64_tallowed;/**擴(kuò)展方法的數(shù)組*/apr_array_header_t*allowed_xmethods;/**允許方法的鏈表*/ap_method_list_t*allowed_methods;/**body數(shù)據(jù)流的字節(jié)數(shù)*/apr_off_tsent_bodyct;/**body的字節(jié)數(shù)*/apr_off_tbytes_sent;/**請(qǐng)求資源的最后修改時(shí)間*/apr_time_tmtime;/*HTTP/1.1連接層的性質(zhì)*//**發(fā)送塊的傳送代碼*/intchunked;/**Range:header*/constchar*range;/**“真正”的內(nèi)容長(zhǎng)度*/apr_off_tclength;/**從請(qǐng)求主體中讀取剩余的字節(jié)數(shù)*/apr_off_tremaining;/**從請(qǐng)求主體中已經(jīng)讀取的字節(jié)數(shù)*/apr_off_tread_length;/**讀取請(qǐng)求主體的方法。(例如REQUEST_CHUNKED_ERROR、REQUEST_NO_BODY、REQUEST_CHUNKED_DECHUNK等)*/intread_body;/**讀取塊的傳送代碼*/intread_chunked;/**客戶(hù)端等待100個(gè)回復(fù)?*/unsignedexpecting_100;/*輸入和輸出的MIME報(bào)頭環(huán)境,以及一個(gè)發(fā)送給子過(guò)程的、包含環(huán)境變量的數(shù)組。*所以人們可以編寫(xiě)模塊增加到這個(gè)環(huán)境中。**headers_out和err_headers_out的區(qū)別在于err_headers_out在發(fā)生錯(cuò)誤時(shí)也被*顯示。*并且在內(nèi)部重定向時(shí)被保留*(因此為ErrorDocument處理函數(shù)所顯示的header會(huì)有這些內(nèi)容)。constchar*handler;constchar*handler;/*我們真正用來(lái)處理命令的函數(shù)*/constchar*handler;constchar*handler;/*我們真正用來(lái)處理命令的函數(shù)*/*'notes'apr_table_t被用來(lái)從一個(gè)模塊向另一個(gè)模塊記錄,沒(méi)有其他的意圖。*//**請(qǐng)求的MIME報(bào)頭環(huán)境*/apr_table_t*headers_in;/**應(yīng)答的MIME報(bào)頭環(huán)境*/apr_table_t*headers_out;/**應(yīng)答的MIME報(bào)頭環(huán)境,在出現(xiàn)錯(cuò)誤時(shí)被顯示,并且在內(nèi)部重定向中被保留*/apr_table_t*err_headers_out;/**為子過(guò)程所使用的環(huán)境變量數(shù)組*/apr_table_t*subprocess_env;/**一個(gè)模塊到另一個(gè)模塊的記錄*/apr_table_t*notes;/*content_type、handler、content_encoding和所有的content_languages*必須是小寫(xiě)字母的字符串。它們可以是指向靜態(tài)字符串的指針,*不能被修改。*//**當(dāng)前請(qǐng)求的content-type*/constchar*content_type;/**用來(lái)調(diào)用一個(gè)處理函數(shù)的函數(shù)名稱(chēng)*//**如何編碼數(shù)據(jù)*/constchar*content_encoding;/**表示內(nèi)容語(yǔ)言的字符串?dāng)?shù)組*/apr_array_header_t*content_languages;/**變長(zhǎng)列表驗(yàn)證器(如果協(xié)商)*/char*vlist_validator;/**如果通過(guò)認(rèn)證檢查,用來(lái)設(shè)定用戶(hù)名*/char*user;/**如果通過(guò)認(rèn)證檢查,用來(lái)設(shè)定認(rèn)證類(lèi)別*/char*ap_auth_type;/**表示不能被緩存*/intno_cache;/**沒(méi)有此應(yīng)答的本地拷貝*/intno_local_copy;/*需要什么樣的對(duì)象(可以是直接的,也可是內(nèi)容協(xié)商映射的)*//**沒(méi)有經(jīng)過(guò)分解的URI*/char*unparsed_uri;/**URI的路徑部分*/char*uri;/**和此應(yīng)答對(duì)應(yīng)的磁盤(pán)文件名*/char*filename;/**真正的文件名,如果不匹配我們填入r->filename*/char*canonical_filename;/**此請(qǐng)求中抽取的PATH_INFO*/char*path_info;/**此請(qǐng)求中抽取的QUERY_ARGS*/char*args;/**st_mode,如果沒(méi)有此文件,該值設(shè)為0*/apr_finfo_tfinfo;/**包含URI組件的結(jié)構(gòu)體*/apr_uri_tparsed_uri;/***處理函數(shù)接收或者拒絕當(dāng)前請(qǐng)求的path_info的標(biāo)志。所有的模塊應(yīng)當(dāng)尊重AP_REQ_ACCEPT_PATH_INFO和AP_REQ_REJECT_PATH_INFO的值,AP_REQ_DEFAULT_PATH_INFO表示遵從慣例。*這是對(duì)修訂中在HOOK_VERY_FIRST上根據(jù)用戶(hù)的喜好設(shè)定的。*/intused_path_info;/*一些其他的配置信息可能根據(jù).htaccess文件進(jìn)行變化。*這些是配置向量,每一個(gè)模塊都有一個(gè)void*指針。*//**配置文件中的可選設(shè)置*/structap_conf_vector_t*per_dir_config;/**對(duì)“這個(gè)”請(qǐng)求的記錄*/structap_conf_vector_t*request_config;/***被這個(gè)請(qǐng)求訪(fǎng)問(wèn)的.htaccess配置指令的鏈表。*注意,當(dāng)心總是加到這個(gè)鏈表的頭部,而從不加到鏈表的尾部*這樣的話(huà),一個(gè)子請(qǐng)求的鏈表可以臨時(shí)的指向父請(qǐng)求的鏈表。*/conststructhtaccess_result*htaccess;/**應(yīng)用到此請(qǐng)求的輸出過(guò)濾鏈表*/structap_filter_t*output_filters;/**應(yīng)用到此請(qǐng)求的輸入過(guò)濾鏈表*/structap_filter_t*input_filters;/**應(yīng)用到此請(qǐng)求的協(xié)議層輸出過(guò)濾鏈表*/structap_filter_t*proto_output_filters;/**應(yīng)用到此請(qǐng)求的協(xié)議層輸入過(guò)濾鏈表*/structap_filter_t*proto_input_filters;/**確定eosbucket已經(jīng)被發(fā)送出去的標(biāo)志*/inteos_sent;/*在記錄最后面放置的事物是為了避免破壞二進(jìn)制兼容性。*如果能夠記住對(duì)記錄重新排序以改善64位對(duì)齊,那再好不過(guò)了。*下次基于某種原因我們可能會(huì)破壞這種二進(jìn)制兼容性。*/};server_recserver_rec對(duì)象定義了邏輯Web服務(wù)器。如果使用虛擬主機(jī),那么每一個(gè)虛擬主機(jī)擁有自己的server_rec文件,使得該虛擬主機(jī)獨(dú)立于其他的虛擬主機(jī)。server_rec對(duì)象在服務(wù)器啟動(dòng)階段時(shí)被創(chuàng)建并一直持續(xù)到整個(gè)httpd關(guān)閉為止。server_rec對(duì)象沒(méi)有自己的池,而服務(wù)器資源需要從進(jìn)程池中分配,進(jìn)程池被所有的服務(wù)器所共享。server_rec對(duì)象具有一個(gè)配置向量以及服務(wù)器資源,包括服務(wù)器名稱(chēng)、服務(wù)器定義、資源和限制、日志信息等。server_rec對(duì)象對(duì)于程序員來(lái)說(shuō)是僅次于request_rec的、第二重要的結(jié)構(gòu),它將在我們整個(gè)模塊編程討論中起著關(guān)鍵的作用。下面是摘自于httpd.h文件中的server_rec對(duì)象的完整定義。/**為每一個(gè)虛擬服務(wù)器存儲(chǔ)信息的結(jié)構(gòu)體*/structserver_rec{/**本服務(wù)器所運(yùn)行的進(jìn)程*/process_rec*process;/**鏈表中的下一個(gè)服務(wù)器*/server_rec*next;/**服務(wù)器的名稱(chēng)*/constchar*defn_name;/**服務(wù)器在配置文件中定義的行數(shù)*/unsigneddefn_line_number;/**/**ServerAlias服務(wù)器的通配符命名*//**/**ServerAlias服務(wù)器的通配符命名*//**包含指向模塊的每服務(wù)器配置結(jié)構(gòu)指針的配置向量*/structap_conf_vector_t*module_config;/**包含指向模塊的每服務(wù)器配置結(jié)構(gòu)指針的配置向量*/structap_conf_vector_t*module_config;/*契約信息*//**管理員的契約信息*/char*server_admin;/**服務(wù)器的主機(jī)名*/char*server_hostname;/**為重定向等*/apr_port_tport;/*日志文件——目前在模塊之間傳送日志*//**錯(cuò)誤日志的名稱(chēng)*/char*error_fname;/**錯(cuò)誤日志文件的文件描述符*/apr_file_t*error_log;/**本服務(wù)器的日志級(jí)別*/intloglevel;/*服務(wù)器的模塊配置和默認(rèn)項(xiàng)*//**如果本服務(wù)器是虛擬主機(jī)則為真*/intis_virtual;/**MIME類(lèi)型信息等等,在我們開(kāi)始檢查目錄信息之前取消*/structap_conf_vector_t*lookup_defaults;/*事務(wù)處理*//**服務(wù)器地址*/server_addr_rec*addrs;/**暫停時(shí)間,在我們放棄之前,Arp的間隔時(shí)間*/apr_interval_time_ttimeout;/**我們等待另外一個(gè)請(qǐng)求的Arp的間隔時(shí)間*/apr_interval_time_tkeep_alive_timeout;/**每個(gè)連接的最大請(qǐng)求數(shù)*/intkeep_alive_max;/**使用持續(xù)連接*/intkeep_alive;/**ServerPath的路徑名稱(chēng)*/constchar*path;/**路徑的長(zhǎng)度*/intpathlen;/**ServerAlias服務(wù)器的普通命名*/apr_array_header_t*names;/**此連接進(jìn)入的服務(wù)器*//**此連接進(jìn)入的服務(wù)器*/apr_array_header_t*wild_names;/**HTTP請(qǐng)求行的限制大小*/intlimit_req_line;/**任何請(qǐng)求頭部字段的限制大小*/intlimit_req_fieldsize;/**請(qǐng)求頭部字段的限制大小*/intlimit_req_fields;};conn_recconn_rec對(duì)象是一個(gè)TCP連接在Apache的內(nèi)部表示。在Apache接收一個(gè)來(lái)自于客戶(hù)端的連接請(qǐng)求時(shí)conn_rec對(duì)象被創(chuàng)建,隨后在該連接結(jié)束時(shí)conn_rec對(duì)象被銷(xiāo)毀。通常由于一個(gè)連接被用來(lái)處理一個(gè)或者多個(gè)HTTP請(qǐng)求,因此一個(gè)conn_rec對(duì)象也對(duì)應(yīng)著一個(gè)或者多個(gè)request_rec對(duì)象。絕大部分應(yīng)用程序只關(guān)心請(qǐng)求,因此會(huì)忽略掉conn_rec對(duì)象,不過(guò)協(xié)議模塊和連接層過(guò)濾器需要使用conn_rec對(duì)象,有些模塊有時(shí)也會(huì)因?yàn)槿蝿?wù)需要而使用conn_rec對(duì)象,如對(duì)一個(gè)HTTPKeepalive(持續(xù)連接)的生命周期內(nèi)優(yōu)化資源。conn_rec沒(méi)有配置信息,但是它具有一個(gè)和連接相關(guān)的瞬時(shí)數(shù)據(jù)配置向量,以及一個(gè)連接資源池。conn_rec還擁有連接輸入和輸出過(guò)濾鏈,以及TCP連接的描述數(shù)據(jù)。區(qū)分請(qǐng)求和連接是非常重要的。請(qǐng)求總是連接的一個(gè)組成部分。Apache使用獨(dú)立的對(duì)象清晰地表示了請(qǐng)求和連接,除了一個(gè)重要的特殊情況。這個(gè)特殊情況我們將在第8章討論連接過(guò)濾的時(shí)候進(jìn)行處理。下面是摘自于httpd.h文件中對(duì)conn_rec對(duì)象的完整定義。/**存儲(chǔ)每個(gè)連接的相關(guān)信息的結(jié)構(gòu)*/structconn_rec{/**和此連接相關(guān)的池*/apr_pool_t*pool;server_rec*base_server;/**被http_vhost.c使用*/void*vhost_lookup_data;/*關(guān)于連接本身的信息*//**本地地址*/apr_sockaddr_t*local_addr;/**遠(yuǎn)端地址*/apr_sockaddr_t*remote_addr;/**客戶(hù)端的IP地址*/char*remote_ip;/**如果可以獲取,則為客戶(hù)端的DNS名稱(chēng);如果沒(méi)有檢查則為NULL;如果沒(méi)有發(fā)現(xiàn),就為“”。該字段只是為get_remote_host()使用。*/char*remote_host;/**如果做rfc1413的查找則設(shè)定。該字段只是為get_remote_host()使用。*/char*remote_logname;/**我們還在談話(huà)么?*/unsignedaborted:1;/**/***this*連接的筆記:從一個(gè)連接發(fā)送筆記到另一個(gè)連接。/**/***this*連接的筆記:從一個(gè)連接發(fā)送筆記到另一個(gè)連接。/**我們將要為另一個(gè)請(qǐng)求保持此連接的激活?*@seeap_conn_keepalive_e*/ap_conn_keepalive_ekeepalive;/**我們做過(guò)double-reverseDNS?-1為是/失敗,0為沒(méi)有。*1為是/成功。*/signedintdouble_reverse:2;/**我們使用它多少次?*/intkeepalives;/**服務(wù)器的IP地址*/char*local_ip;/**當(dāng)UseCanonicalName設(shè)定為DNS時(shí),為ap_get_server_name使用。*(忽略HostnameLookups的設(shè)定)*/char*local_host;/**連接的ID,每個(gè)連接都不同*/longid;/**包含連接的每服務(wù)器配置結(jié)構(gòu)的指針的配置向量*/structap_conf_vector_t*conn_config;*必須在本連接的所有請(qǐng)求上保持正確。*/apr_table_t*notes;/**本連接所使用的輸入過(guò)濾鏈表*/structap_filter_t*input_filters;/**本連接所使用的輸出過(guò)濾鏈表*/structap_filter_t*output_filters;/**本連接得分板信息的處理函數(shù)*/void*sbh;/**為所有bucket/brigade創(chuàng)建所使用的bucket分配器*/structapr_bucket_alloc_t*bucket_alloc;/**本連接的當(dāng)前狀態(tài)*/conn_state_t*cs;/**輸入過(guò)濾器還有懸而未決的數(shù)據(jù)么?*/intdata_in_input_filters;};process_rec和我們以上討論的其他內(nèi)核對(duì)象不同,process_rec是一個(gè)操作系統(tǒng)對(duì)象,而不是一個(gè)Web架構(gòu)對(duì)象。當(dāng)進(jìn)程池提供所有的server_rec對(duì)象(并且通過(guò)s-〉process-〉pool來(lái)訪(fǎng)問(wèn)server_rec對(duì)象),并且應(yīng)用程序使用服務(wù)器生命周期內(nèi)的資源時(shí),應(yīng)用程序需要關(guān)注server_rec對(duì)象和它們自身,其他情況下都不要關(guān)注server_rec對(duì)象。server_rec對(duì)象在httpd.h中定義,此處并沒(méi)有給出它的定義。2.5其他的關(guān)鍵API組件httpd.h頭文件定義了以上這些內(nèi)核結(jié)構(gòu),不過(guò)它也只是應(yīng)用開(kāi)發(fā)者需要使用的很多API頭文件中的一個(gè)。這些頭文件屬于幾個(gè)松散邊界的種類(lèi),可以通過(guò)命名慣例標(biāo)識(shí)出來(lái):ap_頭文件一般定義了較低層次的API元素,通常(盡管不是總是)被其他頭文件包含而被間接訪(fǎng)問(wèn)。http_頭文件定義了應(yīng)用開(kāi)發(fā)者比較感興趣的絕大部分關(guān)鍵的API。這些API也可以通過(guò)一些模塊暴露給腳本語(yǔ)言,例如mod_p
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度綠色環(huán)保產(chǎn)品生產(chǎn)加工合同4篇
- 2025年度地下車(chē)庫(kù)車(chē)位車(chē)庫(kù)設(shè)備維護(hù)保養(yǎng)合同4篇
- 二零二五版知識(shí)產(chǎn)權(quán)許可合同擔(dān)保法執(zhí)行合同3篇
- 2025年度出租車(chē)租賃合同范本(含車(chē)輛維護(hù)保養(yǎng)責(zé)任)4篇
- 二零二五版水產(chǎn)養(yǎng)殖承包與品牌推廣合同3篇
- 個(gè)人房屋擔(dān)保合同范本(2024版)
- 2024經(jīng)典勞務(wù)承包合同范本
- 二零二五年度船舶拆解回收利用合同4篇
- 二零二五年度酒店裝修工程進(jìn)度款支付合同4篇
- 2025年度大產(chǎn)權(quán)房屋租賃合同范本4篇
- 二零二五年度無(wú)人駕駛車(chē)輛測(cè)試合同免責(zé)協(xié)議書(shū)
- 2025年湖北華中科技大學(xué)招聘實(shí)驗(yàn)技術(shù)人員52名歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- 高三日語(yǔ)一輪復(fù)習(xí)助詞「と」的用法課件
- 毛渣采購(gòu)合同范例
- 2023中華護(hù)理學(xué)會(huì)團(tuán)體標(biāo)準(zhǔn)-注射相關(guān)感染預(yù)防與控制
- 五年級(jí)上冊(cè)小數(shù)遞等式計(jì)算200道及答案
- 2024年廣東高考政治真題考點(diǎn)分布匯 總- 高考政治一輪復(fù)習(xí)
- 燃?xì)夤艿滥甓葯z驗(yàn)報(bào)告
- GB/T 44052-2024液壓傳動(dòng)過(guò)濾器性能特性的標(biāo)識(shí)
- FZ/T 81013-2016寵物狗服裝
- JB∕T 14089-2020 袋式除塵器 濾袋運(yùn)行維護(hù)技術(shù)規(guī)范
評(píng)論
0/150
提交評(píng)論