- 講演資料(柴田氏):大規模開発におけるこれからのフロントエンド開発
- 講演資料(伊藤氏):Yahoo! JAPANが実践するOpenStackと大規模環境でのコンテナ利用
めまぐるしく進歩するフロントエンド技術
本セッションは2部構成で、前半はフロントエンド、後半はインフラについての話だった。
前半は柴田氏が登壇し「大規模開発におけるこれからのフロントエンド開発」と題して語った。柴田氏はデザイナーとして勤務しているが、最近の主な担当は、広告入稿管理のフロントエンド周りの開発だ。
柴田氏が最近のフロントエンドに関するトピックで目立っていると感じているのは「シングルページアプリケーション」。この言葉自体は新しいものではないが、最近トレンドになってきている。
従来は、サーバサイドでPHPやRubyによってHTMLを構築し、それをブラウザに返して表示させる手法が主流だった。それがシングルページアプリケーションになると、サーバから返すのは最初の一回だけで、以後はJavaScriptで必要なデータを、その都度APIで取ってくる。つまり、従来サーバサイドで行っていた処理をクライアントサイドで行っているというわけだ。すると、JavaScriptで行う必要がある処理が多岐にわたり、実装が煩雑になりやすい。「機能ごとにファイルを分割し、きちんと整理しないと、訳が分からない状況になる」と柴田氏は言う。
ここで重要になるのが、モジュールの管理だ。もともとJavaScriptはその構造上、丁寧にファイル分割したとしても、ひたすらJavaScriptの外部ファイルを定義したHTMLを読み込むことしかできない。そのため大規模なアプリケーションになると、その読み込み数が30を超えることもある。
またファイル同士の依存関係があり、「ファイルAをファイルBのあとに読み込まないとエラーになる」ということがある。
少し進化したやり方だと、機能のまとまりごとに連結するという方法もある。こうすることで読み込みリソースが減り、モジュールの依存関係も解決される。
さらに、CommonJSスタイルによって依存解決する方法もある。もともとJavaScriptはブラウザで動くことを前提に作られているので、ファイル読み込み機能などは用意されていなかった。それが最近ではサーバ対応など、ブラウザ以外でも動くようになってきている。そこで、どのようなプラットフォームでも動くように、標準仕様を定めようとして考えられたのがCommonJSだ。その中でModule APIを受け、require()を用いてファイルの読み込みができるようになる。しかし、この関数はブラウザ上では動作しない。最近では、それを可能にするツールwebpackやBrowserifyが出ているので、事前にコンパイルしてから読ませるようにする。
2015年6月、JavaScriptの最新仕様ECMAScript 2015(ES6)が正式公開された。これにより、それまでプロトタイプなどを使って擬似的にクラスを表現していたところを、標準的にクラスを作れるようになったり、コールバック地獄で苦しんでいたところをプロミスで解決できたりするなど、色々と便利な機能が増えた。
ただ現状では、動く環境が限られているため、ヤフーではBabelといったツールを使ってES6からES5にコンパイルしてからブラウザに読ませる流れが主流になっている。「本当にコンパイル祭りという感じ」と柴田氏。
続くテーマは、フレームワークだ。JavaScriptのフレームワーク戦争などと言われているが、柴田氏は「若干落ち着いてきたものの、その中でも未だ勢いがあるのがAngularとReact」という。このように、フロントエンド技術のトレンドはめまぐるしく変わり、技術の進化スピードは半端ではない。
大規模開発における技術選択のポイントは「息の長い技術であるか」
昨今のフロントエンド周りの新技術に対し、ヤフーの対応状況はどうか。柴田氏は「少々残念だが、シングルページアプリケーションは△、CommonJSとES6は×、フレームワークは△」と評価している。
シングルページアプリケーションの対応状況が△というのも、ヤフーではサーバサイドでHTMLを構築しているアプリケーションが多く、長く続いている大規模なサービスが多いため、なかなかシステムをリニューアルする工数が取れない。また、HTMLメインで進めてきたので、JavaScriptを書けるエンジニア・デザイナーが少なく、全体の2~3割程度だ、という背景がある。
2つ目のCommonJSスタイル、ES6に関しては、まだごく少数のケースにしか対応できていないという印象だ。ただ最近、新規サービスでは導入しているケースもある。しかし既存サービスをリニューアルするのは厳しい。
フレームワークに関しては、シングルページアプリケーションの割合と比例している。その中でAngularとBackbone、React、Vueなどを用いたアプリケーションが増えている。中でもReactが増えつつある。
大規模プロダクトをリニューアルするには、専用の工数を確保する必要がある。既存の機能改修とバグ改修を同時に進めていかなければならないので、単純計算で人数が2倍必要になる。かつ既存の回収とリニューアルのスピードが遅いと、追いつかない。サグラダ・ファミリア状態になってしまう、という。
以上の課題を解決するため、ヤフーでは2014年頃、フレームワークを統一しようという流れが現れた。当時、ヤフーのプロモーション広告は、スポンサードサーチ/YDN(Yahoo!ディスプレイアドネットワーク)についてはjQuery、Twitter広告はBackboneで作っていた。これらをAngularに統一しようと考えたのである。
1年ほど経った時点で、アプリケーションが大規模すぎたため全体の3割程度しか進んでいない状態だった。またReactが伸びてきて、当時最強だったAngularの影がだんだん薄れてきた。そうこうしているうちにAngular2のベータ版が出てきて、これから新規のプロダクトをAngular1で作るのは、モチベーションが上がらない状態になってしまった。
フレームワーク統一のメリット、デメリットについてまとめたのが下記のスライドだ。
以上の点を考慮して、柴田氏のチーム周辺では統一を止めようという結論になった。では、現状を打破するためにどうしていったのだろうか。
技術が進歩するのは素晴らしい。ただその分、既存の技術が古くなっていくのも事実だ。そのため、サービスはいつかリニューアルせざるを得ない。そこで重要となってくるのは、どれだけ息の長い技術を選択できるかになる。柴田氏が「進歩の種類」として挙げるポイントは以下の3点だ。
- 言語仕様:変わるのは必然。polyfillを使って未来を先取りすることで、プロダクトの寿命を延ばせる。
- 概念:ここではAjax、JSX、Fluxなどのことで、イノベーションにより今までのバランスが崩壊することがあるので注意。
- フレームワーク:発展がとても早いが、機能的には近しいものが多い。今後の言語仕様に沿っているかどうかが長生きの鍵になる。
技術選定のポイントとして柴田氏が挙げるのは次の3つ。基本として新しい言語仕様は取り入れていくこと。未来の言語仕様にうまく載ることができそうな技術を選ぶこと。最後に、話題に上がってくる新しい概念は、とりあえず触っておくこと。
では新しい技術をいつ取り入れればいいのか。何事もすぐに取り入れるのは危険だ。新規リリース直後の場合、バージョンアップが多い。特に大規模なアプリケーションにおいて、ライブラリのメジャーアップデートはリスクとなってしまう。話題に上がってから半年〜1年が経ち、それでも筋が良さそうだったら取り入れるという戦略を取っているとのことだ。
ここで柴田氏は、ヤフーならではの大規模開発、特にプロダクトの数が莫大に多いプロジェクトにおいて適した方法について語った。ポイントは「仕組みの共通化」「モジュールの共通化」「属人化の回避」の3点だ。
まず仕組みの共通化では、ソースコードを共通化するのではなく、仕組み自体を共通化する。命令規制・コーディング規制をESLintに揃える。テストの構成をKarma、mocha、chaiに。タスクランナーの処理はgulp、Yeomanに。プルリクエストのフォーマットをCONTRIBUTING.mdに揃えるなどになる。
2番目のモジュールの共通化については、使っているフレームワークが異なると難しい。ディレクトリ構成をできる限り揃えるだけでも十分効果はある。ユーティリティ関数だけを切り出して、使い回す等は可能だ。
最後の属人化の回避は、プロダクト数が多くなると、担当プロダクトの専任になりがちだ。そこで、定期的に担当者をシャッフルする、別プロダクトをレビューする、別プロダクトのテストを担当するなどの策が有効だ。
まとめとして、言語仕様の未来を見据えて技術を選ぶこと、大規模開発においてはソースコードよりも仕組みや構成を共通化することが大事であること、属人化を回避できるような運用を考えること、の3点を挙げ、柴田氏のパートは終了した。
ヤフーのデータセンターを支える基盤としてOpenStackを採用
セッション後半では、伊藤氏が「Yahoo! JAPANが実践するOpenStackと大規模環境でのコンテナ利用」と題して語った。
OpenStackは、クラウド基盤を構築するソフトウェアの一つだ。NASAとRackSpaceからコードがOpenStackプロジェクトに寄贈され、初回のリリースは2010年。現在も活発に開発が進んでいる。
ひとくちにOpenStackと言っても、インフラ基盤やミドルウェアなどを対象にした様々なプロジェクトがあるが、その中からヤフーは、10個ほどのプロジェクトを利用している。
2015年10月、OpenStack Summitが東京で開催された際には、ヤフーは国内企業として初めてキーノートで発表したという。発表した内容は以下の5つ。
- APIのフォーマットが変わらないことが重要:APIがハードウェアの違いを吸収し、抽象化する。
- 異なる環境であっても同じAPIで動作することが重要:異なるランタイム環境KVM、VM、ベアメタルであっても、同じコンサルティングリソースを提供する目的においては、同じAPIで動作することが求められている。
- インフラのAPIはアプリに近づくことが前提:プラットフォームから見てAPIをインフラよりもアプリ側に近づけることで、より柔軟にアプリケーションを作ることができる。APIのレイヤーで違いを吸収、抽象化する。
- ヤフーはデータセンター抽象化のコア技術としてOpenStackを採用:OpenStackにより、データセンターの抽象化をし、常に新しいハードウェアの導入することが可能になった。
- インフラ部門側からハードウェアライフサイクルを実施することが可能になった:従来インフラ部門は、受け身で動くことが多かったのだが、能動的に新しいものにどんどん替えていくことができるようになった。
ここで伊藤氏は、データセンター抽象化の一例として、オープンハードウェアの採用について話した。OpenStackはインフラ部門側が主導して導入しており、データセンターにおける新たなチャレンジにも使われている。
まず、OpenStack基盤としてOCP(Open Compute Project)を採用した。抽象化することで、ハードウェアプラットフォームの変更を行うのだが、リスクが高いチャレンジにも関わらず問題なく進めることができた。結果、継続的なハードウェアライフサイクルが実現している。物理的な経年劣化があるし、電力対性能という面で見ても古いものは入れ替えていく。この際、海外においてベンダーと直接交渉したことによりスキルが向上し、コスト削減も実現している。
継続的なソフトウェアライフサイクルのために有用なコンテナと、コンテナ利用の注意点
伊藤氏たちは、アプリケーションのレイヤーまで継続的なライフサイクルを実現したいと考えている。ハードウェアだけでは得られるメリットが限られるからだ。ランタイムなどで新しい技術が生まれてきているので、それに併せてソフトウェアの動作環境も変えていきたい。
継続的なソフトウェアライフサイクルを行うためにはまず、実行環境への依存を無くす必要がある。ものによっては環境を選ぶ必要があるが、ほとんどのものは、依存を無くすことができる。加えて実行環境をベアメタル、VM、コンテナに対応する。
望ましいのは、アプリケーションの実行環境をシステムが自動的に提供し、人が選ばないようにすることだ。「リソースの使用が効率化されるので、メリットが大きい」と伊藤氏。
ここで、伊藤氏は下記のスライドを見せながら、KVM、Docker、ベアメタルを比較して見せた。
アプリケーションのレイヤーまで継続的なライフサイクル実現に寄与する期待されるのが、伊藤氏のセッションのもう一つのテーマである、コンテナ(Docker)だ。
コンテナの利点として伊藤氏は次の2点を挙げた。まずは「イメージの管理性」。上手く作れば最軽量で、持ち運びが楽で、デプロイの高速化に効果を発揮する。レイヤーを重ねなくても高いメリットがある。
さらに「性能劣化が少ない」ということ。エミュレーションしていないのでVMより早く、計算資源に対する実性能が高いため高集約であることも利点だ。
一方、コンテナの注意点についても述べられた。まず「VMからコンテナへの移行は難しい」ということ。なぜならイメージサイズが大きいと、メリットが薄いからだ。可搬性が下がっていくし、詰め込みすぎないのがポイントだ。
次に「ネットワーク機能の違い」があるということ。複雑なアプリケーションになるほど難しく、コンテナ独自のネットワーク機能も多い。実環境においてはCalicoなどの純粋なIPネットワークを重視するのだという。
最後の注意点として「ストレージ機能の違い」もあるという。コンテナに永続的にデータを持たせることは考えるべきではなく、最近ではDockerボリュームに対応したストレージアプライアンスが出ている、という。データはSwift/S3とDocker Volumeを使い分けることにより、コンテナでも安心してデータを預けることができるのだそうだ。
何でもコンテナにすればいいかと言えばそうでもない、コンテナにも向き不向きがある。まず、モノシックなアーキテクチャーには不向きである。コンテナへの重量級のデプロイはメリットが無いケースが多い。従って、コンテナにするなら、軽量化・分割化を行う必要がある。
一方、マイクロサービスもコストが高い、という。オーバーヘッドもあり、管理対象が増えてくる。トラブルシュートが大変なので、ログと、メトリクスの集約が必須だ。メトリクスも俯瞰できないと意味が無いのだそうだ。
また、コンテナを手でデプロイするのは大変、と伊藤氏。大量にあるコンテナを手でデプロイするのは、事実上不可能だ。そのため、デプロイとオーケストレーションを自動でやる必要があるのだそうだ。
そしてデプロイ自動化をするなら、前段も含めて自動化する必要がある、という。いわゆるCIの実現だ。アプリケーションの作り方から変えていかなければならず、コンテナ導入の前には揃えるものが多いのだという。
最後に伊藤氏は「コンテナは、継続的ライフサイクルの実現に適している。コンテナ活用の手助けをしていきたい」と語り、セッションを締めくくった。
お問い合わせ
ヤフー株式会社