接着上次的開篇,這次重點講Worker Role和Web Role。
1、什么是Role?
Role可以理解為一種部署方式。我們所要運行的程序,歸根究底是要運行在進程上的。我們開發程序有Windows Service,Web Application,Silverlight等等區分,各有各得用武之地和區別,但是底層都是被host在進程之上,各個進程是相對封閉的,為了能在進程與進程間傳遞數據,於是就有了最早的IO,Remoting,以及我們現在用的非常普遍的WCF Service。當然進城內還有AppDomain的概念,不再細說。我提這些是因為Role在Windows Azure上,正是為了給不同類型的應用分配更加適合於他們的部署方式。
2、Worker Role和Web Role的區別
簡單點說,Woker Role和Web Role的區別在於部署的位置,Web Role所綁定的項目被部署到IIS上,Worker Role所綁定的項目被部署到獨立進程上。就一般意義而言,我們在Web Role上部署用於對外公開的網站或者服務,在Worker Role部署供內部調用的服務或應用。這也不是絕對的,比如說Worker Role里也能部署WCF service和公開基於HTTP協議的服務,但是配置起來比較麻煩還有很多問題,下面我會具體講講我所遇到過的問題。
3、Web Role
先說Web Role,因為Web Role相對比較簡單。怎么創建Web Role,太多教程了,我這里放一個鏈接,我主要講我所遇到的問題。
問題1:在Web Role的RoleEntryPoint中怎么讀取不到配置文件?
我們知道,無論是Web Role還是Worker Role,在綁定的項目里都會有一個Web/WokerRole.cs文件,這個文件里定義的類繼承於RoleEntryPoint。這個類,在Azure上會被Host進程調用,里面有三個可重寫方法,OnStart,Run,OnStop,分別在進程開始,進程運行,進程結束的時候被調用,我們可以在OnStart里Host Service,做一些配置工作等等。我剛才說的Host進程是PaaS用於把我們的項目Host到虛擬機上的進程,它被運行為一個類似於Console的進程。Web Role是被部署到IIS上的,這樣他們之間不是沖突的嗎?其實這個Host的程序有自己獨立的運行位置,它讀取的是App.config而不是Web.config。所以才會出現讀取不了Web.config的內容,所以,至少我們在本地測試的時候,要重新創建一個App.config讓這個Host進程讀取。事情似乎已經解決了,但是事實上,當我把項目發布到實際的雲上的時候,居然還是讀取不了app.config。我遠程登上Instance,發現這個Web Role的Host進程叫做WaIISHost.exe,他的運行位置在E:\base\x64下。因此他是讀不到app.config的數據的。Worker Role的host進程叫做WaWorkerHost.exe,也在這個文件夾下,我猜想是因為它和它要部署的項目的方式是一樣的,他能讀取到app.config的數據。而Web Role默認沒有app.config,所以這個host進程里沒有相關邏輯去處理這個問題。如果有哪位大蝦知道此中原由,希望能告訴我。
那怎么辦呢?最簡單的方法是:我們有Global.asax,所以我們可以在Application_Start里做OnStart的事情,於是就可以讀取到Web.config的信息,不管用於WCF Service還是配置其他東西都可以做到了。
問題2:如何在Web Role里用代碼部署WCF Service?
在Web應用中部署WCF Service最簡單的就是創建*.svc文件來host。但是我這邊Host WCF Service有統一的方法,都是通過代碼來host的,為的是在Worker Role里host和Web Role里host統一配置方式。也不像創建那么多svc文件,不太容易擴展。在Windows Azure上加一樣東西,都是需要重新發布的,不然手動加上去的東西不能保證一直存在。
上個問題中說了,我們不能像worker role里在OnStart里部署service,那么只能在Global.asax里部署。但是需要注意的是,我們在RoleEntryPoint里host wcf service,service的端口,host進程會幫我們自動添加到Firewall上,但是Global.asax並不會幫我們做這些,所以,我們只能自己做。我們要用到的是Startup task這個配置節點。我們需要在host進程host我們的項目的時候,事先用系統權限在Instance的防火牆上加入我們需要事先定義的端口號。startup task可以讓我們運行一個批處理文件或者其他應用程序。因此我們只需要寫一個cmd或者bat文件,寫個腳本讓它運行就可以了。怎么做,開此鏈接:http://msdn.microsoft.com/en-us/library/gg456327.aspx
加端口的腳本是這么寫的:
netsh advfirewall firewall add rule name="InternalEndPoint" dir=in action=allow localport=8888 protocol=tcp
EXIT /B 0
4、Worker Role
問題1:如何在Worker Role里Host對外網公開的restful service或者http的service?
答案可能令大家失望,對於目前而言,Impossible!但是這里有個條件是對外公開的,也就是配置在Input的Http的Endpoint,其他都沒問題。原因在於,Windows Azure自動幫我們做了load balance,至少現在的load balancer沒辦法正確map到worker role里的http服務。但是Web Role,由於有IIS,所以不存在這個問題。不管是不是個bug,現在似乎只能無奈地接受。希望以后能夠修復這個問題。
其他的問題,我再遇到的話隨時在更新。如果大家遇到過什么問題,我看看我遇到過沒有,希望能夠幫到忙。
下次我會講雲上的存儲。