您是否曾经尝试过在Windows Azure模拟器中运行带有完整IIS和多个角色实例的托管服务?几天前,我注意到一个网络角色的多个实例中只有一个在IIS中是开始的。以下屏幕截图说明了屏幕截图前面的行为和消息框,显示了此行为的原因。消息框出现在尝试启动IIS经理中的一个停止网站时出现。
屏幕截图:IIS带有停止网站
示例云应用程序包含两个Web角色:MVCWebrole1和WCFServiceWebrole1每个配置为使用三个实例。我的第一个想法是:"当然!在真正的Azure世界中不会发生港口碰撞,因为每个角色实例都是自己的虚拟机。它在模拟器中无法使用!"但是,经过一些研究并分析了Azure计算模拟器的许多部分,我发现计算模拟器为每个角色实例创建了一个独特的IP(在我的示例中,从127.255.0.0到127.255.0.5)。这篇MSDN博客文章(http://blogs.msdn.com/b/avkashchauhan/archive/2011/09/16/whats-new-inew-inew-inwindows-azure-sdk-1-5-5--5--------------instance-instance-in-instance-in-yan-Microsoft员工Avkkash Chauhan的role-gets-its-its-ins-ind-ip-ind-ind-ind-ip-ind-ind-ind-ip-indress-to-ind-to-to-ind-compute-compute-close-close-the-cloud-environment.aspx)也描述了这种行为。结论之后,我提出了以下问题:为什么要计算模拟器(更准确地说是devfc.exe)的地狱不会将适当角色的IP添加到每个网站的绑定信息中? <?/p>
我用手和tadaaaaa将IP添加到每个网站:每个网站都可以启动而无需任何碰撞。下一个屏幕截图以突出显示的绑定信息进行了演示。
屏幕截图:IIS带有启动网站
再次:为什么模拟器不为我做到这一点?我写了一种小的静态辅助方法,以在每个角色开始时为我做绑定的扩展。也许有人想使用它:
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();
}
}
我得到了它!
我在三台不同的机器上都有这种行为,这些机器均已格式化,并与新鲜干净的Windows 8,Visual Studio 2012和Azure SDK 1.8和Azure Tools Anstallations一起使用。因此,重新安装了Azure SDK和工具(正如Anton所建议的那样)不应改变任何内容。但是我三台机器的清洁度是关键点!安东(Anton),您的机器上是否有Visual Studio 2010,至少安装了VS2010 SP 1?我用ILSPY分析了IISConfigurator.exe
,并找到了将网站绑定信息设置为'*'
(而不是127.255.0.*
)的代码。这取决于静态属性Microsoft.WindowsAzure.Common.Workarounds.BindToAllIpsWorkaroundEnabled
。此方法内部使用Microsoft.WindowsAzure.Common.Workarounds.TryGetVS2010SPVersion
并导致将IP绑定到'*'
,如果Visual Studio 2010的SP级别小于1。TryGetVS2010SPVersion
检查四个注册表键,我不知道为什么,但是我的注册表和注册表中存在其中一个键Visual Studio 2010 SP 0级别(我从未在三台机器中没有安装VS2010 !!!)。当我将HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftDevDivvsServicing10.0SP
的值从0更改为10(更大的0应该这样做)时,Azure Emulator开始将角色的127.255.0.*
IPS设置为IIS中所有网站上的绑定信息,并且所有网站都正确启动。