您是否曾尝试在具有完整 IIS 和多个角色实例的 Windows azure 模拟器中运行托管服务?几天前,我注意到在 IIS 中一次只有一个 web 角色的多个实例是 startet。以下屏幕截图说明了该行为,屏幕截图前面的消息框显示了此行为的原因。尝试在 IIS 管理器中启动已停止的网站之一时会出现该消息框。
示例云应用程序包含两个 Web 角色:MvcWebRole1 和 WCFServiceWebRole1,每个角色都配置为使用三个实例。我的第一个想法是:“当然!在真实的天蓝色世界中不会发生端口冲突,因为每个角色实例都是一个自己的虚拟机。它不能在模拟器中工作!” 但是经过一些研究和分析 azure 计算模拟器的许多部分后,我发现计算模拟器为每个角色实例创建了一个唯一的 IP(在我的示例中,从 127.255.0.0 到 127.255.0.5)。这篇 MSDN 博客文章 (http://blogs.msdn.com/b/avkashchauhan/archive/2011/09/16/whats-new-in-windows-azure-sdk-1-5-each-instance-in-any微软员工 Avkash Chauhan 的 -role-gets-its-own-ip-address-to-match-compute-emulator-close-the-cloud-environment.aspx) 也描述了这种行为。为什么计算模拟器(更确切地说是DevFC.exe)没有将相应角色的IP添加到每个网站的绑定信息中???
我手动为每个网站添加了 IP,tadaaaaa:每个网站都可以在没有任何冲突的情况下启动。下一个屏幕截图演示了它,并突出显示了更改的绑定信息。
再一次:为什么模拟器不为我做呢?我写了一个小的静态辅助方法来在每个角色开始时为我做绑定扩展。也许有人想使用它:
public static class Emulator
{
public static void RepairBinding(string siteNameFromServiceModel, string endpointName)
{
// Use a mutex to mutually exclude the manipulation of the iis configuration.
// Otherwise server.CommitChanges() will throw an exeption!
using (var mutex = new System.Threading.Mutex(false, "AzureTools.Emulator.RepairBinding"))
{
mutex.WaitOne();
using (var server = new Microsoft.Web.Administration.ServerManager())
{
var siteName = string.Format("{0}_{1}", Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CurrentRoleInstance.Id, siteNameFromServiceModel);
var site = server.Sites[siteName];
// Add the IP of the role to the binding information of the website
foreach (Binding binding in site.Bindings)
{
//"*:82:"
if (binding.BindingInformation[0] == '*')
{
var instanceEndpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[endpointName];
string bindingInformation = instanceEndpoint.IPEndpoint.Address.ToString() + binding.BindingInformation.Substring(1);
binding.BindingInformation = bindingInformation;
server.CommitChanges();
}
else
{
throw new InvalidOperationException();
}
}
}
// Start all websites of the role if all bindings of all websites of the role are prepared.
using (var server = new Microsoft.Web.Administration.ServerManager())
{
var sitesOfRole = server.Sites.Where(site => site.Name.Contains(RoleEnvironment.CurrentRoleInstance.Role.Name));
if (sitesOfRole.All(site => site.Bindings.All(binding => binding.BindingInformation[0] != '*')))
{
foreach (Site site in sitesOfRole)
{
if (site.State == ObjectState.Stopped)
{
site.Start();
}
}
}
}
mutex.ReleaseMutex();
}
}
}
我调用辅助方法如下
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
if (RoleEnvironment.IsEmulated)
{
AzureTools.Emulator.RepairBinding("Web", "ServiceEndpoint");
}
return base.OnStart();
}
}