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 件のコメント:
コメントを投稿