1.5K Views
November 27, 17
スライド概要
SpringFest2017の以下のセッションの資料です。
Yahoo! JAPANのコンテンツプラットフォームを支えるSpring Cloud Streamによるマイクロサービスアーキテクチャ
http://springfest2017.springframework.jp/
2023年10月からSpeaker Deckに移行しました。最新情報はこちらをご覧ください。 https://speakerdeck.com/lycorptech_jp
Yahoo! JAPANのコンテンツプラットフォームを支える Spring Cloud Streamによるマイクロサービスアーキテクチャ 2017年11月24日 ヤフー株式会社 鴨志田 智弥 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
自己紹介 • 鴨志田 智弥 • ヤフー株式会社 メディアグループ メディアカンパニー プラットフォーム開発本部 • 経歴 • 2009年 新卒入社 • 2009年〜 Yahoo!ニュース • 2016年9月〜 コンテンツプラットフォーム Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
アジェンダ • Yahoo! JAPANとコンテンツ • コンテンツプラットフォームでのSpringの採用事例 • 既存システムの課題と新システムの設計 • システム概要と詳細 • 良かったこと、悪かったこと Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Yahoo! JAPANとコンテンツ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Yahoo! JAPANとコンテンツ 天気 路線の 遅延情報 試合情報 ニュース Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
提供コンテンツ 提供社 Yahoo! JAPAN 個人 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
提供コンテンツ • ニュース記事、コラム • 天気、地震情報 • 株価 • 試合情報、試合のスコア • 動画 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
コンテンツプラットフォームでの Springの採用事例の紹介 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
アジェンダ • Yahoo! JAPANとコンテンツ • コンテンツプラットフォームでのSpringの採用事例 • 既存システムの課題と新システムの設計 • システム概要と詳細 • 良かったこと、悪かったこと Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
コンテンツプラットフォーム • 提供コンテンツの入稿・配信のプラットフォーム • 1stリリースは記事コンテンツがターゲット • 開発に至った背景 • 旧記事入稿プラットフォームがレガシーなためリニューアル • 2009年から稼働 • PHP、Perl、C Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
旧システムの辛い所 • 巨大なモノリシックなアプリケーション • 大きすぎてリファクタリングできない • さらにテストコードが無い&書きづらい • その結果レガシーなコードのまま • 環境や依存のバージョンアップの時はひたすらエラーを潰す Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
旧システムの辛い所2 • 実機&VMで動いている • マスタ/スタンバイ構成で冗長性有り • 簡単にスケールアウトできないので常にリソースは確保している 常に確保 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
旧システムの辛い所3 • アーキテクチャが古いのでPaaSなどへの移行は難しい • IPアドレスに依存していたり • 処理自体はテキスト処理などで非常にシンプル Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
新システムの設計 • マイクロサービスアーキテクチャ • システムを細分化して柔軟に対応できるようにしたい • 同期的に処理しなくて良い部分は非同期で処理したい Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
新システムの設計2 • Java • プラットフォームなのでなるべく不具合無くリリースしたい • 静的型付け、コンパイラで検知 インタープリタ型言語 動的型付け PHP コンパイラ型言語 静的型付け Java Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
新システムの設計3 • PaaS • 運用コストを下げたい • リソースを有効活用したい • 重大ニュースなどで負荷が大きく上昇するため素早くスケールアウ トしたい PaaS Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
新システムの設計4 • Spring Boot • Javaでマイクロサービスするなら鉄板 • フルスタックで機能も豊富 • 社内PaaS環境のPivotal Cloud Foundryとの相性も良い Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
アジェンダ • Yahoo! JAPANとコンテンツ • コンテンツプラットフォームでのSpringの採用事例 • 既存システムの課題と新システムの設計 • システム概要と詳細 • 良かったこと、悪かったこと Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
システム構成 入稿サービス 解析処理 入稿API データ保存 処理済みデータ (Cassandra) 入稿データ (MySQL) 旧PF レガシーアダプタ 参照サービス バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
システム構成 入稿サービス 入稿API 非同期 データ受付 確認 データ保存 入稿データ (MySQL) Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
システム構成 解析処理 解析 入稿データ (MySQL) Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
システム構成 データ保存 データ保存 更新通知 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. 参照サービス 処理済みデータ (Cassandra)
システム構成 ストレージに保存 バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
システム構成 入稿API フォーマット変換 旧PF レガシーアダプタ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
システム構成補足 • 現在約20サービスほど • オンプレ環境に構築したPivotal Cloud Foundry上で稼働 • Spring Bootと一部Node.js • 非同期部分はPulsarとSpring Cloud Stream • MySQL、Cassandra、内製のS3互換ストレージ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Pivotal Cloud Foundry • Pivotal社製のCloud Foundry • PaaS • コマンド1つでアプリケーションが立ち上がる $ cf push -p build/libs/hoge-1.0.0.jar 数分後 https://hoge.XXXX.yahoo.co.jp/ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Pivotal Cloud Foundry Spring Boot Actuator連携 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Apache Pulsar • Pub-Subメッセージングシステム • Yahoo! Inc.製で今はApache Incubator • 特徴 • 高パフォーマンス、高スケーラビリティ • マルチテナント • 複数DC間でのレプリケーション Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Spring Cloud Stream • Springでメッセージングシステムを使うフレームワーク • 公式ではRabbitMQとKafkaをサポート • Pulsarは公式ではサポートされていないので内製対応 Producer Message Broker Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. Consumer
Source / Processor / Sink Processor Source binder Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. Sink
Source / Processor / Sink 入稿サービス 解析処理 入稿API データ保存 Processor Source 処理済みデータ (Cassandra) 入稿データ (MySQL) 旧PF レガシーアダプタ 参照サービス Sink バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
依存の追加
ext {
springCloudVersion = 'Dalston.SR4'
使うbrokerのものを指定
}
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-stream-rabbit')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-actuator')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
その他はお好みで
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
依存の追加 RabbitMQの場合 org.springframework.cloud:spring-cloud-starter-stream-rabbit Kafkaの場合 org.springframework.cloud:spring-cloud-starter-stream-kafka Pulsarの場合(自作) com.example:spring-cloud-starter-stream-pulsar Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sourceの実装 @SpringBootApplication @RestController public class SourceDemoApplication { @PostMapping public void send(@RequestBody Map<String, String> message) { // ここに送信する処理を書く } } public static void main(String[] args) { 〜略〜 } Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sourceの実装 @SpringBootApplication @RestController @EnableBinding(Source.class) public class SourceDemoApplication { @PostMapping public void send(@RequestBody Map<String, String> message) { // ここに送信する処理を書く アノテーションを追加 } } public static void main(String[] args) { 〜略〜 } Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sourceの実装
@SpringBootApplication
@RestController
@EnableBinding(Source.class)
public class SourceDemoApplication {
@Autowired
private Source source;
@PostMapping
public void send(@RequestBody Map<String, String> message) {
// ここに送信する処理を書く
インジェクション
}
}
public static void main(String[] args) { 〜略〜 }
Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sourceの実装
@SpringBootApplication
@RestController
@EnableBinding(Source.class)
public class SourceDemoApplication {
@Autowired
private Source source;
送信処理
@PostMapping
public void send(@RequestBody Map<String, String> message) {
source.output().send(MessageBuilder.withPayload(message).build());
}
}
public static void main(String[] args) { 〜略〜 }
Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sourceの設定 spring.rabbitmq.addresses=localhost:5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest broker固有の設定 spring.cloud.stream.bindings.output.destination=foo_topic spring.cloud.stream.bindings.output.contentType=application/json binderの設定 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
broker固有の設定 spring.rabbitmq.addresses=localhost:5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest RabbitMQの例 spring.cloud.stream.kafka.binder.brokers=localhost spring.cloud.stream.kafka.binder.defaultBrokerPort=9092 spring.cloud.stream.kafka.binder.zkNodes=localhost spring.cloud.stream.kafka.binder.defaultZkPort=2181 Kafkaの例 spring.cloud.stream.pulsar.binder.clusterUrl=pulsar://localhost:6650 Pulsarの例(イメージ) Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Source側のbinderの設定 送信先トピック spring.cloud.stream.bindings.output.destination=foo_topic メッセージのシリアライズ方法 spring.cloud.stream.bindings.output.contentType=application/json JSONがオススメ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sinkの実装 @SpringBootApplication public class SinkDemoApplication { public void receive(Map<String, String> data) { // ここに受信したメッセージの処理を書く } } public static void main(String[] args) { 〜略〜 } Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sinkの実装 @SpringBootApplication @EnableBinding(Sink.class) public class SinkDemoApplication { public void receive(Map<String, String> data) { // ここに受信したメッセージの処理を書く アノテーションを追加 } } public static void main(String[] args) { 〜略〜 } Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sinkの実装 @SpringBootApplication @EnableBinding(Sink.class) public class SinkDemoApplication { @StreamListener(Sink.INPUT) public void receive(Map<String, String> data) { // ここに受信したメッセージの処理を書く } } public static void main(String[]アノテーションを追加 args) { 〜略〜 } Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sinkの実装
@SpringBootApplication
@EnableBinding(Sink.class)
public class SinkDemoApplication {
@StreamListener(Sink.INPUT)
public void receive(Map<String, String> data) {
System.out.println("Received : " + data.toString());
}
}
public static void main(String[] args) { 〜略〜 }
処理を書く
Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sinkの設定 spring.rabbitmq.addresses=localhost:5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest broker固有の設定 spring.cloud.stream.bindings.input.destination=foo_topic spring.cloud.stream.bindings.input.group=bar_group binderの設定 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Sink側のbinderの設定 受信トピック spring.cloud.stream.bindings.input.destination=foo_topic ConsumerGroup名 spring.cloud.stream.bindings.input.group=bar_group Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
ConsumerGroup 設定しない場合はそれぞれに同じメッセージが届く AAA BBB CCC AAA BBB CCC AAA BBB CCC AAA BBB CCC Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
ConsumerGroup 設定した場合はグループ内のどれか1つにだけメッセージが届く AAA BBB CCC AAA BBB CCC Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
メリット • 抽象化されているのでロジックに集中できる • 違うbrokerに乗り換える場合は設定の差し替え程度で済む • Springの他の機能との連携 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Spring Boot Actuator連携 接続先のbrokerのヘルスチェック { "status": "UP", 〜中略〜 "rabbit": { "status": "UP", "version": "3.6.12" }, "binders": { "status": "UP", "rabbit": { "status": "UP", "binderHealthIndicator": { "status": "UP", "version": "3.6.12" } } } } Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Spring Cloud Streamのテスト • テストツールが提供されている • spring-cloud-stream-test-support Sourceテストコード assert Sinkテストコード モック Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. assert
実装後に出てきた課題 • 処理の流れがわかりにくい • 想定よりスループットが出ない • エラー時の処理 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
処理の流れがわかりにくい • マイクロサービスの処理の流れはわかりにくい • どこでエラーが起きたのか? • どこがボトルネックになっているのか? ? エラー! Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Spring Cloud Sleuth リクエストにトレース用のユニークなIDを付与する ID発行 abc abc X-B3-TraceId: abc Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. abc
Spring Cloud Sleuth • 自動で追跡用のIDが発行・付与 • 自動でログにも出力 • トラブル時はTraceIDで検索すればOK Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin TraceIDを可視化するツール Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin 入稿サービス 解析処理 入稿API データ保存 参照サービス 処理済みデータ (Cassandra) 入稿データ (MySQL) Zipkin 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
Zipkin Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin 入稿サービス 解析処理 入稿API データ保存 参照サービス 処理済みデータ (Cassandra) 入稿データ (MySQL) ① 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
Zipkin ① Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin 入稿サービス 解析処理 入稿API データ保存 参照サービス ② 処理済みデータ (Cassandra) 入稿データ (MySQL) ① 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
Zipkin ① ② Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin 入稿サービス ② 解析処理 入稿API データ保存 参照サービス ③ 処理済みデータ (Cassandra) 入稿データ (MySQL) ① 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
Zipkin ① ② 同期処理終了 ③ 続きがある Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin 入稿サービス ② 解析処理 入稿API データ保存 参照サービス ④ ③ 処理済みデータ (Cassandra) 入稿データ (MySQL) ① 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
Zipkin ① ② ③ ④ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Zipkin 入稿サービス ② 解析処理 入稿API データ保存 ④ ③ 入稿データ (MySQL) 参照サービス ⑤ ⑥ 処理済みデータ (Cassandra) ① 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
Zipkin ① ② ③ ④ ⑤ ⑥ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
想定よりスループットが出ない • 負荷テストしてみたら非同期部分が遅い • Sinkの同時処理数が1だった・・・ 必ず設定する spring.cloud.stream.bindings.input.consumer.concurrency=10 デフォルトは1 適度に増やす Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
エラー時の処理 • 処理の途中でエラーになったメッセージが行方不明に • Pulsarは再送までの時間を設定しないと再送してく れなかった・・・ • brokerの仕様は把握しておくことが大事 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) • 非常災害時でもサービスを継続する必要がある • 西日本と東日本のDCに分散構築 西日本クラスタ 東日本クラスタ GSLB Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 西日本 MySQL 東日本 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 GSLB Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 MySQL GSLB Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 MySQL Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
BCP(事業継続計画) 仮に片方のDCが停止しても問題ないように設計 MySQL Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
利用サービス例 • Yahoo! JAPANアプリ • ニュースフィード部分などで利用 • Vespaでコンテンツのレコメンデーション 更新検知& データ取得 インデックス 更新 更新通知 更新処理 Index アプリBE コンテンツ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
アジェンダ • Yahoo! JAPANとコンテンツ • コンテンツプラットフォームでのSpringの採用事例 • 既存システムの課題と新システムの設計 • システム概要と詳細 • 良かったこと、悪かったこと Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Java/Springで良かったこと • フルスタックで機能も豊富なのでロジックに集中できる • マイクロサービスに必要なものが揃っている • テストコードが書きやすい • Mockito • MockRestServiceServer • REST Assured Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
非同期部分は機能拡張が簡単 購読を増やすだけなので既存システムへの影響は少ない ・・・ ・・・ 既存アプリケーション ・・・ この線を増やせばOK 追加アプリケーション Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
非同期部分は機能拡張が簡単 入稿サービス 解析処理 入稿API データ保存 参照サービス 処理済みデータ (Cassandra) 入稿データ (MySQL) 実は後から追加 旧PF レガシーアダプタ バッチ処理用 データ保存 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ストレージ Hadoop
1つの機能がシンプル • 機能が小分けになっているので実装がシンプルに • APIやメッセージを挟んでいるので疎結合 • 修正やレビューは見る範囲が狭い方が良い 🔥 数万行 ☀ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. 数百〜数千行
1つの機能がシンプル • 複数人での並行開発も容易 • コンフリクトも起こりにくい コンフリクト地獄 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved. ☀
新たな課題 • メモリの使用量が他の言語に比べ多め • マイクロサービスの管理が大変 • 便利なソリューションも提供されているが・・・ • 依存ライブラリのバージョンを上げるのも一苦労 • 開発メンバーが少ないのも要因の1つ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
今後の展望 • Kotlinの検討 • マイクロサービス系のツールのさらなる導入 • 検証が追いつかず導入を見送ったものがいくつかある • 新しく増えたものも随時検討 • Spring Cloud Skipperなど Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
まとめ Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
まとめ • 既存システムの課題がSpringとマイクロサービスで 大きく改善できた • マイクロサービスをやるならSpring Cloud Stream が便利 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.
Javaエンジニア 積極採⽤中!! ヤフー 採用 Copyright © 2017 Yahoo Japan Corporation. All Rights Reserved.