在將多個站點遷移到一個站點(Tenant Feature)的時候碰到了一個棘手的問題,使用者需要繫結自定義域名,但IIS繫結域名的時候會導致這個站點重啟,那麼只要一個使用者繫結了一個域名則會導致這個應用上的其它租戶都會受到影響,下面寫出我們的解決方案,但不一定是最優的。
問題在IIS上繫結域名導致應用程式重啟
一個簡單的測試
1.新建一個空MVC專案,在MvcApplication類中定義一個全域性的靜態變數
2.建立一個控制器和檢視
3.在檢視頁對MvcApplication中的Count進行++並輸出
4.訪問幾次頁面
5.繫結一個域名
6.重新整理頁面
至此驗證完成,可以看到應用被重啟了。
為什麼繫結域名會導致應用程式重啟
其實原理和更改Web.config檔案會導致應用重啟啟動是一樣的,因為繫結域名時實際在C:\Windows\System32\inetsrv\config\applicationHost.config檔案中增加一了一段配置,如下:
只有IIS會重啟?
答案是否定的,在早期我接觸Java的時候Tomcat等也是需要重啟的,不過是需要手動重啟服務,現在我就不清楚老。
使用Nginx解決問題
為了解決這個問題可謂是找了很多資料,最終無奈使用一個代理伺服器來解決這個問題,雖然我覺得在這裡Nginx受了委屈,因為它更大的作用是負載均衡,但能解決問題就行,以後在大訪問量的時候也可以派上用場,下面就簡述下使用Nginx解決這個問題的過程。
原理其實非常簡單,在使用者訪問一個Url時由Nginx去分配,這樣域名就可以不用直接繫結在IIS上,而由Nginx來分配域名指向哪裡。
提前在IIS上繫結無數個泛解析域名
比如:site1.cs.xxx.com~site9999999.cs.xxx.com,這樣就免去了在新增Tenant時需要繫結域名的尷尬。
將繫結自定義域名的動作交給Nginx
Nginx沒有提供什麼API,只有一個配置檔案和幾個命令,所以我們要做的就是將在Nginx上配置域名的動作自動化,我們為此寫了一個Daemon Service來完成這個動作,下面會介紹並放出這個守護程式的使用說明及原始碼。
這樣IIS繫結域名的問題就解決了,但其實在這個方案之前我們還有過其他的方案。
被Pass掉的方案
1.一臺伺服器只掛一個站點,而這個站點不繫結任何域名,所有指向這個伺服器IP的80埠的請求全部由這個站來響應。
Pass原因:浪費資源,80埠被極大的浪費。
2.每天定點繫結域名
Pass原因:使用者綁完域名後生效時間不確定,可能需要等到晚上12點之後才能生效。
Nginx自動化配置
Server
守護服務的主要原理是這樣的,守護服務提供一個WCF服務,這個WCF服務中有兩個操作,繫結域名和刪除域名,服務約束如下:
具體實現程式碼就不演示了。
使用說明
1.配置守護服務(App.config)
主要有兩個配置:
NginxPath:Nginx的存放路徑,因為我要找到配置檔案和nginx.exe,你懂的。
RunModel:因為Nginx只提供了命令列的模式去執行,所以我需要藉助PowerShell或CMD,注意如果使用PowerShell,則PowerShell的版本必須為3.0及以上。
2.配置Nginx
因為Nginx預設的配置檔案中有很多配置,所以我們單獨把域名的配置獨立出來,這就需要對Nginx原有的配置進行一些修改。
開啟nginx-1.7.2\conf\nginx.conf檔案,在http節點下新增配置 include custom.conf;
到這裡我們的配置就完成了,接下來啟動服務。
Client
1.新增服務引用
2.新增如下測試程式碼
執行之後會發現nginx-1.7.2\conf\下多出了一個custom.conf檔案。
內容為:
到這裡我們就測試通過啦,如果想看效果請自行hosts對映test1.com和test2.com到本地IP。
為了防止繫結失敗我們同時在服務的根目錄下儲存了domains.xml檔案,域名的繫結資訊也會在此保留,這樣大家就可以自己還原啦。
Daemon Service Source Code
http://files.cnblogs.com/ants/ChunSun.NginxServer.DaemonService.zip
說明:該原始碼是我精簡過後的,原來的原始碼是基於Rabbit Kernel的,所以精簡後的原始碼沒有提供日誌等功能的支援,大家可以自行新增。