在我们公司内部,我们有一个相当大的服务应用程序作为azure cloudservice运行 . 该服务包含webrole和workerrole . webrole包含一个MVC应用程序,而workerrole正在后台运行 . workerrole用于处理几个大型进程和一堆24/7的小进程,每5分钟检查一次 .
我为这个应用程序创建了一个azure网站,并编写了一个小包装器类,用于检查是否需要从web.config文件或 Cloud 配置文件(.cscfg文件)中获取配置值 . 我添加了适当的转换来转换一些额外的设置并将应用程序发布到azure网站 .
到目前为止一切都很好,但我已经预料到的确实已经发生了...... Worker 不再工作并且正在抛出错误 . 我见过的第一个错误是;
Could not load file or assembly 'Microsoft.WindowsAzure.ServiceRuntime, Version=2.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
所以当然我采取了快速解决方案并且去了'属性>复制本地'并将其设置为true . 将此发布到azure网站后,我收到以下错误;
Could not load file or assembly 'msshrtmi, Version=2.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
我可以找出这个错误来自哪里,但感觉这是另外一堆错误中的第二个 . 在几个网站上我读过,azure网站不支持workerroles(显然) . 这给了我一些选择;
-
找到解决方案,这样我就可以将azure网站连接到仍然在cloudservice中运行的workerrole . 如果这有效,我可以删除webrole,我可以将多个实例连接到一个workerrole .
-
找到一个解决方案,将workrole转换成azure网站支持的东西(不知道这可能是什么) .
-
忘掉整个想法,坚持使用web和workerrole进行cloudservice设置 .
Fragment from workerrole.cs
Facade进行数据库调用以检查任何新添加的进程 .
public override void Run()
{
// Only process if the web.config says we're allowed to do so.
while (true)
{
var process = Convert.ToBoolean(WebConfigurationManager.GetSetting("Process"));
try
{
if (process )
{
var username = WebConfigurationManager.GetSetting("UsernameWorkerRole");
if (string.IsNullOrEmpty(username))
{
var version = Assembly.Load("Ecare.Productie.WorkerRole").GetName().Version;
var versionString = String.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build.ToString("000"), version.Revision.ToString("00000"));
username = ApplicatieConstanten.WorkerRoleName + " " + versionString;
}
IServiceFacade serviceFacade = new ServiceFacade(username);
serviceFacade.Start();
}
}
catch (Exception ex)
{
AuditingLoggingHelper.GetLoggerInstance(ApplicatieConstanten.WorkerRoleName).Error("Exception while starting service", ex);
}
Thread.Sleep(10000);
}
// ReSharper disable once FunctionNeverReturns
}
我们这样做的主要原因是因为我们的VS解决方案具有MVC应用程序(Web角色)和workerrole . 我们目前正在将此发布到azure的 Cloud 服务中 . 由于开发过程,我们正在运行单独的测试,接受和 生产环境 环境 . 由于这是一个沉重的过程,我们在天蓝色的机器上运行相当昂贵的机器,但这通常只需要 Worker . webpart很轻巧 . 因此,主要是尝试降低成本的想法 . 因此,我们的想法是将webrole转换为azure网站(这部分工作只需要进行一些小修改即可从web.config而不是cloudconfiguration中读取信息) . 但是 Worker 目前还没有工作,因为我们还没有改变任何东西 . 我的一位同事基本上说“为configpart编写一个包装器,将azurewebsite发布到一个或多个testenvironments并将它们指向同一个workerrole” . 但我怀疑这是否有可能..
有没有其他人遇到过这种情况并为此找到了解决方案?非常感谢任何寻求解决方案的帮助!
3 回答
我猜你正在使用某种队列机制(Azure存储队列或服务总线队列)来促进Web和工作者角色之间的通信 . 如果是这种情况,那么你可以继续使用相同的 . 您的网站将推送队列中的消息,您的工作人员角色将轮询此队列并获取消息并对其进行处理 .
请看一下Azure Webjobs . 在Web Apps世界中,它们与Worker Roles相对应 .
UPDATE
基于这些评论,我认为您应该能够将代码移植到Web作业中 . 有两种方法可以做到:
如果您创建
Continuous Web Job
,那么您必须在代码本身中放置这10秒的睡眠逻辑 . 这项工作将持续运行,但每10秒钟才会被唤醒 . 与您当前的Worker Role实现类似 .您可以通过将Web作业设置为
Scheduled Web Job
来从代码中取出这10秒睡眠逻辑,您可以计划每隔10秒运行一次 . 因为你已经解决了你的调度逻辑(10秒睡眠),我建议你沿着这条路走下去从你的申请 . 所以明天如果你要增加睡眠时间,你只需更改门户中的时间表而无需重新部署代码 .正如Gaurav指出的那样,App Service空间中的工作者角色相当于Azure WebJobs .
关于这个问题:
Microsoft.WindowsAzure.ServiceRuntime
特定于 Cloud 服务,不适用于Web应用程序(这就是您在Web应用程序中出现msshrtmi
错误的原因) . 如果您仍在运行辅助角色,则该文件位于实例GAC中,并且也应位于本地计算机中 . 也就是说,Microsoft.WindowsAzure.ServiceRuntime
可以在worker角色项目中引用,但不能在Web应用程序项目中引用 .我猜你正在使用ServiceRuntime来获取一些配置设置值:
您可以将其更改为:
因为此方法从相应的配置存储(from MSDN)中读取配置设置值 .
这里的 best 解决方案是将Worker Role转换为WebJob,如上面提到的@Graurav .
如果要将Web App连接到Worker Role,则可以使用Azure Queue或其他中间存储,其中操作可以从WebApp中删除并由Worker Role获取 .