こんばんは、statemachineです。書きかけの記事を吹き飛ばしてしまい、二回目の執筆ですがいかがお過ごしでしょうか。
前回は、Windows Azure におけるPluginの仕組みについて紹介しましたが、今回は実際Pluginを作成してみたいと思います。
海外では既に、Memcached pluginを作成されている方もいらっしゃるようですが、こちらは特に参考にしたりしていません。食い違っていることを言っていたらごめんなさい。例によって本記事の内容は、無担保、無保証でありPluginの作成方法も正式に公開されている訳ではないので、注意してください。
おさらい
前回のおさらいとして、Pluginの特徴をまとめると以下。特にPluginだからといって特殊な機能を備えているわけではなく、あくまでSDK 1.3で提供されている範囲内だと思われます。
- 格納場所は、C:\Program Files\Windows Azure SDK\v1.3\bin\plugins
- サービス定義、構成ファイル風のスキーマを持っている。
- StartupTask/ConfigurationSettings/InputEndpointなどを定義できる。
Agentの作成
Pluginとして起動するAgent的な何かを作成します。Connect/RemoteDesktop/Diagnosticsなど、どれもAgent的なものなのでそれに倣ってみます。また以下の機能を持たせることで、Pluginの機能を検証します。
- StartupTaskでAgent的な何かを常駐。
- ConfigurationSettingsで値を利用
- InputEndpointを定義し通信
ということで作成したのが以下のプログラム。
- TcpListenerで常駐し、InputEndpointを利用。
- クライアントからの接続で、構成ファイルに定義された値をランダムに返却
プログラム自体は、.NET 3.5 Console Applicationです。Microsoft.WindowsAzure.xxxなDLLの参設照定を追加を忘れずに。.NET 4だとデフォでClient Profileになるとか混合アセンブリが云々と言われるので。
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Text; using System.Net.Sockets; using System.Web; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.ServiceRuntime; namespace HogeAgent { class Program { static void Main(string[] args) { new HogeAgent().Start(); } } public class HogeAgent { private readonly TcpListener _listener; readonly string[] _response; private readonly Random _rnd = new Random(); public HogeAgent() { IPEndPoint ip; if (RoleEnvironment.IsAvailable) { ip = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["statemachine.HogeInput"].IPEndpoint; // サービス構成ファイルは日本語化けるっぽいのでUrlEncode済 _response = RoleEnvironment.GetConfigurationSettingValue("statemachine.ResponseStrings"). Split(',').Select(HttpUtility.UrlDecode).ToArray(); } else { // test route ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4989); _response = new string[] { "あほ", "ばか", "とろ" }; } _listener = new TcpListener(ip); } public void Start() { _listener.Start(); while (true) { TcpClient client = _listener.AcceptTcpClient(); var message = _response[_rnd.Next(_response.Length)]; // byte[] data = Encoding.GetEncoding(932).GetBytes(message + "\n"); byte[] data = Encoding.UTF8.GetBytes(message + "\n"); NetworkStream stream = client.GetStream(); stream.Write(data, 0, data.Length); stream.Close(); client.Close(); } } } }
Pluginの作成
Agentが完成したら、Pluginを作成します。作成手順としては以下。
- Pluginフォルダを作成。C:\Program Files\Windows Azure SDK\v1.3\bin\plugins\Hogeなど。
- Plugin定義ファイル Hoge.cspluginを作成。
- Agent的な実行ファイルを配置
作成したHoge.cspluginが以下。Azureの定義ファイルをご存じの方なら説明不要かと思います。
- RoleModuleのnamespace属性に、Pluginの名前空間を定義。Pluginで定義された情報へのアクセスは、この名前空間を付加する。
- StartupTaskでHogeAgentを起動。特に管理者権限は必要ないので、権限はlimited。常駐して制御を返さないので、taskTaypeはbackgroundで。
- ConfigurationSettings/InputEndpointは普通に定義。
- ignoreRoleInstanceStatusは、RemoteForwarderについていたので,特にそのまま。
<?xml version="1.0" ?> <RoleModule xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" namespace="statemachine"> <Startup> <Task commandLine="HogeAgent.exe" executionContext="limited" taskType="background" /> </Startup> <ConfigurationSettings> <Setting name="ResponseStrings" /> </ConfigurationSettings> <Endpoints> <InputEndpoint name="HogeInput" protocol="tcp" port="4989" localPort="4989" ignoreRoleInstanceStatus="true" /> </Endpoints> </RoleModule>
Pluginの組み込み
通常のWebRoleプロジェクトを作成し、サービス定義ファイルにImport文を追加します。
すると、サービス定義ファイルに、statemachine.ResponseSettingsが自動で追加されるのでレスポンスデータを定義します。日本語が化けるっぽいのですが、原因は追及せずUrlEncodeでごまかします。
実行
WebRoleをAzure上にデプロイします。Agent的な何かは、4989ポートでリクエスト待ちとなっているので、telnet等で4989ポートをつんつんしてみます。すると、以下のようなレスポンスデータがランダムに返ってくることになります。
まとめ
- Pluginの作成自体は得に難しいものではないが、お作法が合っているのか不明。
- サービス的なものにしたほうが良いのか? 起動、終了のシーケンスなどきちんとやらきゃいけないとか。
- SDKのインストールフォルダに配置しなければいけないのか? 配布が面倒かもとか。
といらえず、実現可能性は分かったので、このあたりでサヨナラ、サヨナラ、サヨナラ。