现实世界:Windows Azure角色的启动生命周期
现实世界:Windows Azure角色的启动生命周期
2011年05月20日
公告 :本博客为微软云计算中文博客 的镜像博客。 部分文章因为博客兼容性问题 ,会影响阅读体验 。如遇此情况,请访问 原博客。
这篇文章的作者是Cory Fowler [@SyntaxC4 ]. Cory自称为"开发即服务"。它是一个技术团队的领导者、指导者和演讲者,他乐于和别人分享他对软件开发的激情。基于对Windows Azure(微软的云计算平台) 的集中研究,Cory已经被授予微软MVP 。他已是的云计算的权威,同时也开发多种解决方案包括而不局限于网站(用ASP.NET MVC & Silverlight)、Windows Phone 7应用程序(用Silverlight & XNA)和其它的使用C#编程语言的解决方案。Cory在加拿大多伦多的ObjectSharp 当顾问。 当你开始部署应用程序到Windows Azure时,你会发现应用程序被部署时需要比Windows Azure Guest OS Base Image (阅读:怎样改变Windows Azure上的客户操作系统 )上提供的更多的功能性。Windows Azure SDK 1.3可以实现这个,这就是所谓的启动任务 ,还与SDK 1.3一起介绍了Full IIS Support,它的优先级别高于遗留(但仍具功能性的)的托管的Web核心部署模型(阅读:新的完全IIS功能:与托管的Web核心的差异 )
就像一个ASP.NET Web窗体开发人员学习ASP.NET页面生命周期 ,对一个为Windows Azure建立应用程序的开发者来说了解角色启动生命周期 是很重要的,即他们什么时候在创建启动脚本和利用Windows Azure虚拟机角色之间做决定。 在Windows Azure [SDK 1.3]上的角色启动过程中有一些参与者。请注意我只是说Full IIS Support中的参与者(这不是托管的Web核心)。
启动任务 在Windows Azure中一个启动任务是一个在云服务的定义文件(.csdef)中被引用的命令行可执行文件。当一个部署上传到Windows Azure,Windows Azure平台的一个被称作结构控制器的组件读取定义文件来为你的部署分配必要的资源。一旦这个环境建立,结构控制器初始化角色启动过程。
为了更好地理解启动任务,让我们深入到云服务定义文件的"任务"元素。
CommandLine属性 这里是当启动任务运行时被执行文件的名称。这个脚本或可执行程序在角色里如何运行将在executionContext和 taskType里介绍。
ExecutionContext属性 启动任务的executionContext属性定义了脚本或可执行程序文件在一个特定的角色里运行的权限水平。这里有两种类型的执行文本: Limited:在与角色运行相同的权限下运行脚本或可执行文件
Elevated:享有管理特权来运行脚本或可执行文件
TaskType属性 启动任务的taskType属性定义了一个启动任务过程是怎样被执行的。TaskType是启动过程的时间长短的关键因 素。在这背后的原因是不同任务类型要么同步要么异步。很显然同步作业完成需要更长的时间来执行,因此注意你的安装的时间长度,因为启动任务的执行不应超过 5分钟。这里是三种不同类型的启动任务: Simple(默认):(同步)任务启动并且实例被阻塞,直到任务完成。(注意:如果任务失败,实例被阻塞并且启动失败)
Background:(异步)启动任务进程并且继续角色启动。(注意:触发并遗忘。为了调试请一定要记录运行过程)
Foreground:(异步)任务被执行但是在foreground任务退出之前不允许角色关闭。
IISConfigurator.exe IISConfigurator进程是一个可执行文件,在计算模拟器和云里的Windows Azure环境里都能找到。IISConfigurator.exe负责通过站点节点迭代增加和配置必要的站点(虚拟目录和应用程序)、端口和IIS里的 主机头。我以前写了一个帖子讨论计算模拟器里的IISConfigurator.exe 。
[Web/Worker]Role.cs : RoleEntryPoint 在Web或Worker Role里你会发现一个继承自RoleEntryPoint的类。RoleEntryPoint公开3个事件OnStart、 Run和 OnStop,这些方法用于执行角色的整个生命周期的任务。稍后我在这个帖子里更详细地解释了这些事件。 让我们看一看在部署我们的托管服务时Windows Azure经历的过程。
当你向Windows Azure上传你的云服务包和云服务配置时整个过程就开始了。(为了配置你的应用程序,上传你的部署到Blob存储是一个好的做法。这使得你能够保持你的部署版本并手上保留有备份以防托管服务需要回滚到先前的版本。)
接下来就像云服务定义中描述的那样Fabric Controller着手工作来为你应用程序检索必要硬件。一旦Fabric Controller找到了必要硬件就为你的托管服务分配必要的资源,适当的Guest OS Image被部署到服务器并初始化Guest OS Boot过程。
从这里事情变得有趣起来。
如果当前角色包含云服务定义的一个开始节点,这个角色以你的云服务定义中安排好的顺序开始执行每个任务。取决于TaskType(上面解释了),这些启动任务同步(simple)或异步(background, foreground)运行。
当"Simple"(同步)启动任务执行完成,这个角色开始它的启动生命周期的下一个阶段。在生命周期的这个阶段IISConfigurator进程被异步执行,同时(或者不久以后)OnStart事件被激发。
一旦OnStart事件完成,角色应该是在准备 状态并开始接收来自Load Balancer的请求。在这时候Run事件被激活。即使Run事件不在WebRole.cs代码模板里。你可以重写这个事件并提供一些事件来执行。 Run事件常用于worker role,如果没有工作要做,它被实现为一个周期性地调用Thread.Sleep的无限循环。
经一段长时间的服务请求,这时候很可能出现角色被回收或者不再被需要并且关闭。这将激活OnStop事件来处理一些必须的角色清理,例如将Diagnostics数据或永久性文件从交换区转移到Blob存储。注意到OnStop方法没有时间限制,因此明智的做法是当你的角色仍然正常并且没有试图关闭时周期性地转移重要的数据。
在OnStop事件退出之后(要么代码执行完成要么超时),Role开始停止进程并终止Job对象 。一旦Job对象被终止,角色重启并再一次遵照上述的启动生命周期执行。知道这一点很重要因为你的启动任务可能在相同的Role上被多次执行,为此你的启动任务需要是幂等的 ,这非常重要。 作为软件开发人员我们都知道所谓的"Happy Path",这一术语用来描述一个过程的一切都是按计划发展的。然而,在现实世界中,没有过程可以保证这一点,我们需要知道有可能出错的情况。
这里快速列出了在启动生命周期期间的潜在问题: 启动任务可能执行失败
启动任务可能永远没法完成
IISConfigurator.exe可能覆盖启动任务对IIS的修改
IISConfigurator.exe和OnStart可能存在竞争
启动任务和OnStart可能存在竞争
启动过程可能不是幂等的
这里有很多方法可以帮助你在启动过程中避免竞争状态。典型的做法是对资源(被启动过程中的特定的项目所影响的)进行制衡。另外可以做的是新建一个VM角色 。
VM角色是VHD上的一个Windows Server 2008 R2 Image,在VHD上配置所有的需要安装在你的角色上的组件。你还需要安装Windows Azure集成组件并用sysprep进行泛化。
在以下条件下VM角色是一个好的方法: 你的启动任务影响你的部署时间
应用程序安装是容易出错的
应用程序安装需要手工交互
我将在其它博客文章里介绍更多关于VM角色,因为它本身就是一个足够大的话题。
一旦你配置了你的VM角色实例,它通过使用csupload命令行工具或使用Visual Studio里的Cloud Tools上传到云。这个新建的VM Role image现在被预分配代替一个Microsoft's Guest OS Images。因为映