Tomcat前端配置一個(gè)HTTP服務(wù)器應(yīng)該是大部分應(yīng)用的標(biāo)配了,,基本思路就是所有動(dòng)態(tài)請(qǐng)求都反向代理給后端的Tomcat,HTTP服務(wù)器來(lái)處理靜態(tài)請(qǐng)求,,包括圖片,、js、css,、html以及xml等,。這樣可以讓你的應(yīng)用的負(fù)載能力提高很多,前端這個(gè)HTTP服務(wù)器主流用的最多的當(dāng)屬Apache HTTP Server和nginx,。今天這篇文章主要講解的是這種組合的方式的前提下,,后端的Tomcat中的app在301跳轉(zhuǎn)的時(shí)候遇到的一個(gè)問(wèn)題。 問(wèn)題先把問(wèn)題說(shuō)清楚,,前端nginx占用81端口,,因?yàn)?0干了別的,暫時(shí)懶得停80的應(yīng)用,,暫時(shí)修改為81端口而已,。然后Tomcat占用8080端口,具體配置如下(只是截取了server中的一段):
上面的代碼只是簡(jiǎn)單舉例,,其中處理靜態(tài)內(nèi)容的部分也可以用目錄alias或者root的方式去處理,,效果應(yīng)該一樣的,但是具體區(qū)別我也沒(méi)深入了解,,不過(guò)這不是今天的重點(diǎn),。在這個(gè)配置下出現(xiàn)的問(wèn)題就是當(dāng)訪問(wèn)http://host:81/app1/Login.do的時(shí)候,登錄成功需要301跳轉(zhuǎn)到用戶(hù)中心頁(yè)面,,然后跳轉(zhuǎn)的地址本應(yīng)該是http://host:81/app1/userindex.do,,但是結(jié)果不太盡如人意,瀏覽器實(shí)際出現(xiàn)的地址http://host/app1/userindex.do,。這里面的問(wèn)題就是81端口沒(méi)了,,跑80端口去了,自然就404了。扯了一大段,,這就是今天想說(shuō)的問(wèn)題,。 問(wèn)題出現(xiàn)了,自然得分析原因,,由于我們這個(gè)項(xiàng)目中需要支持ssl,,使用了Struts1.2的Framework,于是采用了SecurePlugIn(想了解的可以參照SSLExt Command 2.3節(jié))的插件來(lái)處理,。那么我首先懷疑是不是這個(gè)東西在作怪,,看了下配置文件這個(gè)插件的enable都直接為false??磥?lái)不是這個(gè)插件作怪了,,那么在不是應(yīng)用本身邏輯在作怪的話那么可能是服務(wù)器配置有問(wèn)題了,這個(gè)時(shí)候就應(yīng)該直接從http請(qǐng)求開(kāi)始分析了,。 首先我打開(kāi)chrome,,然后來(lái)分析這次request發(fā)生了什么(打開(kāi)開(kāi)發(fā)者工具中的Network面板),能發(fā)現(xiàn)的基本就是請(qǐng)求Login.do是沒(méi)問(wèn)題的,,但是Login.do之后發(fā)生的301重定向是錯(cuò)誤的,,一個(gè)重要的線索就是Login.do的請(qǐng)求中response中的Location的值是http://host/usercenter.do,這里丟掉了端口號(hào),。這個(gè)地方的具體原因后邊會(huì)提到,,先說(shuō)下解決思路。 解決思路可以有兩個(gè),,第一個(gè)就是nginx是可以利用proxy_redirect來(lái)修改response的Location和Refresh的值,,Location自然可以被重新修改為81端口的地址,第二個(gè)就是找到是誰(shuí)把Location搞錯(cuò)了,,修改這個(gè)地方別搞錯(cuò)Location就行了,。 解決思路1:利用nginx的proxy_redirect這個(gè)思路其實(shí)有點(diǎn)偏重解決問(wèn)題型,就是我看到這里錯(cuò)了,,原因不糾結(jié),,我讓你好使就可以了??赡芎枚嗳硕际沁@個(gè)思路,,畢竟解決問(wèn)題是首要目的。 很多人在配置nginx的時(shí)候,,習(xí)慣參考官方wiki的Full Example (taken from Nginx site),,來(lái)做一些配置,參考這個(gè)肯定比參考baidu搜索出來(lái)的文檔要靠譜很多,,建議不了解每個(gè)屬性的可以來(lái)參照下這個(gè)官方示例,。這個(gè)配置里面proxy_redirect的屬性為off,很多人應(yīng)該沒(méi)有問(wèn)過(guò)為什么就直接根據(jù)人家來(lái)做了,之所以這樣下結(jié)論是因?yàn)槲铱吹教鄧?guó)內(nèi)人的集成例子中都是這樣設(shè)置的了,。我這里也是這樣設(shè)置的,,以前也倒是沒(méi)想起來(lái)問(wèn)下為啥,的確不太符合我的風(fēng)格,。反正服務(wù)器是這樣配置的,,現(xiàn)在是出來(lái)問(wèn)題了,我們先來(lái)看下這個(gè)屬性能做什么,。 首先看官方文檔Reference:proxy_redirect的說(shuō)明:
基本意思就是修改代理服務(wù)器(也就是此時(shí)的nginx)的response的頭信息里面的
這樣重啟 解決思路2:找到問(wèn)題原因,修改出錯(cuò)的地方解決根據(jù)上個(gè)思路解決了問(wèn)題以后,,一點(diǎn)都沒(méi)如釋重負(fù)的感覺(jué),,反而各個(gè)地方都覺(jué)得很空的感覺(jué),因?yàn)橛泻脦讉€(gè)疑問(wèn)沒(méi)解決,,其中包括為啥是80而不是81或者8080沒(méi)道理,?這個(gè)Location是不是應(yīng)該nginx來(lái)重寫(xiě),修改掉那個(gè)跳轉(zhuǎn)錯(cuò)的地方是不是比這個(gè)思路會(huì)更好,? 那就先來(lái)分析下問(wèn)題的原因:既然response的Locaiton不對(duì),,那么首先想到的就是這個(gè)Location是誰(shuí)構(gòu)造出來(lái)的,了解HTTP協(xié)議的人應(yīng)該都知道,,request中的header都是client(瀏覽器等)構(gòu)造好發(fā)送給服務(wù)器的,,服務(wù)器收到請(qǐng)求以后構(gòu)造response信息返回給client。那么這樣Location這個(gè)值肯定就是nginx或者Tomcat給搞出的問(wèn)題了,,這個(gè)地方nginx只是一個(gè)proxy server,,那么response肯定是Tomcat發(fā)給nginx的,也就是說(shuō)我們應(yīng)該從Tomcat下手來(lái)分析這個(gè)問(wèn)題,。 首先我就看了下Tomcat的官方文檔 Proxy Support,,這里面對(duì)這個(gè)介紹如下:
意思就是proxyPort的屬性就是用來(lái)我這種nginx做前端代理服務(wù)器Tomcat在后端處理動(dòng)態(tài)請(qǐng)求的情況的。修改屬性的值可以作用于應(yīng)用的兩個(gè)方法,,主要用于絕對(duì)路徑和重定向之用,。如果不配置的話,可能會(huì)不對(duì)頭,。那么既然是這里不對(duì)頭,,我就先把server.xml中我這個(gè)http的connector的配置加入了 事情到了這個(gè)時(shí)候,,其實(shí)問(wèn)題基本明了了,,不過(guò)我還是對(duì)這個(gè)Tomcat為啥默認(rèn)解析了80端口很是疑惑。我下載了Tomcat的source來(lái)看下問(wèn)題究竟,,看了以后用通俗的語(yǔ)言來(lái)表述的話就是這樣:如果默認(rèn)不配置proxyPort默認(rèn)為0,,然后在構(gòu)造response的時(shí)候判斷如果proxyPort為0那么就不添加端口,不添加端口當(dāng)然就默認(rèn)走了80端口,,源代碼如下:
到了這里就真相大白了,心里也沒(méi)結(jié)了,,一塊石頭終于落地了,。 總結(jié)也就是說(shuō)Tomcat在設(shè)計(jì)的時(shí)候是對(duì)這種代理服務(wù)器和Tomcat集成的情況做了考慮,80端口之所以沒(méi)問(wèn)題是因?yàn)閜ort為空,,瀏覽器會(huì)默認(rèn)走80端口,,如果nginx這代理服務(wù)器不是80這個(gè)端口應(yīng)該需要配置proxyPort的屬性的,這樣就不會(huì)遇到這個(gè)問(wèn)題,。 那么基于這個(gè)來(lái)總結(jié)的話,,兩種解決方式都可以,不過(guò)修改Tomcat配置文件的方式是我最推薦的,,因?yàn)檫@個(gè)思路看起來(lái)是又合理,、又易于理解。我的感覺(jué)就是誰(shuí)的事情誰(shuí)來(lái)解決比較好,,nginx作為proxy server 你就只需要做你的靜態(tài)文件的解析,,和把動(dòng)態(tài)請(qǐng)求方向代理的服務(wù)器就可以了,既然Tomcat把這個(gè)信息構(gòu)造錯(cuò)了,,人家也有提供了解決方案,,就根據(jù)你的情況合理配置就可以了。 一直以來(lái)自己是個(gè)特別較真的人,,各種事情都是,,希望每個(gè)人在解決問(wèn)題的時(shí)候不要僅限于解決了問(wèn)題就ok吧,更多的去了解問(wèn)題的真相才會(huì)進(jìn)步更快,,例如這個(gè)問(wèn)題其實(shí)有一個(gè)必要前提是需要了解一些HTTP的協(xié)議的基礎(chǔ)知識(shí),,如果不了解的話可能你不會(huì)很快判斷出Location出了問(wèn)題,你可能也不會(huì)很快知道response是誰(shuí)構(gòu)造錯(cuò)的,。建議大家都讀下《HTTP權(quán)威指南》,,每個(gè)做web開(kāi)發(fā)的工程師都應(yīng)該擁有這本書(shū),可以大概先看一遍了解,后續(xù)需要就拿出來(lái)作為工具書(shū)查閱資料,。如果作為工具書(shū)的話,,那就強(qiáng)烈推薦大家購(gòu)買(mǎi)圖靈推出的《HTTP權(quán)威指南》電子版,我都把我的紙質(zhì)書(shū)賣(mài)了換了電子版了,,買(mǎi)了都說(shuō)好啊,。不過(guò)順帶說(shuō)句圖靈購(gòu)買(mǎi)也需要輸入個(gè)兌換碼才能送銀子,這體驗(yàn)不好,,因?yàn)榭偸峭?,著急買(mǎi)書(shū)的都會(huì)忘記,建議改進(jìn)下啊,。 |
|