サーバサイドエンジニアの @kasai です。
この記事は Photocreate Advent Calendar 2018 の 23日目 の記事です。
バックエンドの刷新中です
フォトクリエイトではおかげさまで日々何万枚といった写真を撮影させていただいており、多くの方にその一瞬をカタチにしてお届けすることができています。
その日々の膨大なデータを捌いているとても優秀なバックエンドシステムがあるのですが、実はこのバックエンドシステム・・少なくとも10年以上も前に作られた仕組みで動いて・・ます!なう!納品や出荷の経路やサービスの仕様に変更が入るたびに「修正」は度々行われてましたが、当時の設計思想やプログラムが脈々と受け継がれてました。
大変ありがたいことに、ここ数年で取り扱う写真が爆発的に増えてきました。そんな状況で2018年の最繁忙期を迎えることになり、10年モノの2008システム(と、この記事では呼ぶことにします)では耐えきれないということで、テックリードを中心にしたチームで一部を抜本的に刷新することにしました。
ちなみにフォトクリエイトの最繁忙期は10月の運動会のシーズンです。全国の幼稚園や保育園、小学校にて一斉に運動会の日程が組まれるので、会社を挙げて乗り越える一つの山場となっています。
行った改修
2008システム
改修前の2008システムについて話をしなければなりません。あまり細かなことはかけませんが、ざっくりこんな感じです。
- サーバ:
自社サーバ
- OS:
WindowsServer
- プログラム:
PHP4.4
先日のPHPカンファレンス2018ではEOLを迎えるPHP5系をPHP7.3にしようみたいな話が結構主流と感じましたが、まさかのPHP4.4でした。あくまでバックエンドのシステムであって公開しているものではない事情もあり、古いバージョンで置き去りにされていても大きな問題としにくかったのかもしれません。それに加えて動作環境がWindowsサーバなので扱いが独特です。プロダクト全体としても非常に重要な部分だったのですが、歴史を重ねるほどに手を入れにくくなっていた状況でした。
マイクロサービス化
フォトクリエイトでは今後すべてのシステムをクラウド化していく方針です。その方針に則って、2008システムもクラウドネイティブ化を目指しました。
クラウドネイティブ化に当たって行われたのが「マイクロサービス化」でした。2008システムの課題はアーキテクチャが古風だったというだけではありません。システムの中で色んな処理を行っている複雑さもありました。たとえばDBへの登録、写真の検査や加工、アップロードです。なので、「ちょっと処理を差し込みたい」というだけで、非常に慎重な作業が必要でした。これをこの機会にマイクロサービスとして分けることにしました。
結果として2008システムは7つのマイクロサービスに分割されました。
マイクロサービス化してよかった
マイクロサービスを用いたプロダクトを作るのは私は今回が初めての経験でした。理屈は分かってたのですが、実感としてメリットを感じることができたのは特に以下の点でした。
1)保守性が上がった気がする
2つの点で保守性が上がったと感じました。一つは問題が特定しやすくなったことです。もう一つは修正を入れる際の安心感です。
何かシステムの問題が発生したときに、問題箇所の特定がよりしやすくなったと感じています。何かしら問題が発生したとき、エラーログを吐いているプログラムをまずは見に行くと思いますが、この時点でかなり絞られています。サービス自体も小さなプログラムで、やっていることが少ないので、ソースコードの可読性も自ずと高くなります。『2008システムのどこかで何かが起きてる』とやっていた頃から大きな進歩です。
プログラムに問題があったとわかった際はプログラムの修正を行うのですが、その影響範囲の小ささは修正担当者の安心感にも繋がります。I/Fさえきちんと守られていれば、前後の処理への影響はないというのがマイクロサービスの基本だと思っています。
2)開発のスピード感が上がった気がする
マイクロサービスにすることで、自ずと一つのサービスに一人のエンジニアが集中するという状況になります。その規模はおよそ数日から1週間程度でした。エンジニアは一つのサービスに集中して取り組むことになるので、「ただひたすら作る」という状況が作りやすくなります。
I/Fの設計さえきちんと出来ているのが条件ですが、極論としてほぼサービスの単体テストがきっちりできていれば、結合テストで大きな齟齬が起きることはほぼ無いと感じています。
余談ですが、ただひたすらコードと向き合って完成まで突き進む疾走感はとても気持ちがいいものです。
マイクロサービス化する上での注意点
マイクロサービスは良いなーという一方で、気をつける点がいくつかあると感じました。
1)疎結合を徹底すること
マイクロサービスを作る際に、1つのプロジェクトで1つのマイクロサービスだけを作るということは無いと思います。おそらく幾つかのマイクロサービスを連動させる設計を最初から行うことでしょう。その際に、隣り合うシステムがお互いに依存してしまわないように気を付けるべきです。「マイクロサービスAから呼ばれたらこうする、Bから呼ばれたらこうする」みたいな仕様が入った時点でマイクロサービスの複雑度は上がります。
マイクロサービスへの移行を進めている中で、最初は上手く設計したつもりでも、進めていくうちに複雑度が上がっていかないようにしなければならないというのは途中段階で既に実感しているところです。
2)共通化すべきかどうかは慎重に行うこと
作っていくうちに似たような処理は共通化したくなるのはエンジニアの性だと思います。しかしそれは本当に共通化すべきマイクロサービスなのかは特に慎重に考えるべきです。
当社では写真販売サイトの運営を行っていますが、「スナップスナップ」「オールスポーツ」「フォトチョイス」・・というように複数の販売サイトを展開しています。これは単純に領域で分けているだけでなく、微妙に仕様が異なっています。
一見として共通そうな仕様に見えても、実はサイトによって微妙に違っていた・・!ということはあります。そして何より気にしなければいけないのは、今後「特定のサイトだけこういう仕様にしたい」といった要件が発生したときに共通処理が共通処理でなくなる可能性が発生します。共通化は今だけでなく将来もある程度見据えた状態で行わなければいけません。サイトの仕様に関係する箇所は心を鬼にして共通化しないように気をつけています。
3)ドキュメント大事
マイクロサービス化することでサービスの数が格段に増えるので、システム単体としてはシンプルになっても、全体を見渡すと複雑に見えます。今回は1つのシステムを7つのマイクロサービスに分割しました。それらの関係性はよりわかりやすく図示しておくべきです。先日のre:InventでStepFunctionがAWS Batchに対応したので、StepFunctionに移行できればより人間に優しい状態で管理できそうですが、全部がカバーできるわけではありません。どのマイクロサービスがどういう使われ方をしているのか、人間が見てわかりやすいように管理する重要性が増しました。
AWS Batch でバッチリ
こうしてマイクロサービス化したバックエンド処理の動作環境はAWS Batchを中心としました。AWS BatchはDockerコンテナとして定義したジョブを指定のコンピューティング環境で順次実行してくれるサービスです。
使い方としてはDockerコンテナを「ジョブ定義」として登録しておき、使いたいときに「ジョブ」として「ジョブキュー」に積んでいく感じです。ジョブキューに登録されたジョブは紐付いているコンピューティング環境の状況に応じて逐次実行されていきます。
https://aws.amazon.com/jp/batch/
https://docs.aws.amazon.com/ja_jp/batch/latest/userguide/what-is-batch.html
ジョブのDockerコンテナへは環境変数を任意で設定可能となっているので、それをパラメータとして利用しています。
スケールの安心感
AWS Batchに限らずにクラウドの利点になりますが、コンピューティング環境に応じてスケールしてくれる安心感が何より強いです。ジョブが溜まっている状況に応じてCPUを用意してくれて、かつ実行可能なだけ実行してくれるのは大きなメリットと感じます。当社の最繁忙期をトラブルなく乗り越えられたのは、何よりもAWS Batchの安定感によるものと思っています。
依存関係の登録が便利
依存ジョブが設定できるのもAWS Batchを利用する点で大きなメリットになります。AWS Batchでは例えば「A」「B」「C」の3つのジョブを登録するときに、『CはAとBが終わってから実行する』という依存関係の設定ができます。なので、『画像100枚を加工して完了を通知』ということをしたいとき、「画像を加工する」というジョブ100件とそれに依存する「完了を通知」というジョブ1件を最初にまとめて登録しておくことができます。画像の加工はコンピューティング環境が許す限りでドカッとやらせておいて、それでなお『100件終わったかな?』という監視をわざわざ書く必要がありません。
まとめ
re:Inventを受けて世の中のサーバレスの流れが加速するようです。単純にその流れに乗るわけではありませんが、システム刷新を通じてバックエンドの処理こそマイクロサービスの強みが存分に発揮できるという実感を持ちました。そのツールとしてAWS Batchは重要な役割を担ってくれています。
クラウドへの移行は道半ばですが、置き換えを行った部分に関しては1つのイベントに対して5〜6時間かかっていた処理が0〜2時間で済むようになって大きな成果が出ています。これでも全体としてもごく一部です。
フォトクリエイトの理念である「感動をカタチにしてすべての人へ」のもとで今後もより多くの方へ迅速に写真をお届けできるようなバックエンドの仕組みを構築していく所存です。
明日は
明日の記事は @ntakaaki さんで Transit Gatewayやってみた (Photocreate Advent Calendar 24日目) です。
フォトクリエイトでは感動をカタチにして迅速にお届けするバックエンドシステムの構築に興味がある方からの ご応募をお待ちしております。