【atte FeSセミナーレポート②前編】「GoとGAEは最高のWebアプリ開発手段」「PaaS時代が本格的に始まった」…ソウゾウのサーバーサイドエンジニア鶴岡氏が「メルカリ アッテ」の開発を紹介

メルカリのグループ会社であるソウゾウは、地域コミュニティアプリ「メルカリ アッテ」のリリースを記念して、2週連続月曜日にアッテリリースまでの裏側を語る「atte FeS」を先日完成したばかりのオフィス新イベントスペースで開催。本稿では、2週目の開催となる「Go・Swift開発編」について紹介する。今回はその前編で第一部の模様をお伝えしよう。

attefes201
メルカリのグループ会社であるソウゾウは、地域コミュニティアプリ「メルカリ アッテ」のリリースを記念して、4月11日・4月18日の2週連続月曜日にアッテリリースまでの裏側を語る「atte FeS」を先日完成したばかりのオフィス新イベントスペースで開催。

ソウゾウは、2015年9月、メルカリのグループ会社として、「Building next ordinary(ありそうでなかったをソウゾウする)」をミッションに設立された会社。3月17日より、地域コミュニティアプリ「メルカリ アッテ」を提供している。

イベントは、以下のような構成であった。本稿では、2週目の開催となる4月18日(月)の「Go・Swift開発編」について紹介する。本サイト「Pedia News」では、イベントの模様を前編・中編・後編に分けてお伝えしたい。今回はその前編で第一部の模様をお伝えしよう。

* 第一部 アッテ開発の技術:Golang と Google Cloud Platform
* 第二部 アッテ開発の技術:Swift と RxSwift
* 第三部 アッテ開発の技術:アッテの設計と開発フローの変遷

### ソウゾウ初の開発者向けイベント
イベント開始直後、早速株式会社ソウゾウのサーバーサイドエンジニアである鶴岡達也氏が乾杯の挨拶をした。

鶴岡氏は、今回のイベント「atte FeS」について、

ソウゾウは、去年の9月に設立して開発が10月からゆっくり始まって、最近「アッテ」をようやくリリースした。今日は、「アッテ」のリリース以来、初めて開発者の方を集めてイベントを開催する。「メルカリ」の開発も初期から関わっていて、リリースから約1年後に初めてPHPカンファレンスで発表した。今回「アッテ」でおもしろいことは、セッションのタイトルをみてわかるように、Goを使っていたり、Google Cloud Platformを使っていたり、iOSはSwiftを使っていたり、「メルカリ」とは異なる新しいものに挑戦した。

と述べ、「メルカリ アッテ」で「メルカリ」と異なる新しい挑戦を試みたことを明かした。

### 「メルカリ」初期開発メンバーが語る「アッテ」の開発
第一部では、「アッテ開発の技術:Golang と Google Cloud Platform」と題して、鶴岡氏が登壇。鶴岡氏は、メルカリ創業時からバックエンドのエンジニアリングを担当し、メルカリを技術的に支援。主としてAPIの開発を取りまとめると共に、エンジニア全体の開発環境作りにも注力。現在、ソウゾウのサーバサイドチームでサーバーサイドエンジニア兼マネージャーとして開発を担当する。

冒頭、鶴岡氏は、Go言語とGoogle App Engineで「アッテ」を開発したと説明した上で、

今回「アッテ」でGoとGoogle App Engineを使って非常に良かった。Goは非常に有力なウェブアプリ開発手段だと思う。また、Google App Engineに触れて、PaaSの時代が本格的に始まってきたと感じた。PaaSエンジンは今までもHerokuなどあったが、その中でGoogle App Engineが突き抜けて優秀だと思う。Google App Engineは毎日のようにアップデートもされていて非常に便利。

と述べ、GoとGoogle App Engineの魅力を語った。

### GoとGAEを選んだ理由
まず鶴岡氏は、「Why Go? Why GAE?(なぜGoにしたか?なぜGAEにしたか?)」について、①アプリケーションの要件、②メルカリではなくソウゾウ、③Googleの動き、④プロダクト開発にフォーカスの4点を挙げた。

①の「アプリケーションの要件」について、鶴岡氏は、

何を作るかによってどの技術を使うかは決まってくる側面がある。そこで「アッテ」は開発に入る前に今作ろうとしているアプリがどのような機能をもつかを洗い出した。

と述べ、「アッテ」の機能的な側面として、

スマホのアプリがあってそのバッグエンドにサーバーがいるという構成なのでJSON APIがあったり、静的コンテンツ配信(HTML/CSS/JS)、動的コンテンツ生成、データベース(永続化、クエリ)、非同期で大量なデータを処理したりするためにキュー処理、「メルカリ」も「アッテ」も検索が重要で検索(キー、全文検索、位置、予測変換)、画像アップロードと配信、メール配信、Push通知、データ分析がある。

と取り上げ、さらに非機能的な側面として、

一つ目はグローバル。ソウゾウだけではなくメルカリ側でも共通していることだが、日本だけではなくて複数リージョンでサービスを展開したいと考えている。特に今回「アッテ」に関しては、データベースもグローバルにひとつだけを目指している。「メルカリ」の場合は、US版と日本版を配信しており、「メルカリ」というコードは同じものだが、国を超えて取引することがないのでデータベースはリージョン毎に分けている。「アッテ」は「メルカリ」と状況が異なるので、GoogleやFacebookのようにグローバルで世界中にひとつだけのデータベースを目指した。二つ目は大規模アプリケーション。大規模アプリケーションの定義はDAUで数千万人規模を扱えること。現在、「メルカリ」が日米で3,500万ダウンロード、ピーク時毎分120万リクエスト、扱うデータ量は億単位なので、当然「メルカリ」レベルの規模を実現できることが前提にあった。また、今後の展開として、グローバルでDAUで数千万になることを踏まえ、それに対応できるものを作りたいと思った。三つ目はハイスケーラブル。ハイスケーラブルとは、立ち上げた時から最後まで一貫したアーキテクチャーにしたいということ。「メルカリ」の開発初期は僕が最初のエンジニアの1人で、PHP、Linux、MySQLを使ってアーキテクチャーを考えて作った。とにかく人手もなかったので、第一世代としてハイエンドなサーバー1台に全部を詰め込もうと考え、アーキテクチャーを開発した。当時は、その時点でのハイエンドなアーキテクチャーにすれば、とりあえず数カ月間で10万~数十万ユーザーまでは対応できると思っていた。実際は、1~2カ月でいっぱいになってしまってパンクしそうになった。その結果、一般的なマスタースレーブ構成に変更したり、ウェブサーバーを増やしたり、わずかな期間でアーキテクチャーがころっと変わってしまった。今では、メルカリにSRE(Site Reliability Engineering)チームがあり、その時点でベストなものに対応している。今回「アッテ」では、「メルカリ」のアプローチではなく、一度立ち上げたら最初のアプローチのままでずっと行きたいと思っている。

と説明した。

②の「メルカリではなくソウゾウ」について、鶴岡氏は、

ソウゾウはメルカリの100%子会社だが、会社を分けているのでメルカリの縛りを受ける必要がない。もちろん、同じ技術を選べば人材の流動性が上がるので同じ技術を選ぶという選択肢もあるが、今回はあえて選ばなかった。

と述べ、ソウゾウでは戦略的にメルカリと異なるアプローチに試みたことを強調した。

けて、鶴岡氏は、メルカリが今の技術になった理由について、

* プロダクトのリリースはすべてに優先される
* 限られたリソース(人、お金、時間)
いま集められる可能性の高いエンジニアは?

を考慮して保守的・堅牢的に考えたものであると述べた上で、ソウゾウが今回の技術を採用した理由について、メルカリが大きく成長していることもあり、

* メルカリだけでは生み出せない新しい価値を出したい
* 潤沢なリソース
3年後にもエンジニアにとって魅力的な場所であるためには?

を考えて、多様性と技術の開拓をテーマに決めたことを明かした。

③の「Googleの動き」について、鶴岡氏は、

Googleの動きがGCP(Google Cloud Platform)を選んだ理由のひとつ。最初は「アッテ」のインフラを考える時に「メルカリ」と同じオンプレミスやAWSを考えていたが、様々な情報を集めていく中、GCP上でアプリケーションを作った人から良い成果を出せたという情報を得た。そこで、すぐにGoogleの担当者を紹介してもらい、去年(2015年)の10月頃からGCP/GAEの採用可能性を1ヶ月ほど検証した。GCP/GAEに触れた結果、Googleがきめ細かなサポート体制をとっていることが分かった。Googleは約5年前にGoogle App EngineやDatastoreを出していたが、当時は非常に特殊な雰囲気を出していてサポートも英語のみだった。今は、アマゾンがAWSの東京リージョンを出した時のように、Googleの中にGCP/GAEのソリューションリージョン担当者がいてサポートしてくれる体制がある。さらに、GCPのコンソールを触ると、2日に1回くらいの非常に細かい頻度でアップデートされている。Googleが多くのリソースを投下していることが分かった。

と述べ、GCP/GAEを検証してGoogleの本気度を感じたことを語った。

④の「プロダクト開発」について、鶴岡氏は、

プロダクト開発とは、エンジニアの多くが開発言語やインフラ特有の問題に時間を使うのではなくてプロダクトの開発に集中できる時間が理想、という観点を示したもの。Goは、メルカリでGaurun(Push配信ミドルウェア)などの実績があり、生産性とパフォーマンスが高くてポテンシャルの高さを感じていた。一方で、Goはミドルウェアを書いているスピードを見る限り生産性が高いが、Webの生産性が分からなかった。そこで、ミドルウェアだけではなくWebでも高い生産を出せるかを検証した。実際Goに触れて、LLと異なる生産性の出し方ができると感じた。数時間で書いたり、書いて捨てたりするなら、PHP、Perl、Rubyの方が速いが、1週間あけてまたもう一度触るような長い目で見ると、Goは型とコンパイルの影響もあって生産性が高い。今回初めてGoに触れたので、頻繁に設計を見直しするなどしたが、関数を変えたり、クラスを変えたり、構造体を変えたとしても、コンパイルエラーが出てそれをひとつずつ修正して再度動かせば動く。Goはコンパイルが通ればOKなので、非常に動かしやすいと思う。

と述べた。さらに、鶴岡氏は、Goには言語自体にチーム開発のための仕組みが入っていてチーム開発のしやすい言語であると述べた上で、

例えば、go fmt(フォーマット)はそれ自体が言語の一部。フォーマットもパッケージの並び順がA~Zなど、それに従ってそれが正しいというルールが細かく決まっている。また、「アッテ」では、goでコードを書いてgo doc(ドキュメント)を生成している。ドキュメントサーバーを用意して、go docは常にマスターから一定間隔でプルして最新ドキュメントをみている。これにより、APIドキュメントを作らずとも、クライアント側がgo docを見てAPIを作れる。

と述べ、チーム開発で利点も多いことからGoを選んだと説明した。

また、鶴岡氏は、「GAE」について、

GAEはGCPプロジェクトの中にある1つの機能で、1つのプロジェクトに1つのApp Engineを持つ。App Engineの中にはアプリケーションが稼働するインスタンスがあり、検索機能やキューも提供される。データベースはDatastore、データ分析はBigQuery。GAEでは、モジュールとバージョンというおもしろい概念を持つ。「アプリケーションを複数の環境にデプロイできる」ことを「バージョン」と呼んでおり、バージョンに対してトラフィックの振り分けを設定できる。さらに、バージョンは並行して1つのApp Engine上で60個まで置ける。これにより、理想的なBlue/Greenデプロイができる。また、GAEは、インスタンスのオートスケールという機能を持つ。これは、App Engineにアプリケーションをデプロイするだけでオートスケールするというもので、アクセスがなければインスタンスは立ち上がらずにアクセスがあった場合に起動する。インスタンスはVMではなく軽量なコンテナ。「アッテ」の場合は、Goのインスタンスなら200ms以下で起動する。そうすると、仮に「メルカリ」からの流し込みや大規模な広告プロモーションがあった場合でも、何もせずとも瞬時にインスタンスが増えて処理できる。さらに、GAEは、統合されたリアルタイムのログ機能を持っており、ビッククエリで取りこぼしなしで検索できる。GAEでは、ログ画面からトレース機能を持っており、Googleが自動で1リクエストの中でどういう処理をしているかをサンプリングしてくれる。このように、GAEは至れり尽くせりで非常に便利。

と述べ、「GAE」の魅力を語った。

### 初めてのNoSQLモデル
次に鶴岡氏は、「分散システムのためのDatastore」について、「アッテ」の開発初期を振り返り、「アッテ」では、①RDBで伝統的なMaster/Slaveモデル、②スケーラビリティを重視したNoSQLモデルの二案を検討していたと述べた。

鶴岡氏は、①のRDBで伝統的なMaster/Slaveモデルについて、

実績十分で確立された手法。とはいえ、DBをゼロから立ち上げてスケールさせていくのは大変。高度な知識がないと厳しい。
* 大規模なデータになるほどRDB本来の持ち味が生かせなくなる。異なるDBテーブルとのトランザクションができない。JOINが限定的。

と考える中、②のスケーラビリティを重視したNoSQLモデルについて、

データストアはNoSQLのデーターベースDatastore。そのため、実用的なACIDは諦めるしかないが、その代わりに極めて高いスケーラビリティをもつ。

と考え、②のスケーラビリティを重視したNoSQLモデルを採用したと述べた。

続けて、鶴岡氏は、「スケーラビリティを重視したNoSQLモデルの採用」について、

「アッテ」では、グローバルでサービスを展開したい、DAUを数千万という規模を目指したい、ということを考えており、さらに、メンテナンスのリソースを持っていなかったので、NoSQLモデルのDatastoreを選ぶべきだと思った。NoSQLはハードルが高そうに思われがちだが、GmailやYouTubeのようなサービスのデータはRDBではなくBigTableに保存されており、NoSQLの実績はGoogleが実証済み。だからこそ、今回「アッテ」も思い切ってDatastoreを利用しようと思った。もちろん、長い間慣れ親しんできたRDBではなくてNoSQLを選ぶ決断は難しいが、グローバルレベルの大規模サービスを作るためにNoSQLを選ぶ決断をしようと考えた。

と説明した。

鶴岡氏は、「DataStoreの特徴」について、メリットとして、

* 極めて高いスケーラビリティ
* 永続化できるデータ(エンティティ)の数に制限はない
* 永続データがどれだけ増えても取得と追加の速度は劣化しない(1件でも10件でも同じ)
* 同一エンティティでなければ制限なしの並列書き込みがいくらでもできる
* 極めて高い可用性
* ダウンタイムなし

を取り上げ、デメリットとして、

* BigTableより高機能とはいえプリミティブ
* 限定された条件でしかACIDトランザクションがサポートされない
* JOINがない、集約関数がないなど

を取り上げた。

また、鶴岡氏は、「Datastoreを使うときに考えること」について、

* RDBのパターンを当てはめることはできない
* トランザクションなしで複数の値を一貫性を持たせて更新。一貫性が無くなることを許容する
* オートインクリメント(単調増加する数値の採番)
* Datastoreの機能だけでスケールする採番は実装できない
* 分散システムでのオートインクリメントの考え方が必要

を取り上げ、「アッテ」の開発を通じて学んだDatastore利用時の注意点を述べた。

### 「アッテ」のアーキテクチャーの裏側
そして、鶴岡氏は、「Webアプリケーションのアーキテクチャー」について、

「アッテ」のアーキテクチャーは、複数個のモジュールで構成されている。API、Web、CStoolなどのモジュールに分かれ、モジュールはそのままデプロイ単位、単一のリポジトリ(monorepo)であり、多くのコードは共通している。「アッテ」では、APIがJSON RPC2.0で、WebとCS ToolはHTMLを動的生成している。また、アプリケーション層、ドメイン層、UI層、インフラ層の4層に分かれており、各モジュールはUI層の違いとして表現している。さらに、設計の方針は、GAEへ依存している。これにより、GAEの機能をフルに活用することで、スケーラビリティや可用性の恩恵を受けている。当然、強力にロックインされることになるが、ささやかな抵抗でドメイン層(ビジネスロジック)とインフラ層を分けて、ドメイン層をGAEに依存しないようにしている。そのため、Datastoreを利用するRepositoryをAWSのDynamoDBを利用するRepositoryに差し替えようと思えば差し替えられる。大切なことは、Goの考え方に従うことだと思う。Goはいろんなことが決められている。Goでは、細かいことも決まり通りに書くと非常に楽だ。そして、「アッテ」では、1つのレポジトリに全てを入れている(monorepo)。API、Web、CStoolのような境界が異なりそうなプロジェクトを、単一プロジェクトとして扱っている。これにより、共通部品を使いやすくて依存管理関係が非常に簡単になり、横断的なコードの改修をしやすくなる。

と述べ、GoとGAEが非常に有力なWebアプリ開発手段でPaaSの時代が本格的に始まってきたことを強調した。

「メルカリ アッテ」App Store

メルカリのエンジニアブログ

メルカリ・ソウゾウの採用情報はこちら