rebuild-dropもしくは rebuild-renameジョブ・クラスを使うと、「現行のテーブルを削除し、新規のテーブルに集計結果を書き込む」または「新規にテーブルを作り、集計結果を書き込み、現行のテーブルとすり替える」という操作を、一つのトランザクションで行うジョブを簡単に実装することができます。rebuild-dropは対象のテーブルを作り直す前に drop tableし、rebuild-renameはすり替えられた古いテーブルを、別名で残しておきます。
ウェブアプリケーションに関する分析の話は、View-Centric Performance Optimization for Database-Backed Web Applications (ICSE'19) のものだったように思います。主に ORM でのアンチパターンをいろいろ分析して(講演では、そのパターンを色々紹介されていました)、それを静的解析してアプリからそのアンチパターンを見つけて良い方法を提案するツールを作ったよ、と。Panoramaというツールを作っていて公開されています。なんと IDE (Rubymine)との統合までやっているようです。凄い。論文中に、いくつかリファクタリング例があるので、気になる方は参考にしてみてください。しかし、Rails アプリの静的解析って、えらく難しそうだけど、どれくらい決め打ちでやってるんですかねぇ。
What are the causes of incidents?
↓ Few hardware problems
↓ Few memory bugs
↓ Few generic semantic bugs
↑ Many fault-detection/handling bugs
↑ Many data-format bugs
↑ More persistent-data races
How are incidents resolved?
↑ More than half through mitigation w/o patches
Table 1: How are cloud incidents different from failures in single-machine systems?
(↑ and ↓ indicate cloud incidents follow certain pattern more or less than single-machine systems.)
PLDI は、Programming Language Design and Implementation の略で、プログラミング言語の設計と実装について議論する、世界で最高の学術会議の一つです。以前は、実装の話が多かったんですが、PLDI 2019から引用しますが、
PLDI is the premier forum in the field of programming languages and programming systems research, covering the areas of design, implementation, theory, applications, and performance.
たとえばとある Web アプリケーションの自動生成されたダッシュボードは以下のようなものです。このダッシュボードを表示する JSON 表現として hako-console は https://gist.github.com/eagletmt/45f8c8bffcbe34f48e937a756aac2a34のようなレスポンスを返しています (※一部の値はマスキングしてます)。
Image may be NSFW. Clik here to view.Image may be NSFW. Clik here to view.
Grafana はダッシュボードの JSON 表現を介して import することもできます。したがって自動生成されたダッシュボードでは物足りず、たとえばアプリケーションが独自に Prometheus に保存しているメトリクスも表示したい場合にも、簡単に拡張することもできます。hako-console 上で固定のメトリクスを表示していたときと比べて、この点も Grafana を利用するメリットだと思っています。
見やすさのために一部の主要なメトリクスに絞って表示することにしたとはいえ、主要でないメトリクスが手掛かりになることがあるのはたしかです。そこで Grafana パネルのリンク機能を使い、別途用意された詳細なメトリクスが表示されたダッシュボードへ移動できるようにしています。
この機能を利用すると現在のダッシュボードで選択されている time range をリンク先のダッシュボードに引き継ぐことができます。とくに1日以上前の障害を調査したり振り返ったりするときには time range の引き継ぎは便利でしょう。
また、このアプリケーション毎のダッシュボードにはデプロイのタイミングを annotationとして表示するようにしています。
Image may be NSFW. Clik here to view.メトリクスの傾向が変化する原因の多くはデプロイです。プロモーション等によるユーザ数の急激な変化や下流のマイクロサービスのデプロイによるアクセス傾向の変化といった他の要因でメトリクスの傾向が変化することもありますが、それらよりもそのアプリケーション自身の変更が原因であることが多いでしょう。ダッシュボード上でデプロイのタイミングを分かりやすくすることで、意図しないパフォーマンス劣化が発生していないか、パフォーマンス改善を狙った変更がうまくいったかどうか、といったことが分かりやすくなることを狙っています。
なお、このデプロイのタイミングはどうやって取得しているかというと、クックパッドではほとんどのアプリケーションが ECS で動いているため、ECS の UpdateService API が実行されたタイミングをデプロイのタイミングとすることができます。そこで、S3 バケットに配信された CloudTrail のログファイルを加工して Prismに渡すことで Redshift Spectrum で読める状態にし、Redshift にクエリすることで UpdateService API が実行されたタイミングを取得して InfluxDB に保存し、Grafana からそれをデータソースとして annotation の query に設定しています。CloudTrail のログは他にも用途があるため、このように一度 Redshift に入れてからそれぞれが使うようになっています。
Image may be NSFW. Clik here to view.
Image may be NSFW. Clik here to view.会場となったBoston Convention and Exhibition Centerの、おそらく正面入口Image may be NSFW. Clik here to view.ベンダーによるブースなどが並ぶ、受付からすぐのスペース。会場は4階まであったので写っているのはごく一部と言えます
Image may be NSFW. Clik here to view.全体で60席くらい用意されていましたが、オンラインで参加できるのでこのホール外から参加していたチームもあったようですImage may be NSFW. Clik here to view.5-hour ENERGY という、ちょっとヤバそうなエナジードリンク
また、プロジェクトや部署ごとに、どの程度サービス運用のためのインフラコストがかかっているかを把握できるようなダッシュボードを作ることができると、財務管理上でもメリットになるでしょう。まるっと「インフラ代金」として予算管理しているものが、開発チームや部署、プロジェクトごとに予算を細かく設定し、追跡することができるのです。財務などのバックオフィスもインフラコストの状況を追跡できるようにしておく重要性はWhitepaper: The guide to financial governance in the cloudでも触れられています。
リソースプールの最適化に限界が見え始めた今、やるべきこと
SRE が責任として持っている、スポットインスタンスの利用推進や RI の適切な運用によって、開発チームが利用するリソースプール自体のコスト最適化は限界に近づきつつあります。次にやるべきことは、リソースプールの利用を最適化していくことで、これは組織全体として取り組めるように SRE がエンジニアリングで解決していく必要があります。
RI の状況ベースでの監視は、実際に状況が変わってからしか検知できないため、対応が後手に回ってしまいがちという弱点があります。RI の追加購入や exchange の際には、いくつ買っていくつ exchange するのかというプランを練ってチーム内でレビューする必要があるため、その作業が終わるまでは RI による費用削減効果が減ってしまうことになります。
少なくとも RI の失効は事前に知ることができるため、上述の RI の状況をベースとした監視に加え、以下のような対応フローも整えています。
RI の失効が発生する 7 日前に PagerDuty の incident を発行してアラートをあげる。
Image may be NSFW. Clik here to view.Grafana から確認できる CloudWatch カスタムメトリクスに集積された RI の状況
ちなみに、Cost Explorer API から取得できる値は、月に一回程度、変な値を示してしまう場合があるのですが、頻度も少ないですしそれは許容しています。このスクリーンショットでは、左上のグラフの谷になっている箇所ですね。
実際に RI の状況が変化してメトリクスがしきい値を割ると、GitHub に issue が自動的に立って場が作られ、そこで対応することになります。
Image may be NSFW. Clik here to view.RI の監視システムによってあがったアラートに GitHub 上で対応している様子
このスクリーンショットのシナリオでは、Amazon ES の RI カバレッジがしきい値を割ったことが検知されており、わたしがその原因を調べてコメントし、オペレーションによる一時的なものであることを確認して CloudWatch Alarm のしきい値を調整し、メトリクスがもとに戻ったことを確認して issue をクローズとしました。別のケースでは、RI を追加で購入したり exchange したりといったオペレーションをしたこともありました。
さて、ここからは実装の話に移ります。以下のトピックについて説明していきましょう。
RI の状況を知る
RI の状況が変わったときにアラートをあげる
RI の失効が近づいたときにアラートをあげる
RI (リザーブドインスタンス) の状況を知る
RI がどのような状況にあるかは、RI 利用率と RI カバレッジによって知ることができます。
RI 利用率は、購入した RI がどの程度有効になっているか、すなわちどの程度余らせることなく有効に使えているかを示す割合です。RI カバレッジは、オンデマンドで動いているインスタンスの総量に対して、RI によってどの程度カバーされているかを示す割合です。
RI 利用率は 100% を維持できている状態が望ましいです。RI カバレッジも同様に、できる限り 100% に近い状態を保っているのが理想です。しかしながら、ある時刻において RI カバレッジが 100% になるように買ってしまうと、将来的な利用の変化に対応することが難しくなります。アプリケーションの改善により必要なキャパシティが減ったり、EC2 であれば、スポットインスタンス化やマネージドサービスに寄せることで RI が余るといったことも起こるでしょう。あまり考えたくはないですが、サービスのクローズによって不要になるリソースもあるかもしれませんね。そこで、ターゲットとなるカバレッジを、たとえば 70% などと決めておき、その値を下回らないように RI をメンテナンスするのがよいでしょう。
RI 利用率や RI カバレッジは Cost Explorer のコンソールや API から確認でき、フィルタを駆使することでリージョンやサービスごとに値を絞り込めます。
Image may be NSFW. Clik here to view.Cost Explorer から確認する RI 利用率の様子
前半ではパブリッククラウドのコスト最適化についての考えを述べ、後半では、その取り組みの一部である RI の維持管理のための仕組みについて説明しました。
RI は、スポットインスタンスの積極的な利用に次ぐコスト最適化の強力な武器ですが、日々の手入れを怠るとその力を十分に発揮することができません。この記事では、クックパッドではその武器をどのように手入れしているかということについて説明しました。RI の管理にお悩みの方は、参考にしてみてはいかがでしょうか。
2.0からはこれに加えて、決済の承認が必要になります。
Google Play決済自体は決済処理時に走る(Pending Purchaseを除く)のですが、3日以内に開発者が決済の承認を行わない場合返金されます。
通信断や障害等で購入フローが正常に完了せず商品が付与されなかったユーザが自動的に救済されるようになるのは、サポートコスト削減の面でも非常に良いですね。
Image may be NSFW. Clik here to view.2.0での購入フロー
一見、購入フローに処理が1ステップ追加されただけのように見えます。加えてリリースノートにも
For consumable products, use consumeAsync(), found in the client API.
本記事ではGoogle Play Billing Client 2.0における消費型商品の決済の承認(acknowledgement)について解説しました。
弊社において利用していない機能もあり(定期購読のupgrade/downgrade等)、決済の承認に関する網羅的な解説とまではなっていないですが、
Google Play Billing Client 2.0導入の手助けとなれば幸いです。
Image may be NSFW. Clik here to view.OiCyWater外観
OiCy Waterは、水の『硬度』と『分量』をレシピに合わせてボタン一つで出してくれる、電動ウォーターサーバーです。スマートフォンのアプリ上でレシピを閲覧すると、そのレシピに書かれている水の『硬度』と『分量』(※)が自動的に装置に転送されます。ユーザーは装置上のボタンを押すだけで、閲覧しているレシピで使うための適切な水を得ることができます。『硬度』と『分量』は、ジョグダイヤルを回して手動で調整することもできます。
Image may be NSFW. Clik here to view.OiCyWaterの構成本機は、2つのチューブポンプを用いて、『硬水』と『軟水』2つのボトルから水を排出する装置です。使用したチューブポンプは3.5ml刻みで排出量を制御、最速で1分間に1.4Lの水を排出することができます。 制御用のマイコンシステムにはM5Stackを使いました。理由は、技適が取れていてかつとても安価、ネット上に参考にできる情報が豊富にあって、ライブラリも充実しているからです。周辺デバイスへの信号は、モーターの速度制御をするPWM信号のみM5StackのGPIOから直接出していますが、それ以外はI2C接続したGPIOエクスパンダを経由してやり取りをしています。GPIOエクスパンダ側で、信号の変化を割り込み制御をする予定でしたが、WiFiのライブラリと同時使用するとファームにリセットがかかるという現象があり、イベント直前で時間がなかったためこの問題解析は保留して、割り込みなしのポーリングで、ジョグやモーターの回転を拾う処理になっています。 モーターの回転は、チューブポンプの回転部分とポンプ外装の間に隙間があるので、100円ショップのネオジウム磁石をそこに接着、ポンプ外側に設置した磁気センサから非接触で回転検出をしています。この方法では回転方向は分からないのですが、チューブポンプは負荷が非常に大きくギア比の大きなモーターが付いており、外部から強制的に回すことはほぼ不可能です。そのためポンプ回転部分はモータードライバに入れている信号の向きにしか回らないため、特に回転方向を検出する必要はありません。磁石の貼り付け位置を、チューブポンプのローラー部分にすることで、水の排出綺麗に途切れるところで正確にモーターを止められる”位置制御にも利用しています。 Image may be NSFW. Clik here to view.OiCyWaterのメカ構造チューブポンプはモーター部分が長く突き出した構造をしていて筐体へのおさまりが悪いため、ベルトとプーリーを用いてモーター部分をポンプ本体とタンデム構造にし、2つのチューブポンプを向かい合わせに対向させるメカ構成にしました。2つのチューブポンプ、2つのモーターは2mm厚のステンレス製の背骨に固定されて、チューブポンプを回す強力なモータートルクに負けない強靭な剛性を持たせました。工房のレーザーカッターでは、金属の切り出しはできないため、この背骨部分の制作のみ外注先に頼んで特急で作っていただきました。ペットボトルを下向きに指すジョイント部分については、弁のついたペットボトルキャップと交換する部分はペット用の給水器の部品を流用、刺さる側の部品は3DプリンタをつかってABS樹脂で成形しました。2Lの水の水圧がかかっても水漏れをしない構造を作るのには試作検証改良を繰り返す必要がありましたが、3Dプリンタが手元にあることは短期間での開発にとても役立ちました。
OiCyサービス対応電子レンジ
Image may be NSFW. Clik here to view.OiCyサービス対応電子レンジ SIGMAメーカー様からお叱りを受けるかもしれないのであまり大きな声では言えないのですが、市販の電子レンジを改造して、スマートフォンのアプリ上で閲覧しているレシピに書かれている 『加熱ワット数』、『加熱時間』をWiFiを通じて自動的に装置に転送されるようにしたものが、OiCyサービス対応WiFi電子レンジ(開発名:SIGMA)です。
SIGMAの構成
Image may be NSFW. Clik here to view.SIGMAの構成電子レンジは、強電系に非常に高圧な回路と大容量コンデンサを搭載しており、改造には危険を伴います。専門的な知識のない場合には絶対に真似しないようにお願いします。今回の改造は、できる限り装置の深い制御部分に手を入れず、UI部分を乗っ取る形でHackしました。こうすることで、強電系の回路に一切触れずに欲しい機能を実現することができました。 電気量販店で、改造しやすそうな電子レンジを探すところから、開発は始まります。改造用の電子レンジを選択する上でのポイントは、液晶表示やタッチパネルなどを用いてるものは、現在の状態を正確に把握するための難易度が高いため避けます。LEDのみ、物理スイッチのみでUIが構成されていて、かつスイッチに複数の機能が割り当てられていないものが好適です。
OiCy Waterと同様に、制御用のマイコンシステムにはM5Stackを使いました。この電子レンジは、UIが、LEDと2つのジョグスイッチだけで構成されていたので、これらの入出力と扉の開閉センサをロジック回路処理(時分割表示のLED信号の復調回路)を噛ませてGPIOエクスパンダに接続し、M5Stackからは全体が一つのI2Cデバイスとして見えるようにしました。
外装は、操作パネル部分のジョグやLEDをすべて外し、レーザーカッターで加工した3mm厚の乳白色のパネルで覆い、表面上からはM5Stackの表示パネルとボタンのみしか見えない構造になっています。スマホからのレシピ情報転送以外に、M5Stackのボタン操作によるレンジ設定変更が可能です。加熱のスタートやキャンセルはドアの開閉で行い、ボタン操作は不要です。
OiCyサービス対応IHプレート
Image may be NSFW. Clik here to view.OiCyサービス対応IHプレート OMEGAこちらもメーカー様からお叱りを受けるかもしれないのであまり大きな声では言えないのですが、市販のIHプレートを改造して、スマホ端末で閲覧しているレシピに書かれている『火力』、『加熱時間』をWiFiを通じて自動的に装置に転送されるようにしたものが、OiCyサービス対応WiFi IHプレート(開発名:OMEGA)です。
クックパッドアプリ内の Kotlin 比率が高くなって来たのでAndroidKTXを導入しました。
去年の11月時点ではクックパッドアプリのおよそ20%が Kotlin でしたが、現在ではさらに Kotlin への置き換えが進み半分ほどがKotlinで書かれている状態です。
Image may be NSFW. Clik here to view.