AWSの話題を中心に、日々の業務やプログラミングの徒然を綴るエンジニアブログです。

HANDS LAB

HANDS LAB ENGINEERS BLOG

ハンズラボエンジニアブログ

東急ハンズのiPad POSでRealmを使ってみた

Pocket

この記事は、Realm Advent Calendar 2015の22日目の記事です。

ハンズラボの黒岩です。

エンジニアブログに書くのが初めてなので軽く自己紹介させてください。
iOSアプリ開発・MDMを使った運用を主に担当しており、現在は東急ハンズの内製でiPad POSレジを開発しています。
(まだ、数店舗での導入しておらず、東急ハンズ・ハンズビー・ピカロ全店のレジを順次iPadに置き換える予定)

東急ハンズのPOSでは、多くの場面でRealmを使っています。

どの場面で利用しているか

  • 商品マスタ
  • 金券マスタ
  • 値引に関するマスタ
  • 取引情報
  • 支払情報
    などの保存に利用。

Realm採用に至った理由

  • パフォーマンスの良さ
  • アップデートが頻繁に行われており、将来性がある
  • 学習コストが少なく書き込み読み込みならすぐに理解が出来る
  • 自動マイグレーションでとても楽

毎朝90万件のデータをアップデート

商品、金券など、毎朝最新マスタのダウンロードします。
商品マスタだけで90万件分のデータがあり、JSONデータをダウンロード・マッピングした後、Realmに書き込みます。
ダウンロード・マッピング・書き込み処理合わせても15分ほどで終わり、Realmの書き込み速度の速さが素晴らしい。(近い将来、全件更新ではなく、差分更新にする予定)
現状、Realmが起因でのクラッシュ等の問題も見られず、順調に運用出来ています。

マスタ取り込み・Realmへの書き込み

お金を扱う処理は、 NSDecimalNumber で扱って計算を行いますが、
NSDecimalNumber のままRealmに保存できないため、下記のように数値をStringに変換して保存します。

1度に1万件ずつJSONデータを ObjectMapper でObjectにマッピングを行い、RealmObject に変換して書き込みます。

関連・オプショナル

取引に支払、複数の取引明細をもつなど、関連で簡潔に定義できる。
必要な場合のみセットするものはオプショナルで持つなどして対応できる。

マイグレーションが楽

Realm最新バージョンでは、例えフィールドがいくつ増えようとも増えても自動でマイグレーションが行われるため、
schemaVersionをインクリメントするだけの修正で済みます。

マッピングが辛かった

ObjectMapperのマッピングの抜け漏れがあって、Realmに保存されないフィールドが多々あった。
やはり手メンテ・目視でもメンテは辛い。

おわりに

軽く上辺だけ話になり、Realmの概要みたいになりましたが、
使い勝手がよくパフォーマンスの良いのでぜひ使ってみてください。

Pocket

AWSでしくじった話 (ElasticBeanstalk編)

Pocket

こんにちは、井上です。

最近好きな番組は「しくじり先生」です。
毎回、何かしらでしくじった諸先輩方が出演し、しくじった体験談と、それを元にした教訓をおしえてしてくれる番組なのですが、実体験に基づくだけあって教訓も説得力があり、非常にためになります。
辺見マリが洗脳されて5億円とられた話とか、生々しすぎて恐怖でした。

それにちなんで、今回はAWSの利用でしくじった話をしようと思います。

今回私がしくじったサービスは、ElasticBeanstalkです。

ElasticBeanstalkは簡単に説明すると、WEBアプリケーションのデプロイ、構成管理、オートスケールなどをまるっと面倒を見てくれる便利なサービスです。

2014年の4月くらいから利用検討を開始し、最初の頃は情報も少なく手探りの状態からスタートしました。
特に ebextensions で設定する構成管理の部分にクセがあり、どのようなタイミングでどのような処理が実行されるのかわからずに四苦八苦しました。

AWSのサポートに問い合わせたり、オークファンの得上さんに相談に乗ってもらったりしながら徐々に問題を解決していき、現在では複数のプロジェクトで活用するようになりました。
その試行錯誤の結果の秘伝のタレがこちらです。 ElasticBeanstalk .ebextensions 逆引き辞典

そんな運用もこなれてきた時に悲劇がおきました。
Applicationの消失です。

Applicationの消失

ElasticBeanstalkは、アプリケーションを配置する Application という単位の中に、開発環境、ステーング環境、本番環境といった様々な状態のものを動作させるための Environment という枠があります。

Environmentでは、アップロードされたいろいろなアプリケーションバージョンを選択し実行することができます。

こんなイメージです。

sikujiri_0

実際、消失したApplicationの中では、本番環境はもとより、ステージング環境、開発環境、○○向け開発用などいろいろなバージョンを動作させていました。また本番環境はBlue/Green Deploymentを実行するために本番待機系などもありました。
1つのEnvironmentには、ELB、EC2インスタンス、セキュリティグループ、AutoScalingGroupなどが含まれていましたが、それらもろとも消失しました。

なんで消えてしまったか

完全に私のオペレーションミスでした。
利用しなくなった古いApplication versionを掃除しようとしていて、誤ってApplication を削除してしまったのです。

以前、急にデプロイできなくなった問題が発生したことがあり、原因がApplication version数の上限に達したことによるものだったため、折を見て利用しなくなったApplication versionはポチポチと消してきれいな状態を保つようにしていました。その作業が裏目に出たのです。

sikujiri_1

sikujiri_2

押してしまったと同時に、全てのEnvironmentがグレーアウトしました。
一瞬何が起きたのか分かりませんでしたが、すぐに気づき血の気がサーっと引いていくのを感じました。

EC2インスタンスの一覧画面に行くと、今まさにターミネート処理中のインスタンスが並んでおり更に絶望しました。
またCSチームの方から「なんかエラーが起きてサービス見られない」という声が聞こえはじめました。

復旧作業

何が起きたのかを察した後は、冷静に冷静にと心のなかで唱えながら、復旧手順を考えました。

が、スクリプトを1つ実行すれば、Environmentが作成できるように自動化してあったことを思い出しました。
手動でApplicationを作成し、その中にEnvironmentを作成しデプロイするスクリプトを流しました。

スクリプト1発とはいえ、Environmentを作成するには、ELBの作成、AutoScalingGroupの作成、インスタンスの起動、アプリケーションのデプロイなど一連のリソース作成が流れるので10分くらいかかります。
それを待っている間の生き地獄感といったらありません。

何か失敗するのではとドキドキしながら待っていたのですが、無事立ち上がってCNAMEを書き換えるとアプリケーションが正常に動作しはじめました。

削除してしまってから、復旧まで約15分でした。

教訓

これらの事象から学べる点を上げてみたいと思います。

手作業はときどき失敗する

まず失敗点として、手作業で大事な作業を行っていたことです。手作業は必ずミスをする可能性があるので、繰り返し行う作業はスクリプト化するなど、間違えないようにしておく必要があると思いました。

一方で環境構築のための手順はコード化されていたため、復旧にかける時間が短くて済みました。
ElasticBeanstalkでAutoScaleを導入する前は、そもそもテレビで取り上げられると30分くらいつながらなくなっていたのでそれよりも短かったと言えます。

IAM権限は最低限

IAM権限の調整により、危険な作業は行えないようにしておくべきと思いました。

マネージメントコンソールを使う際は緊張感をもつ

ElasticBeanstalkの操作に慣れてきていたため、緊張感も足りなくなっていました。
AWSのマネージドコンソールは、結構危険な作業もサクッと行えてしまったりします。
頻繁に使う人ほど慣れてしまって緊張感がなくなるのではないでしょうか。

アプリケーションは状態を持たない

今回のアプリケーションは、データは、DynamoDBやS3など、マネージドシステムに配置しており、インスタンスに状態を持たないようになっていたためインスタンスを立ち上げ直せばすぐに復旧できるようになっていました。
このあたりは、ElasticBeanstalkを使っていて本当に良かったと思いました。

データについては、マネージメメントシステムとはいえ、別の方法にて保全しておき、スムーズに復旧できる手順を確立しておく必要があります。

復旧訓練の必要性

クラウドは便利な反面、怖いと実感しました。

クラウドの導入により、ハードウェア的な障害は避けられるようになりましたが、論理的な障害は防げません。
災害に備えて避難訓練を行うように、クラウドならではの障害にそなえ訓練しておく必要があるのではないでしょうか。
最悪のケースとして、AWSアカウントごと消した場合にどれくらいの時間で企業活動を復旧させることができるか?というのを考えてみるだけでも、やるべきことは見えてくるように思います。

AWSへ望むこと

  • Deployボタンの横にDeleteボタンが配置されているなど、UI上ちょっと工夫してほしいなぁと思う部分が見受けられます。
  • 危険な操作をするときには、クリックだけではなくキーボード入力をしないと実行できないようにしてほしいです。
    • Githubでは、レポジトリを削除する際には、レポジトリ名を入力しないと実行できなくなっています。あれはとても良いインターフェイスですね。

最後にお詫び

無事復旧できましたが、障害時にまさに利用しようとしていたお客様は、急につながらなくなって残念な思いをされたかと思います。この場を借りてお詫びいたします。

Pocket

Twilioで世界に通用する再配達自動応答システムを作る

Pocket

この記事は、Twilio Advent Calendar 2015 の21日めの記事です。
といいつつ、Twilioはほとんど触ったことなかったので、練習として佐川急便の再配達受付みたいなものをつくってみました。

デモ電話番号: 050-3159-5616 (かけると再配達受付っぽいものが動きます)

Twilioに作成した電話番号にかかってくると、Twilioがこちらの指定したURLにリクエストを送ってくれるようで、
こちらでは、それにレスポンスするAPIを用意すれば良いようです。

こんな感じですね。

twilio_uml

まずは、Twilioに設定する初期URLにあたるXMLを作ります。
これは、特に動的な部分はないので単なるXMLです。

File: index.xml

Say のタグに書いた内容を読み上げてくれるようです。language を指定すれば日本語も行ける。すごい。
あと、numDigits で桁数と、次のアクション(APIコール先)として twilio_2.php を指定しました。

7桁の番号が押された時に遷移する次のアクションの twilio_2.php はこんな感じです。
伝票番号の読み上げのところで、Playタグを使ってみました。
Playタグは、音声ファイルを再生してくれるタグのようです。
伝票番号の確認をし、良ければ1、修正する場合には 9 を押して貰うように促します。

File: twilio_2.php

入力された番号(1か9)によって条件分岐するのが、次のアクションの twilio_3.php です。
1 が入力されてたら、再配達希望日時を聞くフローへ、それ以外の場合には最初のフローへ戻すようにアクションを指定しました。

File: twilio_3.php

こんな感じで、ちょいちょいとXMLを返していくだけで、佐川の再配達受付システムができてしまいます。
初心者でしたが、3時間くらいで作ることができました。

ちゃんと作るには、DBとの連携とかいろいろやらなければならないですが、この時間でこれだけのものが作れるのはホント驚きです。

あ、タイトルで「世界に通用する」というのは、伝票番号の復唱のとき、3の倍数の時だけアホな感じで読み上げるからです。古いですね… すみません。

最後に

オフィスでアホな音声を発してくれた青柳さん、藤倉さんありがとうございました。

Pocket

SlackBot大量生産中。

Pocket

HHBot

BooklogBot作った倉嶋です。
↑は昨日・今日で作った社長の予定を通知するHHBotです。(Hideki Hasegawa Botの略)
今日はLambda+PythonじゃなくてGoogle Apps ScriptでSlack Bot作った話をば。

おかげ様で前回の投稿は好評いただいたのですが、Lambdaで作ると大量生産には向きません。
もっと遊びたい 基、Slack生活向上のため、もっと簡単に作りたい。
ちょっと調べてみたところ、Google Apps Scriptで作るのが良さそうだ、ということでいくつか作ってみました。

ざっくりお昼休み2,3回に1つくらいのペースでBotが作れます。
以下、作ったBotを順不同に。

  • 今日の予定通知Bot
  • 社内ポータル更新通知Bot
  • 今日のオススメランチBot
  • Slackに新しいチャンネルできたよBot
  • Slackのスターをつけたよ消したよBot
  • 社長の予定通知Bot new!

Google Apps Scriptのいいところ

  • Googleのサービスとの連携が簡単
  • Slack連携のライブラリを公開してくれている方がいる
  • Javascriptで書ける
  • 勝手に版管理してくれる

東急ハンズはGoogle Apps for Businessを全社的に導入していますので、メールはgmail、カレンダーはgoogle calendar、忘年会の出欠簿はgoogle spreadsheetです。
(MS Officeも使っていますが、ハンズラボメンバーはMacユーザも多く、それほど使用頻度は多くないです)
おかげで、gmailやgcalと連携してほしい情報をjsonなどで取ってきて、ちょっと体裁を整えてSlackに投げればBotがすぐに作れます。
Google Apps Scriptの拡張子は.gsですがほぼJavascriptなので、Javascriptの勉強にもなります。

Google Apps Scriptのもう少し・・・なところ

  • Editorが組み込みオブジェクトのメソッド・プロパティは補完してくれない
  • プロジェクトが個人のmailアドレスに紐づくので、作った人が退職したら「権限の譲渡」とかしないと読めなくなる
  • npmなどでライブラリの追加ができない
  • 時間帯指定では起動できるが、時刻指定はできない

var dt = new Date(); とかしたらDateオブジェクトのメソッドとか補完してほしいじゃないですか!
あとはECMAScript2015対応とかどうなるんですかね?

Google Apps Script、お気軽に作れておすすめです。社内のJavascript勉強会で作り方を共有したので、倉嶋以外が作ったBotもドンドン作られるはず。どんなBotが出てくるか、楽しみです!

— 追記 —

参考にさせていただいたサイトは以下のとおりです。ありがとうございます!

Slack BotをGASでいい感じで書くためのライブラリを作った
今日の予定をまとめて教えてくれるslackの秘書BOT

Pocket

Swaggerで作るSPECファイルを小さいファイルに分割する

Pocket

こんにちは、井上です。

Swaggerで始めるモデルファーストなAPI開発」を見て興味を持ったので、Swaggerをちょっと触ってみたのですが、すぐに、これ1ファイルの YAMLファイルでメンテナンスするの超しんどくない?と感じました。

なので、分割する方法を調べてみました。で、みつけたのが下記エントリ。
How to split a Swagger spec into smaller files

方法としては、別々のファイルに書いた定義を $ref で参照しておき、それを json-refs でマージして1ファイルに戻すというやり方のようです。

下記のような YAML ファイルを、

下記のように分割します。

起点となる index.yaml は下記のようにリンク集のような形になります。

サンプルが githubに上がっているので、それで試してみます。

全部マージして出力されました。

JSON形式になっていますが、resolve.js を下記のような感じに変更すると、YAML 形式で出力されます。
※ js-yaml が必要なので、別途 npm install js-yaml が必要です。

オプションに、resolveLocalRefs: false を加えると、ファイル内の $ref: ‘#/definitions/User’ は展開されず、別ファイルのみ展開されます。
同じ定義を繰り返し参照しているような場合には、展開しないほうが見通しが良いと思います。

使用できるオプションは、下記で参照できます。
json-refs/API.md at master · whitlockjc/json-refs

Pocket