文章版權由作者李曉暉和博客園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/
1.背景
該問題的最終解決離不開公司大拿whs先生的指點,先表示感謝。
某項目的geoserver發布在一台linux上,端口為8082。使用Nginx對該geoserver服務(包括其他服務)做了一個轉發代理,Nginx監聽的端口是8081。由於8082端口沒有對外開放,所以用戶只能訪問該8081端口進行訪問。
由於系統與Geoserver的對接是直接基於OGC服務對接,所以一切正常,但是,用戶依然發現對於Geoserver服務網站的訪問卻存在兩個問題:
a.通過8081代理端口訪問Geoserver網站,圖層無法直接預覽。

b.通過8081代理端口訪問Geoserver時,如果不加上斜杠(/),則會報空指針異常錯誤。

2.問題一:Geoserver服務無法預覽問題
2.1問題排查過程
點擊預覽時錄制腳本:

可見本應是8081端口請求變成了默認的80端口,導致樣式等文件無法加載,從而出現預覽為空。跟蹤源碼,發現URL的獲取方式為:

再查看目前Nginx的配置為:

可見,此處獲取到的URL僅為瀏覽器輸入地址的IP,而沒有端口號,所以出現了腳本中默認80端口的問題。加上端口配置,重啟Nginx服務,解決。
配置修改為:

重啟Nginx操作:

2.2關於proxy_set_header參數的理解
其語法規則為:
語法:proxy_set_header field value;默認值:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
上下文:http, server, location
其作用為:
允許重新定義或者添加發往后端服務器的請求頭。value可以包含文本、變量或者它們的組合。 當且僅當當前配置級別中沒有定義proxy_set_header指令時,會從上面的級別繼承配置。
對上面問題出現我們可以這樣理解:當使用了nginx反向服務器后,在web端使用request.getRemoteAddr()(本質上就是獲取$remote_addr),取得的是nginx的地址,即$remote_addr變量中封裝的是nginx的地址,當然是沒法獲得用戶的真實ip的。
3.問題二:瀏覽器輸入首頁訪問地址不帶斜杠報錯問題(http://ip:8081/geoserver報錯)
3.1.一個奇怪的現象
首先,我在本地單獨發布了一個Geoserver測試該問題,發現即使我輸入不帶斜杠,訪問時瀏覽器也會為我自動加上斜杠訪問。而服務器上的Geoserver則不會。
最開始懷疑為瀏覽器自身補全功能,但是這又無法解釋訪問雲上地址時不補全現象。最后通過查資料確定為如下情況導致:
以訪問http://ip:8081/geoserver為例子,在windows 系統上,一般如果服務器識別根目錄有文件夾為geoserver(沒有文件名為geoserver) 時,他們會自動給目錄加斜杠。但是,如果是linux 系統則不會,linux 系統會把它作為文件處理(不會以目錄形式處理),直接就打開geoserver文件,所以不會加上斜杠。
因為服務器為linux系統,所以不會自動加上斜杠。
3.2從報錯信息排查起
3.2.1正常情況下,帶/時跳轉的原理
Geoserver的web.xml中有如下配置:
<welcome-file-list>
<welcome-file>/index.html</welcome-file>
</welcome-file-list>
所以帶上/時,會自動跳轉至index.html頁面,而
index.html中有:

於是請求再度調轉為:http://192.168.**.**:8081/geoserver/web/,進入Geoserver首頁。
3.2.2沒有按照套路走,報錯發生的原因在哪里
我們再看web.xml中的配置:


此時因為匹配規則是/*,所以所有請求要先經過過濾器之后,才會走到歡迎頁面設置,查看源碼發現:

3.3解決方法
經過認真思考,有兩種解決方案:
一種是對Nginx配置進行針對性優化;
一種方案是對Geoserver升級。
以下分段進行分別描述。
4.針對問題二:Nginx配置優化
4.1需求描述
整理需求為:我們需要實現在直接訪問Geoserver(不帶/)時轉發自動加上/。但是針對Geoserver/(帶上/)時轉發不再自動加上/(//現象會導致訪問404問題)。
查找資料,Nginx的rewrite機制可以非常好的解決該需求:
和apache等web服務軟件一樣,Nginx的rewrite的組要功能是實現RUL地址的重定向。Nginx的rewrite功能需要PCRE軟件的支持,即通過perl兼容正則表達式語句進行規則匹配的。默認參數編譯nginx就會支持rewrite的模塊,但是也必須要PCRE的支持。rewrite是實現URL重寫的關鍵指令,根據regex(正則表達式)部分內容,重定向到replacement,結尾是flag標記。
4.2Nginx相關配置總結
4.2.1語法規則
其語法規則為:
rewrite <regex> <replacement> [flag];
關鍵字 正則 替代內容 flag標記
關鍵字:其中關鍵字error_log不能改變
正則:perl兼容正則表達式語句進行規則匹配
替代內容:將正則匹配的內容替換成replacement
flag標記:rewrite支持的flag標記
flag標記說明:
last #本條規則匹配完成后,繼續向下匹配新的location URI規則
break #本條規則匹配完成即終止,不再匹配后面的任何規則
redirect #返回302臨時重定向,瀏覽器地址會顯示跳轉后的URL地址
permanent #返回301永久重定向,瀏覽器地址欄會顯示跳轉后的URL地址
4.2.2執行順序
a.執行server塊的rewrite指令(這里的塊指的是server關鍵字后{}包圍的區域,其它xx塊類似)
b.執行location匹配
c.執行選定的location中的rewrite指令
如果其中某步URI被重寫,則重新循環執行1-3,直到找到真實存在的文件
如果循環超過10次,則返回500 Internal Server Error錯誤
4.2.3正則表達式規則
. : 匹配除換行符以外的任意字符
? : 重復0次或1次
+ : 重復1次或更多次
* : 重復0次或更多次
\d :匹配數字
^ : 匹配字符串的開始
$ : 匹配字符串的介紹
{n} : 重復n次
{n,} : 重復n次或更多次
[c] : 匹配單個字符c
[a-z] : 匹配a-z小寫字母的任意一個
小括號()之間匹配的內容,可以在后面通過$1來引用,$2表示的是前面第二個()里的內容。正則里面容易讓人困惑的是\轉義特殊字符。
4.2.4常用變量
$args : #這個變量等於請求行中的參數,同$query_string
$content_length : 請求頭中的Content-length字段。
$content_type : 請求頭中的Content-Type字段。
$document_root : 當前請求在root指令中指定的值。
$host : 請求主機頭字段,否則為服務器名稱。
$http_user_agent : 客戶端agent信息
$http_cookie : 客戶端cookie信息
$limit_rate : 這個變量可以限制連接速率。
$request_method : 客戶端請求的動作,通常為GET或POST。
$remote_addr : 客戶端的IP地址。
$remote_port : 客戶端的端口。
$remote_user : 已經經過Auth Basic Module驗證的用戶名。
$request_filename : 當前請求的文件路徑,由root或alias指令與URI請求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 請求使用的協議,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服務器地址,在完成一次系統調用后可以確定這個值。
$server_name : 服務器名稱。
$server_port : 請求到達服務器的端口號。
$request_uri : 包含請求參數的原始URI,不包含主機名,如:”/foo/bar.php?arg=baz”。
$uri : 不帶請求參數的當前URI,$uri不包含主機名,如”/foo/bar.html”。
$document_uri : 與$uri相同。
4.2.5動態變量參數
$1-$9存放着正則表達式中最近的9個正則表達式的匹配結果,這些結果按照子匹配的出現順序依次排列。
$1 代表的是匹配的第一個結果。
括號表示的是表達式定義的“組”(group),並且將匹配這個表達式的字符保存到一個臨時區域(一個正則表達式中最多可以保存9個) 上面的表達式有2個匹配組 (\w+) 和 (.*) 所有后面可以用 $1 和 $2 來用
比如例子^/(\w+)/(.*)$ /$1/index.php last;
對應為:/abc123/bcdfda => /abc123/index.php
4.3解決該問題的最終配置

5.針對問題二:Geoserver升級
進入Geoserver下載官網進行學習:http://geoserver.org/download/

由於公司標准運行環境為jdk1.7.x,所以主要對Geoserver2.8.x和Geoserver2.9.x進行了對比研究,總結如下:
5.1.運行環境
a. 2.9.x系列雖然描述為compatible with Java 8,個人理解為jdk7和jdk8應該都可以運行。 但是,分別在jdk1.7._067和雲上的1.7._079上測試過,不可運行:

b.在2.8.X系列上進行了相關測試,均可以支持jdk1.7.x系列。
5.2.geoserver2.8.5版本的優點

總結優化即是:強化了三維服務支持、集成了更多(最新)的插件、針對某些特殊情況下的數據發布(如局域網共享文件安全機制)導致的閃退等問題進行了修復。
公司主要用到的基於本地矢量數據或者PG數據的WMS、WFS服務沒有特殊說明的優化和改動。
但是geoserver的代碼架構還是做了不少變化。
同時,針對不帶斜杠訪問報錯問題,2.8.5上也做了優化:

5.3.基於業務的測試
a.基於公司雲上一鍵安裝環境進行測試,目前部件展示、I查詢、網格查詢正常:

b基於PG測試,也是正常。

5.4.但是,有一個小缺點
整個2.8.x系列,在版本chrome 63.0.3239.132上,geoserver平台在某些彈出框上會出現內容為空。但是IE(9以上)沒有這個問題。考慮到這類手動操作不常見,不影響工程同事使用。

6.學習上的一點感慨
如WHS先生所說,技巧可以規避問題,知其所以然才可以解決問題。
-----歡迎轉載,但保留版權,請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/
如果您覺得本文確實幫助了您,可以微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^


