20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

100
大規模映像配信サービスの Java8による全面リニューアルの裏側

Transcript of 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Page 1: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

大規模映像配信サービスのJava8による全面リニューアルの裏側

Page 2: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Hello!氏名 秋穂 賢(あきほ すぐる)

所属 株式会社U-NEXT システム開発部

リリース管理や開発用ミドルウェア管理DBFlute & Java8でのAPI開発 など見習いスクラムマスターとして精進中

仕事

このページ以降、U-NEXTはサービス名称を表します

Page 3: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

そもそもU-NEXT?最新情報はWebで http://video.unext.jp/introduction

2015/10/8全面リニューアルを実施!

◉ 12万本以上の映像コンテ

ンツ

◉ 20万冊以上の電子書籍

Page 4: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

そもそもU-NEXT?最新情報はWebで http://video.unext.jp/introduction/device

Page 5: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

そもそもU-NEXT?最新情報はWebで http://video.unext.jp/introduction/family

Page 6: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

そもそもU-NEXT?最新情報はWebで http://video.unext.jp/introduction/fee

Page 7: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

そもそもU-NEXT?

2015年2月〜

2015年10月〜

Page 8: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

そもそもU-NEXT?

◉ 動画配信サービスを軸として、書籍・音楽コンテンツのサービスも

提供

◉ 多種多様なデバイス・複数アカウント

◉ 見放題・ポイント

◉ 各社とアライアンスを提携

◉ FHD配信・アダプティブストリーミング配信

◉ コンテンツホルダーに応じた最高ビットレートのフレキシブルな制御

◉ などなど....

細やかな制御

Page 9: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

第1章リニューアルの背景

Page 10: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

U-NEXTの歴史

Page 11: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Pay per View開始

GyaONEXTサービス開始

マルチデバイス

2007年6月

1デバイス1顧客デバイス認証見放題のみ

2008年11月

都度課金の仕組み

コンテンツDB

顧客・課金DB

2010年6月

TVデバイス対応オンライン認証

の仕組み

新顧客課金DB

新顧客課金DB

Page 12: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

PlayStation VitaU-NEXT

TV

PCスマホ

タブレット

2012年 2014年

増える対応デバイス

Page 13: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

● 様々な環境と異なるバージョンで動いていたPHP● 様々なPHPアプリケーションから直接リクエストされる

DB● 各テーブルが触るな危険状態に

● 新しいサービスを開始する際には同じようなテーブル

が次々と拡張されていく

2007年から拡張し続けた複雑怪奇なシステム

Page 14: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

アニメ放題サービス提携の決定

Page 15: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

これ以上の拡張は不可能

アニメ放題の先を見据えて

既存システムを捨て

U-NEXTサービスサイトの

リニューアルを決断

Page 16: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

U-NEXT大幅

リニューアル

2015年10月

アニメ放題サービス開始

2015年2月

Page 17: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

リニューアルで目指す姿

Page 18: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

性能にこだわるシステム

よりよいユーザ体験の為に性能にこだわる

アプリケーションだけでなく

システムアーキテクチャとして高い性能を出せるような設計に

Page 19: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

メンテナンス性の高いシステム

DBの集中管理

● どのDBがどのアプリケーションからアクセスされているか、管理したい

● DB毎に管理するAPIを実装する方針に

アーキテクチャの最適化を測った結果

自然とマイクロサービスアーキテクチャ

よりの思想に

(実際はミディアムサービスくらい)

Page 20: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

FW選定

Page 21: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

FW選定で重視したポイント

● 強力なORM○ 生のSQLは書かなくてもよいように

■ 人によって書くSQLが違うとか...

○ DB Migration機能

● 静的型付け言語

○ 規模の大きな開発

○ IDEによるサポート

○ コンパイルによるエラー検知

Page 22: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

● PlayFramework

● (NodeJS + TypeScript)

● DBFlute

いくつかの選択肢があった

Page 23: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

縁があってDBFluteメインコミッターのjfluteさんにDBFluteを紹介してもらえることに

● DBFluteの強力なORM● DB Migrationツール

● コードとドキュメント自動生成

● Javaによる静的型付けとコンパイル

● IDEのサポート

● 豊富な公式ドキュメント

● (24時間戦えるjfluteさんが開発してる)

DBFluteとの出会い

Page 24: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

何より

DBFlute / SAFluteはサービス開発のためのFW

サービス開発で便利な機能が豊富

(詳細は後ほど)

DBFluteとの出会い

Page 25: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

これらのメリットからORMはDBFluteに決定

WebFWは一緒に紹介してもらったDBFluteとの親和性が高いSAFluteに

DBFluteとの出会い

Page 26: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Java8+

DBFlute / SAFlute

Page 27: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

第2章アニメ放題サービスの開始

Page 28: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ 迫り来る決まったリリース日

◉ 決まらない要求仕様

◉ この期間でサーバ構成を検討

◉ そして開発メンバーがDBFluteの習得○ jfluteさんが勉強会をひらいてくれた

○ DBFluteハンズオン(チュートリアル)をしっかり実施

アニメ放題

http://dbflute.seasar.org/ja/tutorial/handson/

Page 29: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

DBFluteハンズオン?

DBFluteハンズオン = DBFluteのチュートリアル

セクション1 〜 セクション11で構成されている

DBFluteハンズオンで修行する

業務で出てくる技術の習得

http://dbflute.seasar.org/ja/tutorial/handson/

Page 30: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

DBFlute Live DemoそんなDBFluteを生で見てもらいます

Page 31: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

サーバ構成

クライアントむけのAPI永続層は持たない

リバースプロキシのキャッシュ

コンテンツDBを管理するAPI

コンテンツDBSlaveに全文検索エンジンのMroonga

MySQL Atlas中国企業のOSS

SB認証基盤

コンテンツと紐付いたユーザ情報のDB

Page 32: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

アーキテクチャ課題

クライアントむけのAPI永続層は持たない

リバースプロキシのキャッシュ

コンテンツDBを管理するAPI

コンテンツDBSlaveに全文検索エンジンのMroonga

MySQL Atlas中国企業のOSS

SB認証基盤

コンテンツと紐付いたユーザ情報のDB

① ②

Page 33: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

課題1 Redisへのアクセス

大きく2種類の使い方

◉ データキャッシュとしてのRedis○ マスタデータはDBに格納

○ キャッシュとしてRedis上にも保存

○ ユーザDBのデータはキャッシュへ

◉ データストアとしてのRedis○ マスタデータをRedisに格納

キャッシュを意識しないデータのCRUD

構造を意識したデータのCRUD

Page 34: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

キャッシュとしてのRedis

◉ 対象テーブル毎にCRUDのI/Fを持ったLogicクラスを実装

○ キャッシュを意識したくないテーブルを作るタイミングでLogicクラ

スも一緒に実装

◉ RedisへのアクセスはFacadeを使って統一で使い回し○ insert or update時には内部でキャッシュを削除

○ delete時は一緒にキャッシュを削除

○ select時はキャッシュがあればキャッシュから、なければDBから

のデータをキャッシュに

◉ 内部ではJedisを利用

キャッシュを意識しないデータのCRUD

Page 35: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

キャッシュとしてのRedis

@Resourceprotected ViewingHistoryCacheLogic viewingHistoryCacheLogic;…UsrViewingHistory viewingHistory = new UsrViewingHistory();viewingHistory.setUserId(userId);…viewingHistoryCacheLogic.insertOrUpdate(viewingHistory);

ViewingHistoryParam param = new ViewingHistoryParam();param.setUserId(userId);param.addOrderByList(ViewingHistoryDbm.getInstance().columnUpdateDatetime());… return viewingHistoryCacheLogic.getList(param);

Page 36: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

データストアとしてのRedis

◉ Logic / Facadeクラスは変わらず実装

◉ もう一歩発展

◉ jsonでスキーマ定義

◉ それを元に共通して使えるクラスについてテンプレート化○ Velocityテンプレートを利用

○ DBFluteの自動生成の仕組みに乗せて、Redisにスキーマ定義を

もたせて自動生成!!

◉ IDEのコード補完の恩恵を存分に受けられるように

構造を意識したデータのCRUD

Page 37: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

データストアとしてのRedis

EVALUATION: { $comment : "評価点", $type : "table", PLATFORM_CODE : {

type: "varchar",comment: "プラットフォームコード",kvsKey: true ,notNull: true },

SAKUHIN_CODE : {type: "varchar",comment: "作品コード",kvsKey: true,notNull: true },

EVALUATION_POINT : {type: "varchar",comment: "評価点",notNull: true },

TTL : {type: "java.time.LocalDateTime",comment: "有効期限",notNull: true

}}

public class EvaluationMeta implements KvsStoreMeta {…(Meta data. name, column, ...)}

public class BsEvaluation implements KvsStoreEntity, Serializable {…(getter / setter / util methods)}

public class Evaluation extends BsEvaluation {… (extends local methods)}

自動生成

Page 38: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ 本当は専用の検索エンジン(Solr/Elasticsearch)を使いたかっ

◉ 時間の都合上、手軽に全文検索ができるMroongaを選択

◉ 一部Slaveの全文検索したいテーブルだけのEngineをMroongaにして利用○ 初めて利用するため、何かあった場合の影響を最小限に

課題2 Mroongaへの対応

Mroonga?Groongaをベースとした全文検索エンジン。MySQLのストレージエンジンの1つとしてMySQLに全文検索機能を提供

Page 39: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

課題2 Mroongaへの対応

Mroongaを使うとSQLで手軽に全文検索が出来る

DBFluteはmatch構文をサポート

mysql> SELECT * FROM diaries WHERE MATCH(content) AGAINST("fine");+----+-----------------------------------------+| id | content |+----+-----------------------------------------+| 1 | It'll be fine tomorrow. |+----+-----------------------------------------+1 row in set (0.00 sec)

Page 40: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

課題2 Mroongaへの対応

EngineInnodb

EngineInnodb

EngineInnodbMroonga

Mroongaへの検索かどうかで向け先を変える

Page 41: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

課題2 Mroongaへの対応

EngineInnodb

EngineInnodb

EngineInnodbMroonga

Mroongaへの検索かどうかで向け先を変える

SelectableDataSource

Page 42: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

SelectableDataSource◉ Seasar2が提供しているMaster/Slaveを切り替える仕組

みを利用

// e.g. SelectableDataSource のベタな実装方法 @Javaprotected MemberBhv memberBhv;protected DataSourceFactory dataSourceFactory; // injected

public void fooAndBar() { dataSourceFactory.setSelectableDataSourceName("master"); Member member = ... ... memberBhv.update(member); // master の会員を更新

dataSourceFactory.setSelectableDataSourceName("slave"); MemberCB cb = ... ... ... = memberBhv.select(cb); // slave の会員を検索}

http://dbflute.seasar.org/ja/manual/reference/diway/seasar/selectabledatasource.html

Page 43: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

SelectableDataSource

◉ SAFluteの機能を使ってSelectableDataSourceをベースに汎用性を持たせて使いやすいようにして利用

PagingResultBean<Sakuhin> sakuhinPage = slaveDBAccessor.accessIfNeeds(() -> {

return sakuhinBhv.selectPage(cb -> { cb.specify().... cb.query().... });}, isNotEmpty(searchWord));

http://dbflute.seasar.org/ja/manual/reference/diway/seasar/selectabledatasource.html

検索ワードがあれば強制的にSlaveへSlaveのhost設定をMroongaなMySQLへ向くように設定

Page 44: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ MySQL Atlasはトランザクションを更新処理とみなしてmasterへ

◉ SAFlute(SAStruts)はリクエストでトランザクション

◉ 各API毎に自前でトランザクションをかけるのはつらい

課題3 MySQLとAtlas

ここのLBはMySQL Atlasにお任せ

Page 45: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

LazyTransaction

Page 46: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ 更新系処理が開始した時点で初めてトランザクションを開始するように

◉ DBFluteでBehavior(SQL実行)の処理前後にHookができる

LazyTransaction?

protected BehaviorCommandHook createLazyTransactionHook() { return new BehaviorCommandHook() { public void hookBefore(BehaviorCommandMeta meta) { if (!meta.isSelect() || meta.isProcedure()) { LazyHookedUserTransaction.beginRealTransactionLazily(); } } public void hookFinally(BehaviorCommandMeta meta, RuntimeException cause) { } @Override public boolean inheritsExistingHook() { return true; } }; }

SAFluteのリクエスト開始時点のHookへ登録

Page 47: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ 課題1 Redisへのアクセス○ キャッシュ / ストアとしての使い方○ FacadeやLogicで処理をまとめたり、DBFluteの自動

生成機能に乗せて独自の自動生成機能を作った

◉ 課題2 Mroongaへの対応○ DBFluteのSelectableDataSourceを使ってMaster

/ Slaveの切り替えを汎用的に実装

◉ 課題3 MySQLとAtlas○ BehaviorCommandHookを使って全てのBehavior

の実行前にHookを入れることでLazyTransaction機能を実現

アーキテクチャ課題への対応

Page 48: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Special Thanks

アーキテクチャ周りはDBFluteコアユーザの

@p1us2er0 さん

に多大なるご協力を頂きました

Page 49: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

その他

日々のサービス開発で

便利なこと

工夫してること

などなど

一挙にご紹介!!6連発

Page 50: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

DB変更を行うとき、どのようにしていますか?

DBFluteの場合、こんな感じです

1. ERDドリブン開発

Page 51: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

1. ERDドリブン開発

1. EclipseプラグインのERMasterでER図を変更

Page 52: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

1. ERDドリブン開発

2. ERMasterからDDLを出力

Page 53: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

1. ERDドリブン開発

3. manage.shのrenewalを実行

renewalはDB定義から

Javaのエンティティクラスな

どを自動生成する機能

Page 54: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

1. ERDドリブン開発

4. DB変更した内容のJavaが自動生成

Page 55: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

1. ERDドリブン開発

4. DB変更した内容のJavaが自動生成

DB変更完了!

U-NEXTではDBFluteの流儀に沿って

DB変更する場合はまずERDを修正する

というフローで実施

ER図と実態が一致しない、はありえない

Page 56: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2. ReplaceSchema

テストデータを追加

開発メンバーと共有 & 最新化

みなさんどのようにやってますか?

DBFluteの場合、こんな感じです

Page 57: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2. ReplaceSchema

1. テストデータの修正と出力

1. まず、MySQLへテストデータ

を追加

2. manage.shでload data reverse実行!

3. DBに入っているテストデータ

がxlsやtsv形式で出力

4. git commit & push

http://dbflute.seasar.org/ja/manual/function/generator/task/doc/loaddatareverse.html

Page 58: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2. ReplaceSchema

2. データ共有 & Load

1. git pull2. sh manage.sh3. 04. Enter!

http://dbflute.seasar.org/ja/manual/function/generator/task/doc/loaddatareverse.html

drop table

create table

insert into

Page 59: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2. ReplaceSchema

2. データ共有 & Load

1. git pull2. sh manage.sh3. 04. Enter!

http://dbflute.seasar.org/ja/manual/function/generator/task/doc/loaddatareverse.html

drop table

create table

insert into

修正したデータをgit経由で簡単に共有

開発前にReplaceSchemaをしておけば

テストデータの共有漏れは起こらない

Page 60: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

3. AlterCheck (DB Migration)

ローカルと開発と本番のDBスキーマが違う!

なんてことが起こらないようにするための

DB Migrationツール

DBFluteの場合、こんな感じです

Page 61: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

DB変更後にmanage.shの8

◉ 前回のDBの状態で

ReplaceSchema◉ 最新のDBの状態で

ReplaceSchema◉ 前回と今回の差分を提示し

てFailure

3. AlterCheck (DB Migration)

Page 62: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

3. AlterCheck (DB Migration)

差分を確認

alterSQLを定義

今回の場合は

create table hoge

再度AlterCheckでSuccess!

後は各環境へ差分を反映させるだけ

Page 63: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

3. AlterCheck (DB Migration)

差分を確認

alterSQLを定義

今回の場合は

create table hoge

再度AlterCheckでSuccess!

AlterCheckを運用として実施していくことで

各環境でのDBスキーマで差分が出ないように

Page 64: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

4. Schemaドキュメント

ER図だけでなく、DBFluteはHTML形式のドキュメントも自動生成してくれる

Page 65: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

4. Schemaドキュメント

ER図だけでなく、DBFluteはHTML形式のドキュメントも自動生成してくれる

U-NEXTでは

人によってER図とSchema.htmlを

使い分けて開発作業を行っている

Page 66: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

5. 見やすいログ

開発やテスト時は何度もデバッグを行うため、ログが見やすいことは重要

今回は一部のログをご紹介

http://dbflute.seasar.org/ja/manual/function/helper/saflute/friendlylogging.html

Page 67: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

5. 見やすいログ

Requestの開始と終了

http://dbflute.seasar.org/ja/manual/function/helper/saflute/friendlylogging.html

...-DEBUG (...#before():268) - * * * * * * * * * * {BEGIN}: /member/list/ Request class=org.seasar.framework.container.hotdeploy.HotdeployHttpSer... , REQUEST_URI=/dockside/member/list/, SERVLET_PATH=/member/list/, Chara... , ContentType=application/x-www-form-urlencoded, Locale=ja, Locales=ja,......... Response class=org.mortbay.jetty.Response, ContentType=text/html; chars... , toString()=HTTP/1.1 200 Content-Type: text/html; charset=utf-8 Expir... [session] javax.servlet.jsp.jstl.fmt.request.charset=UTF-8 [session] member_memberListForm=org.dbflute.maihama.app.web.member.Memb... [session] org.apache.struts.action.LOCALE=ja [session] org.dbflute.maihama.domainfw.action.DocksideUserBean={userId=...* * * * * * * * * * {END}: /member/list/ [00m00s247ms]

Page 68: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

5. 見やすいログ

SQLの実行時間と結果概要

http://dbflute.seasar.org/ja/manual/function/helper/saflute/friendlylogging.html

2016-05-20 17:28:22,346 [main]-DEBUG (XLog#log():43) - SakuhinListActionTest.testname():131 -> ...2016-05-20 17:28:22,693 [main]-DEBUG (QLog#log():43) - select dfloc.SAKUHIN_ID as SAKUHIN_ID, dfloc.DISPLAY_NAME as DISPLAY_NAME from SAKUHIN dfloc where dfloc.SAKUHIN_ID = 12016-05-20 17:28:22,694 [main]-DEBUG (XLog#log():43) - ===========/ [00m00s348ms (1) result={1, null, ほげ作品, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}@729c021d]

Page 70: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

6. 書きやすいUT

みなさん、テストは書いていますか?

UTFluteを使えば楽々テスト

UTFluteはDBFluteファミリーのJUnit拡張ライブラリ

UTFlute は、自分で new したものにDIできる JUnit 拡張 です。

http://dbflute.seasar.org/ja/manual/function/helper/utflute/index.html

Page 71: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

6. 書きやすいUTActionクラスのisHogeメソッドを実行してbooleanをAssert

public void test_isHoge_hogeはhogeだったらtrue() throws Exception { // ## Arrange ## SakuhinListAction action = new SakuhinListAction(); inject(action);

// ## Act ## boolean isHoge = action.isHoge("hoge");

// ## Assert ## assertTrue("hogeはtrueだ", isHoge);}

http://dbflute.seasar.org/ja/manual/function/helper/utflute/index.html

Page 72: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

6. 書きやすいUThttp://dbflute.seasar.org/ja/manual/function/helper/utflute/index.html

UTFluteのおかげで単体テストの自動化は結構している

◉ JenkinsでのCIも実施○ エラーが出たらHipChatに通知

◉ UTで事前に不具合を検知できた

コード品質が向上!

Page 73: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

その他、UTFluteでの便利機能が提供されています

詳細は公式ページで!

http://dbflute.seasar.org/ja/manual/function/helper/utflute/index.html

6. 書きやすいUT

Page 74: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

アニメ放題

無事に予定通りリリース!!

振り返ってみると

◉ 最初にDBFluteハンズオンをみっちりと実施した効果は

大○ 業務アプリ実装時に役立つTipsがたくさん

◉ 困った時の拡張ポイントがしっかりしてる○ アーキテクチャ課題は無事にクリア

◉ その他諸々サービス開発で役立つ機能○ 細かいけどあったらとても役立つ機能がたくさん

Page 75: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

第3章U-NEXTサービスサイト

リニューアル

Page 76: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ アニメ放題と比較すると遥かに複雑な業務○ アニメ放題はアニメのみ、U-NEXTは洋画・邦画・ドラマなど、ジャン

ルの多さ

○ アニメ放題はiOS/Android/PC、U-NEXTはTV、ゲーム機、STBなど、対応デバイスの多さ

○ アニメ放題は見放題のみ、U-NEXTは見放題と単品でのレンタル作品も

○ U-NEXTはユーザへの見せ方がよりきめ細やか

◉ 複雑な業務 = 開発が大変◉ 複雑な業務 = 複雑なDB

U-NEXTリニューアルでの難関

API数 10倍程度のAPIテーブル数 125テーブル から253テーブルに (区分値除く 29 => 89)

Page 77: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

激しいDB変更の嵐

DBFlute採用から約1年半、DB変更の回数は 186 回

=> 単純計算すると 約 3 日に 1 回はDB変更してる

毎日のようにER図を変更して

AlterCheckして

本番へDDL実行!をしていた日々もあった

怒涛のDB変更ラッシュもDBFluteで乗り越えた

Page 78: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側
Page 79: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

検索のインクリメンタルサーチを目指していた

=> Mroongaでは性能で不利

ElasticsearchとSolrが候補に

「検索」の実績から Solr を選択

Demo:http://video.unext.jp

詳細:http://www.slideshare.net/SuguruAkiho/20151028-17-solr-unext

MroongaからSolrへ

Page 80: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

solrjをそのまま使うとタイプセーフではない...

MroongaからSolrへ

try (HttpSolrClient httpSolrClient = new HttpSolrClient(“http://localhost:8983/solr/schema”)) { httpSolrClient.setParser(new XMLResponseParser()); ModifiableSolrParams params = new ModifiableSolrParams(); params.add("q", "あの日"); params.add("defType", "dismax"); params.add("qf", "name kana^10"); QueryResponse response = httpSolrClient.query(params); SolrDocumentList results = response.getResults(); }…

Page 81: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Schema.xmlから各種クラスを自動生成

全文検索システムFessで使っていたSolr用CBを拡張

MroongaからSolrへ

SolrPagingResultBean<General> list = generalBhv.selectPage(cb -> { cb.query().dismax("あの日", queryField -> { queryField.put(GeneralMeta.Name, null); queryField.put(GeneralMeta.Kana, 10); queryField.put(GeneralMeta.NameGeneral, 20); queryField.put(GeneralMeta.Synonym, null); }); cb.specify().fieldUid(); cb.paging(10, 2); }); LOG.debug("list={}", list);

DBFluteの機能でページング検索が出来る

dismax検索出来る対象のフィールドがタイプセーフに指定可能

specifyでflをタイプセーフに指定可能

Page 82: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

MroongaからSolrへとある1日のフリーワード検索の平均レスポンス:39ms

Page 83: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2016年9月26日、Seasar2のサポートが終了

SAFluteはSAStrutsの拡張FW

リニューアルが終わってないのにFW移行の危機...

そんな時、jfluteさん

「Seasar2フォークしてJava8で書き換えてLastaFlute作っちゃった」

SAFluteからLastaFluteへ

Page 84: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2016年9月26日、Seasar2のサポートが終了

SAFluteはSAStrutsの拡張FW

リニューアルが終わってないのにFW移行の危機...

そんな時、jfluteさん

「Seasar2フォークしてJava8で書き換えてLastaFlute作っちゃった」

SAFluteからLastaFluteへ

使うしかないでしょう

Page 85: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

LastaFluteのいいところ

◉ 起動が圧倒的に早い○ SAFluteは7〜8秒程度、Lastaは2〜3秒程度

◉ ログが見やすい○ DBFluteイズムで見やすいログ

◉ よりシンプルに書けるコード

○ formが引数, formで型定義、Hibernate Validatorが使え

る、などなど

Page 86: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

APIドキュメント自動生成

API開発をしている場合、クライアントへI/F定義を提示する必要がある

=> 自動生成

Page 87: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2015年 6月U-NEXTリニューアルリリース予定

 リニューアルに向けて開発..開発..開発..

膨大な開発

Page 88: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2015年 6月U-NEXTリニューアルリリース予定

 リニューアルに向けて開発..開発..開発..

2015年 8月へ延期

 開発..開発..開発..開発..開発..開発..

膨大な開発

Page 89: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

2015年 6月U-NEXTリニューアルリリース予定

 リニューアルに向けて開発..開発..開発..

2015年 8月へ延期

 開発..開発..開発..開発..開発..開発..

2015年 9月へ延期

 開発..開発..開発..開発..開発..開発..開発..開発..開発..

膨大な開発

Page 90: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

膨大な開発

2015年 6月U-NEXTリニューアルリリース予定

 リニューアルに向けて開発..開発..開発..

2015年 8月へ延期

 開発..開発..開発..開発..開発..開発..

2015年 9月へ延期

 開発..開発..開発..開発..開発..開発..開発..開発..開発..

2015年 10月9日へ延期

 開発..開発..開発.. リリース!!

Page 91: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

ボリューム満点の開発

SAFlute / LastaFlute / DBFluteの軽快さ

実装 => リリース => 修正 => リリース => …

のサイクルをとても軽快に回すことが出来る

リニューアルを乗り越えられたのは

この軽快さのおかげ

膨大な開発

Page 92: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

第4章更なる高みへ

Page 93: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

リニューアルで全力疾走を続けた結果

◉ 個々のソロプレーを足しあわせて何とかなっていた○ チーム力・組織力が全くない状況

◉ ソースコードがちぐはぐ○ とにかく動くコードを早くリリースするのが正義

○ その結果、ちぐはぐなコードが生まれる

○ それでもテストコードは書いてCIはしていたし、DBFlute部分の

コードは問題なし

■ これはDBFluteハンズオンのおかげ

約1年半の開発である程度の技術的負債が生まれた

Page 94: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

スクラム開発

◉ 今まで

○ 複数人のディレクターやQAからの要望を各分野に精通している人

が個々の判断で優先度を決定し、開発

◉ これから○ スクラム開発を導入

○ 優先度はプロダクトオーナーが決定

○ 開発タスクは開発チームで決定

○ 2週間のスプリント

○ スプリント計画ミーティングで実装タスクを決定

○ デイリースクラムで日々の状況や問題点を洗い出し

○ スプリントレビューで成果物の検査

○ スプリント振り返りでよりよいやり方に改善

○ ビジネス開発:アーキテクチャ改善・リファクタリング=7:3

Page 95: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

より働きやすい環境

◉ ハイスペックな開発マシン

○ メモリ32GB、250GB SSD、インテル® Core™i7-5930k

◉ 高級なイス(予定)○ 候補:アーロンチェアなど

◉ 自由に買える書籍○ 申請して5分後に電子書籍が届くとか

◉ 定期的に開催される勉強会○ スクラム読書会

○ 機械学習の勉強会

○ データベースの勉強会 etc...

Page 96: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

コードの品質

◉ これまで

○ コードを書いた人以外の目に触れずに本番へリリースされる

コードがたくさん

◉ これから○ コーディングガイドラインを整備

■ 規約は文章化せず、自動で判別できるものに

○ プルリクベースでのコードレビューを導入

○ 対面でのコードレビュー会を導入

チーム内でよりよいコードを書くという意識が芽生え始める

Page 97: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

より良いアーキテクチャへ

◉ 当初目指していたDB単位のAPI○ これは実現出来た

○ DB変更は比較的簡単に出来る

◉ リポジトリはそれなりにでかい○ 分割出来るプロジェクトが同じリポジトリに存在している

■ 時間の都合上

◉ もっと最適に分割出来る

マイクロサービスアーキテクチャの思想でアーキテクチャをリファクタリグ

(やりすぎないようにミニマムサービスくらいを目指して)

Page 98: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

◉ まだまだたくさんある開発案件○ これからはチームでよりよいものをより楽しく開発出来るように

○ そして競合に負けないように

◉ 個々の技術力

○ コードレビュー・勉強会などを通じてメンバーそれぞれがお互いを

高め合える環境・そして文化に

◉ より最適なアーキテクチャに○ 既存の技術的負債を放置せず、少しずつ返却していく

○ 2年後、3年後も楽しく開発出来るように

今後

Page 99: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

U-NEXTでは人材を募集しています

映画やアニメが好きなひとエンターテイメントが好きなひと

配信プラットフォームに興味のあるひと技術的なことが好きなひと

一緒に仕事をしましょう

http://unext.co.jp/recruit/

Page 100: 20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側

Thank you for your attention