Apache Storm DRPCのHTTP APIを使う
Apache Stormのdefaults.yamlに drpc.http*
の項目があることから分かるように、Storm 0.10.0のDRPCサーバはDRPCクライアントから利用されるほかに、HTTP APIを持っている(0.9.6にはない)。つまり、HTTPクライアント(PerlのHTTPクライアントライブラリでもcurlでもWebブラウザでも)を用いて、DRPCサーバに処理リクエストを投げ、トポロジの処理結果をレスポンスとして受け取ることができる。
何が嬉しいか
HTTPリクエストに対する処理がスケールアウトしやすい
StormのDRPCは、Distributed Remote Procedure Callの略だが、Stormのトポロジの入力を外部から受け付け、トポロジを通して得られた処理結果を外部に返すためのものである。Stormのトポロジは、入力データを流す始点となるSpoutと、データを処理するBoltに分けられるが、DRPCアプリケーションの場合、Spoutは外部からの入力データを受け付け次のBoltに流し、Boltはデータに処理を行いその結果を次のBoltに渡し、最後のBoltが最終的な処理結果のデータを外部に返す。
Stormのトポロジを構成するSpout、Boltはスケールアウトできるように設計されているので、処理が重い部分・並列分散処理させたい部分の並列数を増やす指定をすることで、実行するスレッド(あるいはプロセス、マシン)を増やしたり、逆に処理を分散させたくない部分の並列数を1にしたりもできる。また、クラスタを構成するマシンの台数を増やすことで、アプリケーション内の並列分散処理の性能を高めることができる。マシンを増やした際の作業は、Stormの仕組みのおかげで、非常に簡単で、アプリケーションに変更は必要ない。
DRPCのHTTP APIを用いることで、このStormの並列分散処理の仕組みをそのまま、HTTPリクエストに対する処理に適用することができる。
このメリットのイメージ図を551の肉まん風に書いてみた。
DRPCのHTTP API仕様
DRPCサーバのHTTP APIはstorm-core/src/clj/org/apache/storm/daemon/drpc.cljを見ると、
- GET: http://DRPCサーバ名:DPRCのHTTPポート番号/drpc/関数名[/引数]
- POST: http://DRPCサーバ名:DPRCのHTTPポート番号/drpc/関数名[/]、リクエストボディに引数
となっていることがわかる。引数を省略した場合、空文字が関数に渡される。GETとPOSTの両APIに実行時の違いは無さそうなので、クライアントの都合でどちらを使うかを選択すれば良いようだ。
実際に使ってみた。
Stormクラスタのセットアップ
最低限の設定として、ZookeeperとNimbus、DRPCサーバのアドレスを指定する(すべてlocalhost)。それを使ってコンポーネントを起動する。
$ curl -O http://ftp.meisei-u.ac.jp/mirror/apache/dist/storm/apache-storm-0.10.0/apache-storm-0.10.0.tar.gz $ tar zxvf apache-storm-0.10.0.tar.gz; cd apache-storm-0.10.0/ $ cp conf/storm.yaml conf/storm.yaml.default $ vim conf/storm.yaml $ diff conf/storm.yaml.default conf/storm.yaml 18,23c18,22 < # storm.zookeeper.servers: < # - "server1" < # - "server2" < # < # nimbus.host: "nimbus" < # --- > storm.zookeeper.servers: > - "localhost" > > nimbus.host: "localhost" > 37,39c36,37 < # drpc.servers: < # - "server1" < # - "server2" --- > drpc.servers: > - "localhost" $ ./bin/storm dev-zookeeper & $ ./bin/storm nimbus & $ ./bin/storm supervisor & $ ./bin/storm drpc &
Storm DRPCアプリケーションのデプロイ
DRPCストリームを含むStormトポロジを、Stormクラスタにデプロイする。今回はapache-storm-0.10.0.tar.gzに同梱されている、storm-starterから2つ拝借する。
- TridentWordCount
- 内部で無限に投入される文に含まれる単語をカウントし続けるストリームと、その結果を取得するDRPCストリーム(関数名は
words
、引数は任意の単語、返ってくる値はその単語のカウント数)を持っている - https://github.com/apache/storm/blob/master/examples/storm-starter/src/jvm/org/apache/storm/starter/trident/TridentWordCount.java
- 内部で無限に投入される文に含まれる単語をカウントし続けるストリームと、その結果を取得するDRPCストリーム(関数名は
- BasicDRPCTopology
- 単純なDRPCストリーム(関数名は
exclamation
、引数は任意の文字列、返ってくる値は引数の文字列末尾に!を付けたもの)を持っている - https://github.com/apache/storm/blob/master/examples/storm-starter/src/jvm/org/apache/storm/starter/BasicDRPCTopology.java
- 単純なDRPCストリーム(関数名は
$ ./bin/storm jar \ examples/storm-starter/storm-starter-topologies-0.10.0.jar \ storm.starter.trident.TridentWordCount TridentWordCount $ ./bin/storm jar \ examples/storm-starter/storm-starter-topologies-0.10.0.jar \ storm.starter.BasicDRPCTopology BasicDRPCTopology
DRPCのHTTP APIにアクセス
TridentWordCountは時間が経つにつれストリームに流れた文の量が増え、単語カウントが大きくなっていく。適当なタイミングでアクセスしてみた。対象関数はwords
で、引数として2つ「the」と「eat」をそれぞれGETとPOSTで渡してみた。
$ curl http://localhost:3774/drpc/words/the [[2679]] $ curl -X POST -d eat http://localhost:3774/drpc/words/ [[536]]
DRPCクライアントを用いた時と同様の返り値であるようだ。
次に、BasicDRPCTopologyについて。対象関数はexclamation
で、引数として「eat」と「Hello」をそれぞれGETとPOSTで渡してみた。
$ curl http://localhost:3774/drpc/exclamation/eat eat! $ curl -X POST -d Hello http://localhost:3774/drpc/exclamation Hello!
こちらも想定通り。
ちなみに、空白を含む文字列などを引数に渡す際にはURLエンコードして渡してやればStormの方でデコードしてくれて、結果もデコードされた文字列で返される。
$ curl http://localhost:3774/drpc/exclamation/The%20cow%20jumped%20over%20the%20moon
The cow jumped over the moon!
DRPCはStormの機能の中でも割とマイナな方だと思っていたが、かなり実用的な進化をしていて嬉しい。drpc.https.*
などの設定項目があることから、セキュアな環境もサポートしているようだ。
aitendoのUSBASPが替わってた
AVR-USBASP-Bが在庫なしで、AVR-USBASP-Cが大量にあった。
Bの方はaitendoロゴがありマイコンがATMEGA8Aだったが、CはV2.0 Lcsoft Studioと書いてあってATMEGA8Lを使っている。
ベースはどちらもUSBasp - USB programmer for Atmel AVR controllers - fischl.deのようだが、CはUSBasp AVR Programmer, Program Atmel AVR microcontrollersなどで販売されている派生版のようだ。違いを説明しているブログがここなどにあった。
本家のファームウェアのアップデートは止まっているし、わざわざ新しい既成品を揃える必要は無いかなと思って、買わなかったけどメモ。
myThingsのIDCFチャンネルとESP-WROOM-02とのMQTT双方向連携
準備
- スマートフォンにmyThingsアプリを入れる
- クラウドサービスならIDCFクラウド -使いやすく、パワフルのチュートリアルを参考にして、サーバ上にMeshbluサーバを立てる
- GitHub - esp8266/Arduino: ESP8266 core for Arduinoを参考にして、Arduino IDEでESP-WROOM-02のプログラムを開発できるようにしておく
使うArduino用ライブラリはGitHub - interactive-matter/aJson: aJson is an Arduino library to enable JSON processing with Arduino. It easily enables you to decode, create, manipulate and encode JSON directly from and to data structures.とGitHub - knolleary/pubsubclient: A client library for the Arduino Ethernet Shield that provides support for MQTT.の2つ。
Arduinoライブラリディレクトリの、PubSubClient.h
内の#define MQTT_MAX_PACKET_SIZE 128
となっているところを#define MQTT_MAX_PACKET_SIZE 1000
にする
myThings外部サービスチャンネル(トリガー) → IDCFチャンネル(アクション) → ESP-WROOM-02
myThingsアプリ上で、Yahoo!天気をトリガーにしたものと、ぐるなびをトリガーにしたものの2つの組み合わせを作成した。それぞれでアクションに渡すメッセージはそれっぽい感じにしている。
ESP-WROOM-02には以下のArduinoコードをビルドしたものをアップロードし、Arduino IDEのシリアルモニタを表示した状態で、Wi-Fi・Meshbluに接続しておく。
myThingsアプリから、2つの組み合わせを手動実行する(あるいは待つ)と、Arduinoシリアルモニタに以下のようなメッセージが出力された。
............. WiFi connected IP address: 192.168.10.20 succeeded to connect to mqtt broker {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":"東京(東京)の2015-10-17の天気は曇り、最高気温20、最低気温16、降水確率40、風向き北の風、波の高さ0.5メートル","fromUuid":"MYTHINGS_UUID"}} 東京(東京)の2015-10-17の天気は曇り、最高気温20、最低気温16、降水確率40、風向き北の風、波の高さ0.5メートル {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":"肉 × イタリアン Hana 六本木店 〒106-0032 東京都港区六本木7-14-10 誠志堂ビル6F","fromUuid":"MYTHINGS_UUID"}} 肉 × イタリアン Hana 六本木店 〒106-0032 東京都港区六本木7-14-10 誠志堂ビル6F {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":"個室&イタリアン CERTO! 六本木店 〒106-0032 東京都港区六本木4-11-5 アネックスビル1F","fromUuid":"MYTHINGS_UUID"}} 個室&イタリアン CERTO! 六本木店 〒106-0032 東京都港区六本木4-11-5 アネックスビル1F {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":"六本木 PALETTE 〜Italian Tapas〜 〒106-0032 東京都港区六本木7-14-10 誠志堂ビル6F","fromUuid":"MYTHINGS_UUID"}} 六本木 PALETTE 〜Italian Tapas〜 〒106-0032 東京都港区六本木7-14-10 誠志堂ビル6F {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":"豪快 イタリアン食堂 DESERT 〒106-0032 東京都港区六本木7-15-25 六本木7thビル2F","fromUuid":"MYTHINGS_UUID"}} 豪快 イタリアン食堂 DESERT 〒106-0032 東京都港区六本木7-15-25 六本木7thビル2F {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":"六本木バル PIZZANIA 〒106-0032 東京都港区六本木2-3-7 セントラルクリブIII1F","fromUuid":"MYTHINGS_UUID"}} 六本木バル PIZZANIA 〒106-0032 東京都港区六本木2-3-7 セントラルクリブIII1F
これで、ESP-WROOM-02がmyThingsのトリガーチャンネルからメッセージを受け取れていることが確認できた。
ESP-WROOM-02 → IDCFチャンネル(トリガー) → 外部サービスチャンネル(アクション)
myThingsアプリ上で、IDCFチャンネルをトリガーにしてYahoo!メールをアクションにした組み合わせを作成した。
ESP-WROOM-02には以下のArduinoコードをビルドしたものをアップロードし、Arduino IDEのシリアルモニタを表示した状態で、Wi-Fi・Meshbluに接続しておく。ここでは、DHT11の温湿度センサを接続し、その情報を流している。
しばらくするとArduinoシリアルモニタに以下のようなメッセージが出力された。
............. WiFi connected IP address: 192.168.10.20 succeeded to connect to mqtt broker Humidity: 39.00 % Temperature: 24.00 *C {"devices":["MESHBLU_ACTION_UUID"],"payload":{"humidity":39.00000,"temperature":24.00000}} Humidity: 39.00 % Temperature: 24.00 *C {"devices":["MESHBLU_ACTION_UUID"],"payload":{"humidity":39.00000,"temperature":24.00000}}
Meshbluに以下の様なPythonサブスクライバを登録しておくと、メッセージが出力された。
connected with result code0 received message: {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":{"humidity":39,"temperature":24},"fromUuid":"MESHBLU_TRIGGER_UUID"}} from MESHBLU_ACTION_UUID received message: {"topic":"message","data":{"devices":["MESHBLU_ACTION_UUID"],"payload":{"humidity":39,"temperature":24},"fromUuid":"MESHBLU_TRIGGER_UUID"}} from MESHBLU_ACTION_UUID
同時に、myThingsアプリのアクションで指定したメールアドレス宛に以下のようなメールが届いた。
これで、ESP-WROOM-02からのメッセージがトリガーとなり、アクションが発火していることが確認できた。
残念ながら、IDCFチャンネルのトリガーメッセージの内容を元にアクションのメッセージを変更する方法がわからなかった。
langtool.elの情報をポップアップ表示できるようにした
GitHub - mhayashi1120/Emacs-langtool: LanguageTool for Emacs は LanguageToolデスクトップ版をEmacsから使うためのElispで、ispell (aspell) と共に、英文を書く際にお世話になっている。
標準の使い方だとlangtool-check-buffer
でチェックプログラムを走らせ、問題があるとしてハイライトされた部分文字列にカーソルを置いてlangtool-show-message-at-point
でその指摘内容を確認するのだが、この指摘内容の表示がlangtool-error-buffer-name
で指定したバッファ名でウィンドウが開くので、結構見づらい。
そこで、これを GitHub - auto-complete/popup-el: Visual Popup Interface Library for Emacs で表示するようにした。
これで見易くなった。langtool-correct-buffer
の修正候補も出せるようになるともっと嬉しいが、そこまでする気力が無かった。
Emacs Lispって、Haskellでいうtake
が無いの?
FeatureFuを使ってみた
FeatureFuはLinkedInが作り公開しているFeature Engineeringのためのライブラリ。
使い方から機能を述べると、数式をS式の文字列として書き、変数に値をバインドしその文字列を評価すると、数式の結果が返ってくる。
参考資料
検証のためのコード
$ cd ~/ $ git clone https://github.com/linkedin/FeatureFu.git $ cd FeatureFu/ $ gradle clean jar $ cd ~/ $ git clone https://github.com/laclefyoshi/test_featurefu.git $ cd test_featurefu/ $ mvn clean test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
肝となるコードをgistに写した。ここに、現在のFeatureFuで使える演算子 (Operator) が全て列挙されている。
やはfor
やreduce
で書いて、その内側の数式をFeatureFuで書いておけば、使い回しもし易くなる、という考えだろう。論文に書かれた数式をコードに落とすのには慣れが必要だが、こういうライブラリがあれば、考えなければいけないことが1つ減ってありがたい。
OCNモバイルONE開通までの流れ
月末にOCNモバイルONE(音声対応)に申し込んで、開通までの流れを記録した。MNPはしていない。
月末は混むといわれているが、7営業日(+週末2日)で全て完了したので、まあ順調だったな方ではなかろうか。
第1週 月曜
goo SimSellerでgooのスマホ+OCNモバイルONE(音声対応)を注文
第1週 火曜(1営業日経過)
クレジットカード決済が完了した旨のメールが届く
第1週 水曜(2営業日経過)
商品が発送された旨のメールが届く
第1週 木曜(3営業日経過)
商品が到着(gooのスマホ+OCNモバイルONEの申込書)
申込書に従い、OCNモバイルONEフォームにアクティベーションコード等を入力して、SIM申し込み
ここからOCNモバイルONEのSIMが届くまでできること
- Wi-Fiを使った通信
- SMS認証を必要としないアプリ
第1週 金曜(4営業日経過)
OCNモバイルONE申込受付完了の旨のメールが届く
第2週 月曜(5営業日経過+週末2日)
OCNモバイルONEのSIMが到着
ここからOCN会員登録証が届くまでできること
- 4G/3G通信(ただしOCNモバイルONEアプリの利用(通信量の確認等)は不可)
- SMS認証を必要とするアプリ
第2週 水曜(7営業日経過+週末2日)
OCN会員登録証が到着
登録証に記載されたメールアカウントでメールを確認すると、050plusの番号とパスワードが記載されたメールが届いていた
ここからできること
- OCNモバイルONEアプリ
- 050plusアプリ
- OCN光モバイル割申し込み(OCN光を使っていれば)