標籤:多網域名稱 頁面擷取url 方案 express 分布式
由於系統是分布式部署的,並且有多個網域名稱,所以經常涉及到擷取url的問題。這是系統架構層面需要提供的能力,否則每個模組都需要自己去想辦法擷取ip,就會很混亂,上線也容易發生bug
主要需要解決幾個問題:
1、能夠自動區分開發環境和生產環境。比如部署上線,url可能是http://www.xxx.com/svc/hello,而在本地開發的時候應該是http://127.0.0.1/svc/hello。而不能寫死,否則開發和部署就要換來換去,很麻煩
2、能夠根據不同的服務,區分URL。比如擷取驗證碼的服務,應該調用http://www.xxx.com/svc/getCode,而相關的服務,應該調用http://wx.xxx.com/svc/xxx
本文總結分享一下思路:
設定檔
1、應用有對應的設定檔,裡面說明了是以開發模式,還是以生產模式啟動。並且將URL分離開,比如鑒權相關的URL,相關的URL,普通服務相關的URL等
2、同時,設定檔有多份,比如topo-dev.json,topo-production.json,topo-image.json等。這樣就把不同的環境隔離開,如果是以開發模式啟動,載入的就是topo-dev.json,其中配置的URL都是127.0.0.1這樣的
3、啟動的時候,載入此設定檔,並將關鍵資訊放在global._g_env全域變數下面,運行時就能很方便地擷取到環境和URL資訊了
服務端擷取URL
服務端的代碼也是跑在node環境下,所以要擷取URL就很簡單,通過_g_env.url,就可以拿到設定檔裡的路徑了
前端頁面擷取URL
前端頁面經常也需要發送ajax請求,所以也需要知道url。但是靜態js沒有辦法擷取server的環境資訊和URL等,所以需要從服務端擷取到這些資訊,一種可行的做法是:
首先服務端有一個服務,專門將這些資訊下發:
function clientSettingScript(req, res, next){ var script = "window.global = {_g_server:{}}; \n"+ ";global[\"_g_server\"].staticurl=\"" +global["_g_topo"].clientAccess.staticurl + "\"\n"+ ";global[\"_g_server\"].uploadurl=\"" +global["_g_topo"].clientAccess.uploadurl + "\"\n"+ ";global[\"_g_server\"].authurl=\"" +global["_g_topo"].clientAccess.authurl + "\"\n"+ ";global[\"_g_server\"].serviceurl=\"" +global["_g_topo"].clientAccess.serviceurl + "\"\n"+ ";global[\"_g_server\"].wxserviceurl=\"" +global["_g_topo"].clientAccess.wxserviceurl + "\"\n"+ ";global[\"_g_server\"].nail_pc_url=\"" +global["_g_topo"].connector.nail_pc_url + "\"\n"+ ";global[\"_g_env\"] =\"" +global["_g_topo"].env+ "\";\n"; res.end(script);}
這是一個express的普通服務,但是其實是一段js指令碼。在前端頁面,用script標籤來載入它
<script src="/svc/portal/setting"></script>
這樣當瀏覽器拿到響應之後,就會將它作為一段js指令碼來執行,在window上放了一個全域變數global,其中有環境資訊和URL資訊
同時,URL只包含網域名稱,頁面根據實際情況,組裝完整的URL,比如:
security_code_url: global["_g_server"].serviceurl + "/getCode/"
總結
這種做法的關鍵在於:
1、把URL和環境資訊放到單獨的設定檔中,而不是寫死在代碼裡。同時根據開發環境、生產環境、鏡像環境隔離不同的設定檔
2、server端專門寫一個服務,把這些配置資訊給到用戶端頁面,用戶端頁面也不用寫死了
多網域名稱環境,頁面擷取url的一種方案