Windows Azure一些小技巧集合

我最近作了一個Windows Azure上面的項目,本身在作的過程當中遇到了不少問題。有的是我本身摸索解決,有的是到網上尋找零碎的信息結合起來解決的。我感受應當把某些解決方法集中一下,方便我之後查閱,也方便其餘人。本文涉及的內容主要是Azure的Cloud Service服務。shell

 

在Windows Azure中啓用Trace

部署到Windows Azure上的代碼是不可以用Visual Studio直接調試的,因此保留完善的Trace來診斷問題很是重要。用Windows Azure SDK 2.0創建的項目已經爲雲端Trace作好了準備,但並無真正啓用。如今咱們來看怎麼完善最後的工做。服務器

 

Windows Azure Cloud Service項目的Trace是在主項目上集中配置的。打開主項目的Roles文件夾能夠看到每一個Role的cscfg文件。咱們雙擊其中一個打開,默認是這樣的:網絡

Configuration

注意下面的Diagnostics段,勾選的話就打開了Trace。可是默認狀況下,Trace使用的Storage Account是「DevelopmentStorage」其實就是本地的Azure模擬器。咱們只要爲其指定一個真正的Azure Storage Account就能夠了。建議專門爲Trace創建一個Storage Account,而不要使用其餘數據的Account。如圖便可選擇一個Storage Account。併發

StorageAccount

 

在代碼中,直接使用System.Diagnostics.Trace類的相應的方法,例如WriteLine或者TraceError等便可將Trace寫入指定Storage Account的表格中。由於Azure的存儲是收費的,因此分級使用Trace很重要,推薦使用TraceInformation,TraceError這樣自帶錯誤等級的方法。某些使用Windows Azure SDK老版本或者從其餘項目移植爲Azure項目時,App.config或者Web.config中可能缺乏Trace Listener的設置,這樣也沒法在運行時正確寫入Trace。咱們能夠打開WebRole或者WorkerRole項目本身的.config,確認有這樣一段在configuration段以內:異步

 

 
  <system.diagnostics>
    <trace>
      <listeners>
        <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics">
          <filter type="" />
        </add>
      </listeners>
    </trace>
  </system.diagnostics>
 

 

WebRole/WorkerRole項目引用的DLL等類庫工程直接使用System.Diagnostics.Trace類便可,無需進行配置。async

 

除了使用Trace類以外,Windows Event Log也很重要,由於諸如雲服務運行時異常,崩潰之類的信息是在Windows Event Log當中的。咱們能夠在前面的Cloud Service主項目的配置頁,單擊Edit按鈕來進行篩選。若是須要諸如性能計數器等額外信息,也能夠在此選擇:工具

image

 

最後是Trace的查看方法。通過以上配置,System.Diagnostics.Trace記錄下來的Trace會保存到設定Storage Account的WADLogsTable表格中;Windows Event Logs記錄到WADWindowsEventLogsTable表格中。在Azure的管理門戶網站上是看不到表格存儲的,須要用代碼來讀取其中的內容。固然,咱們也能夠用一些現成的第三方工具,好比我用的是這個Azure Storage Explorer性能

storageExplorer

 

如此一來,從啓用Trace,代碼中記錄Trace到查看Trace的全套流程就都實現了。測試

 

在WebRole和WorkerRole的VM上安裝Windows Server的功能

咱們都知道Azure Cloud Service的WebRole和WorkerRole都是在各自的VM裏面執行的,其VM的操做系統以及版本均可以在部署的時候進行指定。例如咱們能夠選擇Windows Server 2012等系統。可是默認狀況下大部分Windows Server的功能都是沒有啓用的。一臺本地的服務器咱們能夠用Windows Server管理工具來安裝新功能/角色,那麼在Cloud Service下面怎麼安裝呢?答案是使用PowerShell。網站

 

首先咱們須要肯定所需功能的名稱。在Windows Server本地的PowserShell中執行Get-WindowsFeature命令。若是沒有本地的Windows Server,能夠登陸到Azure的雲服務VM上,或者建立一臺單獨的VM,在裏面執行。你將會看到以下的功能列表:

image

 

第一列是模擬在GUI模式下看到的樹狀的功能列表,而第二列就是在PowerShell中安裝它所需的名稱。記住這個名稱。下面咱們要在Cloud Service虛擬機部署的時候利用部署任務來安裝Windows Feature。在須要該Windows功能的WebRole或者WorkerRole項目中添加一個擴展名是ps1的文件,而且選擇老是拷貝到Output文件夾。

image

 

在ps1中輸入以下代碼。個人例子是安裝了一個Media Foundation功能。注意,安裝該功能是否須要重啓應當提早肯定清楚。須要重啓的功能安裝命令後面加-Restart。若是不加的話部署時會卡在那裏。


Import-Module Servermanager 
$mf = Get-WindowsFeature "Server-Media-Foundation" 
if (!$mf.Installed) { 
  Add-WindowsFeature -name "Server-Media-Foundation" -Restart 
}
 

 

注意,保存這個文件的時候咱們必定要選擇VS文件菜單中的「Save with advanced options」選項,而後按照UTF-8 without signature這個編碼來保存。由於UTF-8的三字節特徵字符是PowerShell所不支持的。切記這一步操做!

image

 

接下來再給該項目新加一個bat文件。這個文件當中咱們調用PowerShell來執行上述部署命令:


if "%EMULATED%"=="true" goto :EOF
powershell -command "Set-ExecutionPolicy Unrestricted" 2>> error.out
powershell .\installfeatures.ps1 2>> error.out
 

 

第一句首先咱們將PowerShell的執行策略改成Unrestricted,由於它默認是Restricted,不能進行Windows功能安裝等任務。咱們將這個文件保存爲startuptask.bat,一樣要利用高級保存選項將它保存爲UTF-8 without signature編碼,並且別忘了選中老是拷貝到Output文件夾。

 

最後一步咱們要到Cloud Service主項目的ServiceDefinition.csdef文件中添加執行bat文件的任務。先找到這個文件:

ServiceDefinition

在剛纔添加過ps1和bat文件所對應的WebRole或者WorkerRole的配置段中,添加這樣的代碼:


<Startup>
  <Task commandLine="startuptask.bat" executionContext="elevated" taskType="simple">
    <Environment>
      <Variable name="EMULATED">
        <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated"/>
      </Variable>
    </Environment>
  </Task>
</Startup>
 

 

其中咱們創建的EMULATED環境變量就是以前bat文件中引用的。利用這個環境變量就能夠防止本地調試Azure的時候執行上述ps1腳本。如此一來,只要部署Cloud Service項目,其VM上就會自動安裝上Media Foundation功能。其餘經由PowerShell能夠實現的VM管理任務也能夠照此方法容易地實現。

 

Windows Azure Storage Service使用心得

接下來是一些關於Storage Service的使用心得集合,若是錯誤歡迎指出。

 

調整併發鏈接數限制

剛創建好的Cloud Service WorkerRole的OnStart()方法中咱們能看到這樣一行代碼

ServicePointManager.DefaultConnectionLimit = 12;
建議你們把這個限制改爲100甚至更高。由於Azure的存儲服務訪問都要通過網絡訪問,瓶頸出如今鏈接數限制上是很常見的問題。要注意的是,Azure Storage Service也不能過分併發訪問。若是鏈接數太高也會返回服務端錯誤。明智的作法是適當進行分組,而後併發地對BlockBlob的各個Block進行訪問;或者併發地對多個Blob進行訪問。我在實踐中選擇的分組大小是10個Block一組,我並無測試它是不是最好的分組大小,有興趣的人能夠親自去試一下。

 

使用BufferedStream訪問Blob

Windows Azure SDK的Blob對象有一個屬性,叫StreamMinimumReadSizeInBytes。它的默認值是4MB。別被它騙了,實際上Blob的OpenRead和OpenWrite打開的流,若是進行尺寸很小的頻繁讀寫,性能仍是很是差的。實際上OpenRead和OpenWrite打開的流比較適合上載和下載整段的數據。當你須要按照訪問本地文件那樣的邏輯訪問Blob的時候,必定要給他套上一個System.IO.BufferedStream。並且記得手工把Buffer的大小改爲4MB(默認是4K,對Azure的Blob來講毫無做用)。

 

關於表格存儲中的DateTime類型

我在一個表格存儲所對應的Entity類中使用了DateTime類型的屬性,結果發現插入操做老是失敗。通過個人尋找,發現DateTime類型的屬性不初始化就直接進行插入或者更新操做的話是不行的。由於Azure Table Storage中的時間日期格式與.net的日期格式範圍不一樣。Azure的日期只能表示從公元1601年開始,而.net的日期不初始化的話是從0001年開始的。這樣一旦提交就是一個非法日期了。那麼,若是我真的有必要表示一個日期是未初始化的應該怎麼作呢?只要將該字段聲明成DateTime?類型便可(Nullable<DateTime>)。

 

採用Task風格的async/await來訪問Azure Storage Service

Azure storage service的訪問所有都經過網絡來進行,因此充分利用異步操做能夠很好地節約本地的線程資源,提升響應性。可是當前的Windows Azure SDK 2.0裏面並未提供C#5/VB11的async/await語法可以訪問的Task風格異步API,而是傳統的Begin/End風格。聽說在下一個版本的SDK當中會全面提供Task風格的異步API,在此以前咱們只好繞路一下。作法就是利用Task.Factory對象的FromAsync方法。好比說咱們但願異步地調用CloudBlockBlob的Delete方法,能夠這樣寫:

await Task.Factory.FromAsync(
    blob.BeginDelete(null, null),
    blob.EndDelete);
 

這個方法可以處理各類有返回值或者沒有返回值的Begin/End系列異步方法。有返回值時須要手動傳入返回值的類型做爲泛型參數:

var stream = await Task.Factory.FromAsync<Stream>(
    blob.BeginOpenWrite(null, null),
    blob.EndOpenWrite);

 

以上就是我對Windows Azure開發總結出的一些粗淺的小技巧,但願可以對你們有所幫助。若是建議或者討論,歡迎到新浪微博上關注 @裝配腦殼

相關文章
相關標籤/搜索