完全な IIS と複数のロール インスタンスを使用して、Windows azure エミュレーターでホステッド サービスを実行しようとしたことがありますか? 数日前、Web ロールの複数のインスタンスのうち、一度に 1 つのみが IIS で開始されることに気付きました。次のスクリーンショットは動作を示しており、スクリーンショットの前のメッセージ ボックスはこの動作の理由を示しています。IIS マネージャーで停止した Web サイトの 1 つを開始しようとすると、メッセージ ボックスが表示されます。
サンプル クラウド アプリケーションには、MvcWebRole1 と WCFServiceWebRole1 の 2 つの Web ロールが含まれており、それぞれが 3 つのインスタンスを使用するように構成されています。私が最初に考えたのは、「確かに!実際の Azure の世界では、すべてのロール インスタンスが独自の仮想マシンであるため、ポートの競合は発生しません。エミュレーターでは機能しません!」というものでした。しかし、いくつかの調査と 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 -role-gets-its-own-ip-address-to-match-compute-emulator-close-the-cloud-environment.aspx) は、Microsoft 従業員の Avkash Chauhan もこの動作について説明しています。なぜ計算エミュレーター (より正確には DevFC.exe) は、適切な役割の IP を各 Web サイトのバインディング情報に追加しないのですか?
私は手動で各 Web サイトに IP を追加しました。次のスクリーンショットは、変更されたバインディング情報が強調表示されていることを示しています。
繰り返しますが、なぜエミュレーターは私のためにそれをしないのですか? 私は小さな静的ヘルパー メソッドを作成して、ロールの開始ごとにバインド拡張機能を実行しました。多分誰かがそれを使いたい:
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();
}
}