Windows Azure上でインスタンス間通信する場合、相手のIPアドレスがわからないと何もできません。通常IPアドレスはインスタンス起動時に適当に振られるので、RoleEnvironmentを使ってインスタンスのIPEndpointを取得するのですが、どうもInputEndpointから取れなくなったっぽい。
※インスタンスを列挙してそのインスタンスのIPEndpointを取得してIPアドレスをゲットする、という方法ですが他のインスタンスのInputEndpointが取れない。
ぽい、というのは昔とれた気がするんですけど、SDK1.8だと取れないんですよね。いつからか不明だけどVPNが来たりしたSpring Waveのときかなぁ?
というわけでSDK1.8時代のロール間通信はInternalEndpointを明示的に指定して、そいつのIPEndpointを参照しましょう、という感じになります。
取得するコード的にはこんな感じです。
var role = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CurrentRoleInstance.Role;
foreach (var instance in role.Instances)
{
foreach (var s in instance.InstanceEndpoints.Values)
{
if (s != null)
{
Console.WriteLine("{0} = {1}:{2}", s.RoleInstance.Id, s.IPEndpoint.Address.ToString(),
s.IPEndpoint.Port);
}
}
}
サービス定義ファイル(CSDEF)はこんな感じ。
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WindowsAzure18_45" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-10.1.8">
<WebRole name="MvcWebRole1" vmsize="ExtraSmall">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
<Binding name="Endpoint2" endpointName="Endpoint2" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
<InternalEndpoint name="Endpoint2" protocol="http" port="8002" />
</Endpoints>
<Imports>
<Import moduleName="RemoteAccess" />
<Import moduleName="RemoteForwarder" />
</Imports>
<Runtime executionContext="elevated">
</Runtime>
</WebRole>
</ServiceDefinition>
テストなので適当にInputEndpointとInternalEndpointを定義してみました。
で、結果はこう。

インスタンス0上で実行しました。他のインスタンスのInputEndpointは取れてないですね。でもInternalEndponitは取れてます。
ということで、何かインスタンス間通信したい場合はInternalEndpointをちゃんと定義しましょう、ということで。
ちなみにコンソールアプリとかで
Unhandled Exception: System.TypeInitializationException: The type initializer fo
r ‘Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment’ threw an exception. —
-> System.IO.FileLoadException: Could not load file or assembly ‘msshrtmi.dll’ o
r one of its dependencies. A dynamic link library (DLL) initialization routine f
ailed. (Exception from HRESULT: 0x8007045A)
at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.InitializeEnvironmen
t()
at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment..cctor()
— End of inner exception stack trace —
at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.get_CurrentRoleInsta
nce()
とか出る場合は以下のようにuseLegacyV2RuntimeActivationPolicyをTrueにすればいいですよ。(結構悩んだ)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
まぁByDesignという感じみたいです。はい。(外部からの受付用のInputEndpointで内部用のIPアドレスが取れちゃうってのも変な話といえば変ですのでいいんですけどね。)