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开发总结出的一些粗浅的小技巧,但愿可以对你们有所帮助。若是建议或者讨论,欢迎到新浪微博上关注 @装配脑壳

相关文章
相关标签/搜索