在我们公司内部,我们有一个相当大的服务应用程序作为azure cloudservice运行。该服务包含webrole和workerrole。 webrole包含一个MVC应用程序,而workerrole正在后台运行。 workerrole用于处理几个大型进程和一堆24/7的小进程,每5分钟检查一次。
我为这个应用程序创建了一个azure网站,并编写了一个小包装器类,用于检查是否需要从web.config文件或云配置文件(.cscfg文件)中获取配置值。我添加了适当的转换来转换一些额外的设置并将应用程序发布到azure网站。
到目前为止,一切都运作良好,但我已经预料到的确实已经发生了......工人不再工作并且正在抛出错误。我见过的第一个错误是;
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.
所以当然我采取了快速解决方案并且去了'属性>复制local'并将其设置为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(显然)。 这给了我一些选择;
来自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的云服务中。由于开发过程,我们正在运行单独的测试,接受和生产环境。由于这是一个沉重的过程,我们在天蓝色的机器上运行相当昂贵的机器,但这通常只需要工人。 webpart很轻巧。因此,主要是尝试降低成本的想法。因此,我们的想法是将webrole转换为azure网站(这部分工作只需要进行一些小修改即可从web.config而不是cloudconfiguration中读取信息)。但是工人目前还没有工作,因为我们还没有改变任何东西。我的一位同事基本上说“为configpart编写一个包装器,将azurewebsite发布到一个或多个testenvironments并将它们指向同一个workerrole”。但我怀疑这是否有可能..
有没有其他人遇到过这种情况并为此找到了解决方案?非常感谢任何寻求解决方案的帮助!
答案 0 :(得分:4)
找到解决方案,以便将azure网站连接到workerrole 仍然在cloudservice中运行。如果这工作,我可以放弃 webrole,我可以将多个实例连接到一个workerrole。
我猜你正在使用某种队列机制(Azure存储队列或服务总线队列)来促进Web和辅助角色之间的通信。如果是这种情况,那么你可以继续使用相同的。您的网站将推送队列中的消息,您的辅助角色将轮询此队列并获取消息并对其进行处理。
找到将workerrole转换为某种东西的解决方案(不知道是什么 这可能是由天蓝色网站支持的。
请查看Azure Webjobs
。在Web Apps世界中,它们与Worker Roles相对应。
<强>更新强>
根据评论,我认为您应该能够将代码移植到Web作业中。有两种方法可以做到:
Continuous Web Job
,那么您必须在代码本身中放置这10秒的睡眠逻辑。工作将持续运行,但每10秒钟才会唤醒。与您当前的工作者角色实施类似。Scheduled Web Job
,您可以从代码中取出这10秒睡眠逻辑,并计划每隔10秒运行一次。我建议你沿着这条路走下去,因为你已经从你的应用程序中解耦了你的调度逻辑(10秒睡眠)。所以明天如果你要增加睡眠时间,你只需更改门户中的时间表而无需重新部署代码。答案 1 :(得分:3)
正如Gaurav指出的那样,App Service空间中的工作人员角色相当于Azure WebJobs。
关于这个问题:
到目前为止,一切都运作良好,但我已经预料到的确实已经发生了......工人不再工作并且正在抛出错误。我见过的第一个错误是;
无法加载文件或程序集“Microsoft.WindowsAzure.ServiceRuntime,Version = 2.5.0.0,Culture = neutral,PublicKeyToken = 31bf3856ad364e35”或其中一个依赖项。系统找不到指定的文件。
所以当然我采取了快速解决方案并且去了'属性&gt;复制local'并将其设置为true。将此发布到azure网站后,我收到以下错误;
无法加载文件或程序集'msshrtmi,Version = 2.5.0.0,Culture = neutral,PublicKeyToken = 31bf3856ad364e35'或其依赖项之一。系统找不到指定的文件。
Microsoft.WindowsAzure.ServiceRuntime
特定于云服务,不适用于Web应用程序(这就是您在网络应用中遇到msshrtmi
错误的原因)。如果您仍在运行辅助角色,则该文件位于实例GAC中,并且也应位于本地计算机中。也就是说,Microsoft.WindowsAzure.ServiceRuntime
可以在辅助角色项目中引用,但不能在Web应用程序项目中引用。
我猜你正在使用ServiceRuntime来获取一些配置设置值:
var value = RoleEnvironment.GetConfigurationSettingValue(settingName);
您可以将其更改为:
var value = CloudConfigurationManager.GetSetting(settingName);
因为此方法从适当的配置存储(from MSDN)读取配置设置值。
答案 2 :(得分:0)
这里的最佳解决方案是将工作者角色转换为WebJob,如上所述@Graurav。
如果要将Web App连接到Worker Role,则可以使用Azure Queue或其他中间存储,其中可以从WebApp中删除操作并由Worker Role选择。