Upload
yusuke-ikeda
View
5.531
Download
0
Embed Size (px)
Citation preview
CyberAgent, Inc. All Rights Reserved
Report to Spring Developer from CyberAgent
自己紹介
● 池田 裕介(@yukung)
● 株式会社サイバーエージェント 技術本部
● サーバサイドエンジニア
● Ameba スマートフォンプラットフォームのAPI設計や
運用を担当Java や Groovy の
コミュニティによく出没します
アジェンダ
● Ameba スマートフォンプラットフォーム
● 抱えていた問題
● 解決策としての Spring Boot と Docker
● 導入結果
● Spring Boot + Docker 3分クッキング
CyberAgent, Inc. All Rights Reserved
Ameba スマートフォンプラットフォーム
Ameba スマートフォンプラットフォーム
Ameba スマートフォンプラットフォーム
● スマホ向けコミュニティサービス+ソーシャルゲームのプ
ラットフォーム
● 2012年4月スタート
● 延べサービス数
○ 約300サービス(2015年8月時点)
Ameba 上のサービス提供フロー
ディベロッパー
App App App
2.開発Ameba Developer Center 1.登録
3.申請
プラットフォームで提供するサービスの情報を集約・管理し、審査や公開を行う 5. 公開
認証システム
課金システム
分析クラスタ
ソーシャルグラフAPI
Ameba スマートフォンプラットフォーム
4. データ連携
CyberAgent, Inc. All Rights Reserved
Ameba Developer Center
Ameba Developer Center
サンドボックス環境の提供
Ameba Developer Center の主な役割
ディベロッパー申請・契約
提供アプリケーションの審査・公開・停止
API 仕様・規約等の各種ドキュメントの提供
各種KPIレポートの提供(PV, DAU/MAU, 消費額など)
プラットフォームからのお知らせ・ニュース
障害情報・システムステータスの開示
問い合わせフォーム
サンドボックス環境の提供
ディベロッパー申請・契約
提供アプリケーションの審査・公開・停止
API 仕様・規約等の各種ドキュメントの提供
各種KPIレポートの提供(PV, DAU/MAU, 消費額など)
プラットフォームからのお知らせ・ニュース
障害情報・システムステータスの開示
問い合わせフォーム
運用に問題があった場合の影響
ディベロッパーの業績に影響
正確なデータ処理
安定したサービスの提供
障害からの迅速な復旧
CyberAgent, Inc. All Rights Reserved
抱えていた問題
保守・運用コストの増大
設定やプロビジョニングの暗黙知化・属人化
保守・運用コストの増大
● サービスのレガシー化
○ フレームワークがメンテされていない
○ 積み重なった場当たり対処
● 冗長なシステムアーキテクチャのオーバーヘッド
設定やプロビジョニングの暗黙知化・属人化
● フレームワークやミドルウェアの設定値がアヤシイ
○ 一貫性がない
● 秘伝のタレ化した Chef cookbook やデプロイスクリプト
○ 怖くて sudo chef-client 叩けない
増え続ける技術的負債
CyberAgent, Inc. All Rights Reserved
リファクタリングしよう!
現チーム構成
Ameba Developer Center
サーバサイドエンジニア
他サービス他サービス
インフラエンジニア
フロントエンドディベロッパー デザイナー
ディレクター
サーバサイドエンジニア
フロントエンドディベロッパー
サーバサイドエンジニア
デザイナー
ディレクター
インフラエンジニア
1人 ><
昔は居たんだけどね…
兼務です!
https://www.flickr.com/photos/cozycozy/4300869920/
Ameba Developer Center の主要スキルセット
● サーバサイド Java(REST API)
○ 内製フレームワーク
● Node.js(Web UI)
○ Express フレームワーク
● フロントエンド
○ Jade, Stylus, jQuery…
所属組織のスキルセット
● 諸事情により Java エンジニアが多い
● システムの特性上、それ自身は利益を上げない
○ 内製フレームワークの学習コスト
○ 外注は難しい…
● では内製?
○ Node.js と Java 両方のスキルが必要
リソースという制約
増えない仲間
CyberAgent, Inc. All Rights Reserved
困った…
アプリケーション用データベース
外部向けAPI サーバ
KPI 取得用API
認証システム
全体アーキテクチャ
ソーシャルグラフAPI
課金システム
経理システム
社内向け管理画面
集計用バッチサーバ
社内向けAPI サーバ
Ameba Developer Center
ディベロッパー向け画面
アプリケーション用データベース
外部向けAPI サーバ
KPI 取得用API
認証システム
全体アーキテクチャ
ソーシャルグラフAPI
課金システム
経理システム
社内向け管理画面
集計用バッチサーバ
社内向けAPI サーバ
Ameba Developer Center
ディベロッパー向け画面
アプリケーション用データベース
Ameba Developer Center アーキテクチャ
集計用バッチサーバ
ディベロッパー向け画面
Webサーバ
外部向けAPI サーバ
社内向け管理画面Webサーバ
社内向けAPI サーバ
Ameba Developer Center アーキテクチャ
Ameba Developer Center
ディベロッパー向け画面
社内向け管理画面
InternalAPI サーバ
OracleDatabase
自作バッチフレームワーク
ExternalAPI サーバ
Jackson
こ…これ1人で見るの><
CyberAgent, Inc. All Rights Reserved
そもそも作りなおした方がよくね?
http://martinfowler.com/bliki/SacrificialArchitecture.html
犠牲的アーキテクチャ
● 少し前に話題になった考え方
○ “作っているものを捨てることになる現状を受け入れ
る”
○ “捨ててしまうソフトウェアも多くの価値を生み出しうる
と認めること”
○ “犠牲的アーキテクチャのコードを書いたチームが、そ
の潮時を決める”
http://capsctrl.que.jp/kdmsnr/wiki/bliki/?SacrificialArchitecture
よし、作りなおそう!
解決に向けたアプローチ
● コストとリソースのバランス崩壊
○ 要件や勘所は自分が一番良く知っている
○ 内製フレームワークからの脱却
○ 生産性が高いものを
解決に向けたアプローチ
● 知識やノウハウの暗黙知化・属人化
○ 時間の経過とともに積み上がるもの
■ ドキュメント化をし続けるのは結構大変
○ 暗黙知を(できるだけ)状態として管理しない
■ コードで宣言的にする
■ 環境変数、設定ファイル、イメージファイル
○ GHE 上で変更の差分も追える
CyberAgent, Inc. All Rights Reserved
これが実現できそうなもの
+
アプリケーション用データベース
Ameba Developer Center アーキテクチャ(再掲)
集計用バッチサーバ
ディベロッパー向け画面
外部向けAPI サーバ
社内向け管理画面
内部向けAPI サーバ
アプリケーション用データベース
新アーキテクチャ
集計用バッチサーバ
社外用Dockerコンテナ
Single Page Application + REST API サーバ
社内用Dockerコンテナ
Single Page Application + REST API サーバ
Dockerコンテナ
Dockerコンテナ
Dockerコンテナ
Dockerコンテナ
新アーキテクチャ技術スタック
社外用Dockerコンテナ
Single Page Application + REST API サーバ
社内用Dockerコンテナ
Single Page Application + REST API サーバ
コンテナ管理はDocker Compose で!
CyberAgent, Inc. All Rights Reserved
どうなったか
作りなおした結果
サービスのレガシー化
少ない人数(実質1人)で技術的負債が返済できた→ Spring Boot の高い生産性のおかげ
冗長なアーキテクチャ
アーキテクチャをシンプルにでき、メンテも楽ちん→ Spring Boot の柔軟さのおかげ
設定やプロビジョニングの
暗黙知
Spring profile や Dockerfile で秘伝のタレをなくし、Docker Compose で安心してプロビジョニング→ Spring Boot と Docker のポータビリティのおかげ
システムそのもののポータビリティも高まり、Cloud Ready に
Spring Boot + Dockerさまさまです
CyberAgent, Inc. All Rights Reserved
Spring Boot + Docker3分クッキング
くらいかも?
Spring Boot + Docker Compose レシピ
1. Spring Boot でアプリのプロジェクトを作る
2. Maven / Gradle で build して実行可能 jar を作る
○ mvn package か ./gradlew build
3. アプリコンテナ用の Dockerfile を書く
4. 各コンテナを制御する docker-compose.yml を書く
5. docker-compose up -d!
FROM java:8 EXPOSE 8080 WORKDIR /opt/webapp ADD build/libs/external-1.0.0.jar /opt/webapp/external.jar ENTRYPOINT [“java”,“-Djava.security.edg=file:/dev/./urandom”, “-jar”, “external.jar”]
Dockerfile
Ameba Developer Center の例
external: build: ./external ports: - 8080:8080 envirionment: _JAVA_OPTIONS: -Xms512m -Xmx1g command: --spring.profiles.active=development links: - mysql - memcachedinternal: build: ./internal ports: - 8081:8080 envirionment: _JAVA_OPTIONS: -Xms512m -Xmx1g command: --spring.profiles.active=development links: - mysql - memcached
docker-compose.ymlmysql: image: mysql:5.6 ports: - 3306:3306 envirionment: MYSQL_ROOT_PASSWORD: "" MYSQL_USER: dbuser MYSQL_PASSWORD: pass MYSQL_ALLOW_EMPTY_PASSWORD: yesmemcached: image: memcached:latest ports: - 11211:11211
Spring の profile を指定
CyberAgent, Inc. All Rights Reserved
サービスの運用について
自己紹介
● 山田 岳人
● Amebaポイント事業室
● ポイントサービス運用
コンテンツ
1. Spring Boot 導入の背景
2. Spring Boot Actuator による運用
a. ヘルスチェック
b. 充実した統計情報
c. リモートシェル
3. まとめ
導入の背景
コレ
Amebaのポイントサービス
https://d-money.jp
2015年4月にローンチした、Amebaの内外で
利用可能な、新しいポイントサービス。
ユーザー
Ameba
1. ポイントユーザー向けのWEBサイト
a. 1,000,000 PV/Day2. Amebaサービスや提携企業向けのAPI
a. 1,000,000 Req/Dayb. 1,000 Req/Sec
→ それなりの規模
システム要件
ユーザー
Ameba
提携企業
セキュリティ
資金決済法
セキュリティ要件
● 仮想通貨の性質を持つため、利用できる
ミドルウェア等にも制限
● ポイント事業をBtoBとして提供するため、ダウ
ンタイムは賠償問題
● 法的にも定期的な監査があり、
1円のズレで業務改善命令
諸事情につき3ヶ月でリリースしたい
諸事情につきエンジニアは3人で
● JVM と Spring Framework の信頼性
● Spring Boot の高い生産性と保守性
● 既存サービスの Javaリソースの再利用
● 深夜残業
● 休日出勤
→ Spring Boot の選定に至る
どう解決するか
Spring Boot の恩恵
● Spring Boot + Lombok + Gradleでの
少ないコード量・高い生産性
● Spring Boot Actuator、CLI等による
充実した開発・運用ツール
Spring Boot の恩恵
● Spring Boot + Lombok + Gradleでの
少ないコード量・高い生産性
● Spring Boot Actuator、CLI等による
充実した開発・運用ツール
↑今回のテーマはこっち
ユーザー
Ameba
提携企業
セキュリティ
資金決済法
業務改善
損害賠償
ユーザー
Ameba
提携企業
セキュリティ
資金決済法
Spring BootActuator
Spring BootActuator
Spring Boot Actuator とは
1. アプリケーションの保全性や統計情報を監視
するための、Spring Bootの追加機能
2. HWリソースの他、 Spring Boot で設定された
DBやAPサーバーの情報を自動で収集
3. 一般的な HTTP によるエンドポイントの他、 JMX や SSH でも利用可能
Gradle なら以下の定義を追加。
dependencies { compile "org.springframework.boot:spring-boot-starter-actuator" }
Actuator の導入
Maven なら以下の定義を追加。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
Actuator の導入
これだけ
CyberAgent, Inc. All Rights Reserved
ヘルスチェック
/health により以下のような情報を取得できる
{ "status": "UP", "diskSpace": {"status": "UP", "free": 152873189376,"threshold": 10485760}, "db": {"status": "UP", "database": "MySQL","hello": 1}, "redis": {"status": "UP", "version": "3.0"} }
ヘルスチェック
ヘルスチェック
{ "status": "UP", "diskSpace": {"status": "UP", "free": 152873189376,"threshold": 10485760}, "db": {"status": "UP", "database": "MySQL","hello": 1}, "redis": {"status": "UP", "version": "3.0"} }
1. アプリケーションの状態
2. ディスクの空き容量
3. バリデーションクエリの結果
HealthIndicatorの実装で拡張も容易
ヘルスチェックの拡張
public class MemcachedHealthIndicator extends AbstractHealthIndicator { @Autowired private MemcachedClient client;
@Override protected void doHealthCheck(Health.Builder builder) throws Exception { Assert.notNull(client.getConnector()); builder.up().withDetail("threadCount", client.getThreadCount()); }}
Memcached の Indicator を作成してみる
ヘルスチェックの拡張
public class MemcachedHealthIndicator extends AbstractHealthIndicator { @Autowired private MemcachedClient client;
@Override protected void doHealthCheck(Health.Builder builder) throws Exception { Assert.notNull(client.getConnector()); builder.up().withDetail("threadCount", client.getThreadCount()); }}
Memcached の Indicator を作成してみる
1. HealthIndicatorの実装
2. 任意の情報を付加
以下のように拡張して使用してみる
{ "status": "UP", "diskSpace": {"status": "UP", "readOnly": false, "free": 152873189376, "threshold": 10485760,}, "db": {"status": "UP", "database": "MySQL","hello": 1}, "redis": {"status": "UP", "version": "3.0"}, “memcached”: {"status": "UP", "version": "3.0"} }
ヘルスチェックの拡張
1. DiscSpaceIndicatorの拡張
2. MemcachedIndicatorの作成
/health でできること
1. 実装なしで利用できるヘルスチェックに最適な
エンドポイント
2. HWリソースの他、Spring Bootで自動設定さ
れたDB等の保全性の情報も自動で収集
3. HealthIndicator の実装により拡張も容易
CyberAgent, Inc. All Rights Reserved
メトリクス
こんなグラフを出している
/metricsにより以下のような情報を取得できる
メトリクス
{ "mem": 8178944, "mem.free": 5761390, "processors": 4, "uptime": 123532217, "instance.uptime": 123511729, "systemload.average": 0, "heap.committed": 8178944, "heap.init": 8388608, "heap.used": 2417553, "heap": 8178944, "threads.peak": 100, "threads.daemon": 88, "threads": 91, "classes": 9240, "classes.loaded": 9240, "classes.unloaded": 0, ・・(略)・・
}
{ ・・(略)・・
"datasource.primary.active": 0, "datasource.primary.usage": 0, "counter.status.200.account.id": 24, "counter.status.200.account.id.deposit": 12, "counter.status.200.internal-query.account.id.deposit": 12535, "counter.status.200.internal.account.id": 3934268, "counter.status.200.internal.account.id.accumulation": 12751, "counter.status.200.internal.account.id.achievement": 157807, "counter.status.200.internal.account.id.deposit": 259011, "counter.status.200.internal.account.id.expiration": 3908684, "counter.status.200.internal.account.id.withdrawal": 12228, "counter.status.200.internal.id.notification": 92097, "counter.status.200.internal.allcomponent": 2, "counter.status.200.internal.component": 612553, "counter.status.200.manage.health": 101106, "counter.status.400.internal.account.id.deposit": 11, "counter.status.400.internal.account.id.withdrawal": 11, "gauge.response.account.id": 3, "gauge.response.account.id.deposit": 17, ・・(略)・・
}
System metrics
1. トータルやフリーのメモリ量
2. サーバーやアプリケーションの起動時間
3. サーバーのロードアベレージ
4. init, commited, used等のヒープ情報
5. peak, deamon等のスレッド情報
6. クラスロード情報
7. GCの時間や回数 …等々
Datasource metrics, Tomcat metrics
1. 有効なDB接続数
2. 使用中のDB接続プールの接続数
3. Tomcatの有効セッション数
4. Tomcatの最大セッション数
CounterService, GaugeService
1. エンドポイントとステータス毎の件数
2. エンドポイント毎の応答時間
こんなグラフを出している
エンドポイント毎に
PublicMetricsでメトリクスの追加も容易
Memcached の Metrics を作成してみる
メトリクスの拡張
public class MemcachedMetrics implements PublicMetrics { private MemcachedContext context; @Override public Collection<Metric<?>> metrics() { List<Metric<?>> metrics = new ArrayList<Metric<?>>(2); metrics.add(new Metrics<Integer> ("active", context.getActive())); return metrics; } }
Memcached の Metrics を作成してみる
メトリクスの拡張
public class MemcachedMetrics implements PublicMetrics { private MemcachedContext context; @Override public Collection<Metric<?>> metrics() { List<Metric<?>> metrics = new ArrayList<Metric<?>>(2); metrics.add(new Metrics<Integer> ("active", context.getActive())); return metrics; } }
1. PublicMetricsの実装
2. Key-Valueで情報を追加
GaugeServiceでゲージの追加も容易
CounterServiceでカウンタの追加も容易
提携先企業様毎のAPI呼び出し
カウンタの拡張
@Service public class ClientCounterService { @Autowired private CounterService counterService;
public void callApi(String clientId) { counterService.increment("services.client.invoked." + clientId); } }
提携先企業様毎のAPI呼び出し
カウンタの拡張
@Service public class ClientCounterService { @Autowired private CounterService counterService;
public void callApi(String clientId) { counterService.increment("services.client.invoked." + clientId); } } 1. 任意の文字列で
こんなグラフを出している
提携先毎のAPIコール数
/metrics でできること
1. 実装なしで利用できる、システムの統計情報取
得に最適なエンドポイント
2. Spring Boot で自動設定されたDBやAPサー
バー等のメトリクス情報も自動で収集
3. 簡単な実装で拡張も容易
ID Description
/autoconfig 自動設定される全ての情報を取得
/beans SpringのBean情報を全て取得
/configprops @ConfigurationProperties で設定された全ての値を取得する
/env アプリケーションの環境情報を取得
/mappings @RequestMappings のパスの一覧を取得
開発で便利なエンドポイント
ID Description
/health アプリケーションのヘルス情報を取得
/metrics アプリケーションのメトリクス情報を取得
/trace 直近のHTTPリクエスト情報を取得
/dump スレッドダンプを取得する
/shutdown アプリケーションをgracefulに停止する
運用で便利なエンドポイント
いずれのエンドポイントも実装なしで利用できて、簡単な実装で拡張も容易
CyberAgent, Inc. All Rights Reserved
リモートシェル
Gradle なら以下の定義を追加。
dependencies { compile "org.springframework.boot:spring-boot-starter-remote-shell" }
Remote shell の導入
Maven なら以下の定義を追加。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-remote-shell</artifactId> </dependency> </dependencies>
Remote shell の導入
これだけ
g-mbp:~ gakuto$ ssh -p 2000 user@localhost . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.3.0.RELEASE) on g-mbp:>
Remote shell の起動
> metrics
> dashboard
驚くほど豊富な機能がある詳しくは...
> help
JavaやGroovyでコマンドの追加も容易
class changeMode { @Usage("Change Mode") @Command def change(InvocationContext context) { return CacheContext.changeMode() } }
Remote shell Command の作成
JavaやGroovyでコマンドの追加も容易
class changeMode { @Usage("Change Mode") @Command def change(InvocationContext context) { return CacheContext.changeMode() } }
Remote shell Command の作成
@Commandを付けるだけ
● Actuator の機能を対話的に実行できる
● SSH で繋ぐことにより、サーバー管理者がより
手軽に、より安全に利用できる
● JavaやGroovyによるコマンドの追加も容易
Remote shellのススメ
CyberAgent, Inc. All Rights Reserved
まとめ
● Spring Boot + Lombok + Gradleでの
少ないコード量・高い生産性
● Spring Boot Actuator、CLI等による
充実した開発・運用ツール
まとめ
まとめ
● Spring Boot + Lombok + Gradleでの
少ないコード量・高い生産性
● Spring Boot Actuator、CLI等による
充実した開発・運用ツール
↑今回のテーマはこっち
まとめ
● Actuatorの充実した機能により、
少ない工数で安全なシステム運用を実現
● 面倒な運用ツールの心配が少ないので、
短い開発期間でも事業的要件の機能化に
コミットすることができる
ご清聴ありがとうございました