Windows Azureのインスタンス間通信にzeromq(http://www.zeromq.org/)をWindows Azure上で使う機会があったので、使うまでの手順とか注意点を記す。またWindows Azureプロジェクトからzeromqを利用するために、clrzmq2(http://www.zeromq.org/bindings:clr)というzeromqのC#バインディングを用いる。
全体的な流れは以下の通り。
- zeromqを64bit Windows向けにビルドする
- clrzmq2を64bit Windows向けにビルドする
- Azureプロジェクトを用意する
zeromqのビルド
まず最初にzeromqを64bit Windows向けにビルドするため、以下のURLから最新のソースコードを持ってくる(この時点ではバージョン2.1.4が最新)。
http://www.zeromq.org/intro:get-the-software
そしてDLしたファイルを解凍し、できたディレクトリ内の zeromq-2.1.4\builds\msvc\msvc.sln をVisual Studioで開く(Visual Studio 2010の場合、プロジェクトの自動変換が必要)。プロジェクトを開いたら、ビルド構成を以下のように設定する。
- アクティブソリューション構成:Release
- アクティブソリューションプラットフォーム:x64
そして、以下のスクリーンショットのようになったことを確認する。
確認ができたら、libzmqプロジェクトをビルド。
すると、64bit Windows向けzeromqのDLLが zeromq-2.1.4\lib\libzmq.dll にできる。
clrzmq2のビルド
次にclrzmq2のビルドを行うため、以下のURLから最新(この時点ではzeromq-clrzmq2-f420936.zipが最新)のソースコードをダウンロード・解凍し、Visual Studioで開く。
https://github.com/zeromq/clrzmq2
そして、zeromqの時と同様にビルド構成の設定を行う。
- アクティブソリューション構成:WIN_RELEASE
- アクティブソリューションプラットフォーム:x64
以下のようになったことを確認する。
確認できたら、clrzmqプロジェクトをビルド。すると zeromq-clrzmq2-f420936\clrzmq\bin\Release 内にclrzmq.dllができる。
Azureプロジェクトを作成
次にいままでの手順でビルドしたlibzmq.dllおよびclrzmq.dllを用いて、Azure上でZeroMQを立ち上げるためのプロジェクトを作成する。まず普通にVisual StudioからWindows Azureプロジェクトを作成。とりあえずWorkerRoleをひとつ(WorkerRole1)作っておく。
次に、ZeroMQがリスニングするエンドポイントの設定を行う
- Name:ZeroMQ(適当でOK)
- Type:Input(Azure内部の通信のみで使うのならInternalにする)
- Protocol:tcp(zeromqはhttp/httpsには対応していない)
- Public Port:51349(適当に空いてそうな番号を選ぶ、49152~65535で選ぶのが望ましい)
次にビルドしたclrzmq.dllへの参照を追加し、プロパティから、[ローカルコピー] および [特定バージョン] を [True] にする。
そしてビルドしたlibzmq.dllをWorkerRole1プロジェクト内にコピーする。同時にlibzmq.dllが依存するDLL(msvcp100.dllおよびmsvcr100.dll)もコピーしておく(64bit版Windows 7の場合、C:\Windows\system32にある)。
msvcp100.dllおよびmsvcr100.dllをコピーする際はVisual Studio上に直接ペーストすると32bit DLLがペーストされる問題に注意。詳細はこちらの記事を参照。
そして追加した3つのDLLのプロパティにおいて、以下のように設定する。
構成マネージャーからWorkerRole1プロジェクトのプラットフォームをx64に変更する(clrzmq.dllを直接使っているプロジェクトは全てx64にする必要がある)。
最後に、WorkerRole.csを以下のように書き換える。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using ZMQ;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.Diagnostics.Management;
namespace WorkerRole1 {
public class WorkerRole : RoleEntryPoint {
public override void Run() {
try {
var endpoints = new List<string> {
"ZeroMQ"
};
var sockets = endpoints.Select((endpoint) => {
var ep = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[endpoint].IPEndpoint;
var address = String.Format("tcp://*:{0}", ep.Port);
Trace.TraceInformation("{0} listening on '{1}'", endpoint, address);
var socket = new Socket(SocketType.PULL);
socket.Bind(address);
socket.PollInHandler += (a, b) => {
Trace.TraceInformation(a.Recv(Encoding.UTF8));
};
return socket;
}).ToList();
while (true) {
Context.Poller(sockets);
}
} catch (System.Exception e) {
Trace.TraceError("{0}", e);
}
}
public override bool OnStart() {
ServicePointManager.DefaultConnectionLimit = 12;
var wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
var account = CloudStorageAccount.Parse(
RoleEnvironment.GetConfigurationSettingValue(wadConnectionString));
var roleInstanceDiagnosticManager = account.CreateRoleInstanceDiagnosticManager(
RoleEnvironment.DeploymentId, RoleEnvironment.CurrentRoleInstance.Role.Name,
RoleEnvironment.CurrentRoleInstance.Id);
var config = roleInstanceDiagnosticManager.GetCurrentConfiguration();
if ( null == config ) {
config = DiagnosticMonitor.GetDefaultInitialConfiguration();
}
config.Logs.ScheduledTransferPeriod = TimeSpan.FromSeconds(10);
config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Undefined;
roleInstanceDiagnosticManager.SetCurrentConfiguration(config);
return base.OnStart();
}
}
}
そして、出来上がったプロジェクトをAzure向けに発行しデプロイすれば終了。あとは、以下のようなプログラムを作って動作確認する。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZMQ;
namespace zeromq {
class Program {
static void Main(string[] args) {
byte[] buf = new byte[1024];
System.Security.Cryptography.RNGCryptoServiceProvider rng =
new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(buf);
var context = new Context(1);
var socket = context.Socket(SocketType.PUSH);
socket.Connect("tcp://<<url>>:51349");
while (true) {
var msg = Convert.ToBase64String(buf);
socket.Send(msg, Encoding.UTF8);
Console.ReadLine();
}
}
}
}まとめ
ZeroMQ on Windows Azureを実現するためのポイントは以下の通り。
- libzmq.dll および clrzmq.dll(clrzmq2) をx64向けにビルドする
- clrzmq.dll の[特定バージョン]をTrueにする
- x64向けの msvcp100.dll および msvcr100.dll を追加しておく(64bit版Windows 7などからコピる)
で、あとは通常のWindows上で使うのと一緒。
0 件のコメント:
コメントを投稿