SlideShare a Scribd company logo
Antifragile Java
kawasima
Java Day Tokyo 2017
D1-E1
TIS株式会社
川島 義隆
Antifragile
リーマンショックで大儲けした
ニコラス・ナシム・タレブの書いた
ブラック・スワンに続くヒット作
(日本語訳は未)
主題は、不確実なことが実際に
起きたときに、大きなゲインを
得ようというもの。
Fragile
変化に対して弱い・損失が大きい仕組み
●
後戻りの計画・その分の予算確保がないウォー
ターフォールのプロジェクト
●
プロビジョニングが十分でないシステム
(ex. 30分 2000PVでダウンする図書館システム)
●
例外のハンドリングが雑なアプリケーション
Robust
変化に対して、十分強い仕組み
(フラジャイルの裏返し)
●
よく計画されたウォーターフォールの開発プロジェクト
●
急激なアクセス増や異常なデータファイルに対しても、
安全に処理できるアプリケーション
●
例外を適切にハンドリング出来ているコード
Resilient
大きな変化に対し、一時的にシステムのパフォーマンス
を落としてもすぐに復旧できる仕組み
Antifragile
変化が起これば起こるほどメリットがある仕組み
ストレスが増せば増すほど強くなる仕組み
そんなことが可能なのでしょうか?
Benefit
Change
Cost
Antifragile
Resilient
Robust
Fragile
Antifragileへの道のり
現在の知識で予測しない
早期に問題を起こして対処する
1697年まではヨーロッパでは真実だった。
「白鳥は白い」
経験に基づく知識
現在の知識の限界 → 分からないことが分からない
<%@ page contentType="text/html; charset=UTF-8"%>
クローラやDDoS攻撃を受けない環境で開発し
てきた人にとっては、問題が予測できない
<%@ page contentType="text/html; charset=UTF-8" session="false"%>
不特定多数がアクセスできるサイトでは、本来セッションを使わない
ページでも、空セッションが作られメモリを圧迫する。
Five Orders of Ignorance
0OI: 全部分かっている
「答え」を持っている。あとは書き写すだけで完成する。
1OI: 分からないことが分かっている
答えを得るための「質問」を持っている。
2OI: 分からないことが分からない
「質問」を持たない状態。決定的な答えを引き出すための「質問」ができない。
3OI: 分からないことが分からない状況を何とかする術を知らない
2OI 1OI 0OI→ → と進んでいくためのプロセスがない状態です。
4OI: 無知にレベルがあることを知らない
http://qiita.com/seki_uk/items/4001423b3cd3db0dada7
2OIには予測できないBlack Swanが潜む
どうやってBlack Swanを見つけるか?
Bricolage(ブリコラージュ)
プロダクトを組合せたり分解したりして
いじくり回し(Tinkering)新しい価値を生み出す
http://aisel.aisnet.org/cgi/viewcontent.cgi?article=1027&context=icis1991
トップダウンアプローチ ボトムダウンアプローチ
アレコレ試してるうちに
イノベーションが産まれる可能性が
あることを認めよう
突飛なアイデアは出にくい
GameDay
消防士の災害訓練みたいなもの
●
実際の重障害発生をシミュレートして対応
にあたる
● Amazonで始められ、Google、Yahoo、Netflix
などで同様に実施されている。
失敗を避けるのではなく
失敗を前提としてシステムを設計する
Availability :=
MTTF
MTTF + MTTR
https://www.slideshare.net/ufried/patterns-of-resilience
Werner Vogels(Amazon CTO): “Everything fails all the time”
MTTFを長くする → Robust
MTTRを短くする → Resilient
Minimize MTTR
検知
原因解析
修正
テスト
デプロイ
それぞれのフェーズを
短くする
Antifragile System
レジリエント
Antifragile
Resilient
Robust
Robust無きResilientの追求はFragile
Resilient無きAntifragileの追求はFragile
Antifragileは1日にしてならず。
まずResilientを目指そう
レジリエントの教科書
Timeout
●
Socket#connect
●
SocketInputStream#read
(privateメソッドのため、実際はSO_TIMEOUTで指定する)
●
Object#wait
●
Process#waitFor
●
Future#get
●
BlockingQueue#poll
●
…
スレッドをブロックする呼び出しは
必ずタイムアウトを考えよう
Resilient
Retry
●
冪等性に注意
(POSTリクエストのSocket Timeoutはリトライすると
二重処理される可能性がある)
● Timeoutした処理はすぐリトライしても、失敗する可
能性が高い
無闇なリトライはリソースを無駄に喰うだけ
Resilient
Resilient
https://github.com/jhalterman/failsafe
Failsafeを使うと、簡単にリトライポリシーを設定できる
Exponential backoff なども
Circuit Breaker
Resilient
Closed Open
Half Open
失敗が何度も続いたら呼び出し側で呼び出しを停める
(Release It!で紹介されてメジャーに)
失敗が閾値を越える
リセットを試みる
失敗
リセット
https://github.com/jhalterman/failsafe
Netflix Hystrixが有名だが、前述のfailsafeでも実装可能
Bulkheads(隔壁)
Resilient
Circuit Breakerと違って、呼び出される側のリソースを保護する
Web
Icon made by Freepik from www.flaticon.com 
Web Web
Free Paid Free Paid
無料会員の影響で、有料会員までアクセスできなくなることのないように
Steady state
人間がサーバに触れば、そこには常に凡ミスの恐れがある
特に見積では遠い未来のことでも、リソース使用に上限が
設定されていないものは、近い将来、手運用が入るか、
本番障害として現れる
●
ログファイル削除(ローテート)
●
データパージ
●
キャッシュの上限
Resilient
ログローテーションはOS全体の運用と合わせるとよい。
(Log4j等のAppender自体の持つローテーションは運用トラブルをよく聞く)
http://qiita.com/kawasima/items/ab2c9c14e8bbb2d23df5
Resilient
Fail Fast
失敗の可能性が早く分かるものは、その時点で失敗させる
Resilient
●
トランザクションを始める前に、失敗の可能性が
あるかチェックする。
●
リソースを使うより先に、ユーザの入力値チェック
をおこなう
APIゲートウェイでValidationする
Resilient
API Gateway
Service A
Service B
HTTP
HTTP
入力フォーマットの
チェックはここで
可能
そういうAPI Gateway (というかBFF)を開発中です
https://github.com/kawasima/darzana
Monitoring
異常状態をいち早く検知することがAntifragileの必要条件
Anormaly Detection
Monitoring
http://docs.datadoghq.com/ja/guides/anomalies/
季節や時間帯などで変動の大きいデータの異常検知手段
Monitoring
Consumer Driven Contract
Testing
Monitoring
Client
(Consumer)
Server
(Provider)
知らぬ間にServerのAPIが変更された、なんてことがないよう、
Contractを書いてテストして検知する
クライアントサイドからのモニタリング
Monitoring
●
ページのスクショを撮って、変わってないことを比較
する
● ページのHTMLソースを比較する
● Javascriptのエラーが無いことを確認する
● 各ページのHTTPステータスをチェックする
●
クライアントサイドの性能に異常がないことをチェッ
クする。
https://github.com/Cognifide/aet
Unknownの早期検出
「分かっていないこと」を、ランダム性やTinkeringによってあぶり出す
Failure Injection Testing
Unknownの早期検出
https://www.slideshare.net/JoshEvans2/embracing-failure-reinvent-2014
意図的に本番障害を起こし、何が起きるかをモニタリングする
Netflixの取り組み
Chaos Monkey: EC2インスタンス単位で落とす
Chaos Gorilla: AZ単位で落とす
Chaos Kong: リージョン単位で落とす
Latency Monkey: 1Microserviceのレスポンスを遅延させる
Failure Injectionの自動化
Unknownの早期検出
https://www.slideshare.net/InfoQ/applying-failure-testing-research-netflix
現段階では「Injectionのポイントを複数にしてテストしたいが、
組合せ爆発するので絞りたい」を解決しにいっている
Random Testing
入力データをランダムに生成し、テストする
Unknownの早期検出
junit-quickcheckの例
clojure.spec
Unknownの早期検出
Design by ContractのためのツールだがProperty-based Testing
にも使える
構造をもったJSONのようなデータも仕様に沿って生成できる
探索的テスト
Unknownの早期検出
探索的テストで、テストにもランダム性と変動性をもたせ
未知の問題をあぶり出す。
Explore (target)
with (resources)
to discover
(information)
何を目的にして何をテストするのかを明示してから
テスト実行する点において、Ad Hoc Testingとは異なる
速い改善のサイクル
高速起動
アプリケーションの起動は速ければ速いほどよい
Java EEやSpringでは遅いし
lightweightを謳うフレームワークでは機能面で物足りない
遅くなる原因
● DIのためのクラススキャン
●
設定ファイルの動的パース
速い改善のサイクル
Enkan
https://www.slideshare.net/kawasima/enkankotowarirepl
起動がとにかく速くなるように1から設計したフレームワーク
速い改善のサイクル
● 1〜3秒で起動し、Port Listenする。
● DIを最小限にし、明示的にコンポーネント生成・登
録する
●
設定ファイルを一切無くし、コードで書く。
(このためServlet APIにも依存しない)
EnkanSystem.of(
"doma", new DomaProvider(),
"jackson", new JacksonBeansConverter(),
"flyway", new FlywayMigration(),
"template", new FreemarkerTemplateEngine(),
"metrics", new MetricsComponent(),
"datasource", new HikariCPComponent(
OptionMap.of("uri", "jdbc:h2:mem:test")),
"app", new ApplicationComponent(
"kotowari.example.MyApplicationFactory"),
"http", builder(new UndertowComponent())
.set(UndertowComponent::setPort, Env.getInt("PORT", 3000))
.build()
).relationships(
component("http").using("app"),
component("app").using("datasource", "template", "doma", "jackson",
"metrics"),
component("doma").using("datasource", "flyway"),
component("flyway").using("datasource")
);
コンポーネント定義
Routes routes = Routes.define(r -> {
r.get("/").to(HomeController.class, "index");
r.get("/login").to(LoginController.class, "index");
r.post("/login").to(LoginController.class, "login");
r.scope("/admin", admin -> {
admin.resource(UserController.class);
});
}).compile();
速い改善のサイクル
app.use(new DefaultCharsetMiddleware());
app.use(new MetricsMiddleware<>());
app.use(NONE, new ServiceUnavailableMiddleware<>(
    new ResourceEndpoint("/public/html/503.html")));
app.use(envIn("development"), new StacktraceMiddleware());
ルーティング
ミドルウェア定義
速い改善のサイクル
https://www.slideshare.net/syobochim/sier-devops-jjugccc-69780604/32
社内利用事例
速い改善のサイクル
https://www.slideshare.net/syobochim/sier-devops-jjugccc-69780604/49
無停止デプロイ
速い改善のサイクル
Server#1
WebApplication
Load balancer
Server#2
WebApplication
Falchion Container
Falchion Container
JVM real process
WebApplication
JVM pool
JVM virtual process
JVM virtual process
JVM real process
WebApplication
Listen the same port
速い改善のサイクル
REST APIでJVMの再起動や監視ができる
速い改善のサイクル
アプリケーションのデプロイ/切り戻し
速い改善のサイクル
appdir/
/1.0.0
webapp-1.0.0.jar
/1.1.0
webapp-1.1.0.jar
% curl -X POST http://[falcion]/container/refresh/1.1.0
% curl -X POST http://[falcion]/container/refresh/1.0.0
1.0.0へ切り戻す
1.1.0へバージョンアップ
バージョン毎にディレクトリを作ってアプリケーションのjarを置いておく
Auto Repair
http://program-repair.org/
速い改善のサイクル
システムの修復には2通りある
● 状態の修復 (トランザクションのロールバックなど)
● 振る舞いの修復 (プログラムのパッチなど)
プログラムの自動修復(パッチ生成)の研究も盛んに行われている
自動的にpatchを作ってくれる
速い改善のサイクル
Auto Tuning
速い改善のサイクル
Antifragile Team & Process
Bimodal IT
SoR SoE
●
安定性重視
●
予測可能業務
●
リスクを抑えて安全運転
●
要件を事前に明確化
●
スピード重視
●
探索型業務
●
スピード重視で運転
●
トライ&エラー、プロトタイピング
Martin Fowlerの批判
1.システムではなくビジネス視点でモードを考えるべきでは?
2.安全性とスピードはトレードオフではない
https://martinfowler.com/bliki/BimodalIT.html
リードタイムとプロセスタイム
リードタイム
タスク着手 タスク完了チケット作成
プロセスタイム
慎重を要するプロジェクトとそうでないプロジェクトの違いは
リードタイムに現れる
リードタイムの短縮領域
●
案件が失敗が許されないのか、失敗前提でいくの
かを起案時にハッキリさせる
●
それに応じたチーム体制を用意する
●
バッチサイズに応じた開発〜リリースプロセスを
設計する
DevOpsの下地完成
Road to DevOps & Antifragile
①DevとOpsを分離する
②Opsを無人化する
③OpsのAntifragile化
DevとOpsの分離
ITILやSOX法への対応のためには、開発者が
本番環境に気軽にアクセスできることはまかりならない
開発環境 本番環境
運用チーム開発チーム
アクセスは互いに
制限される
Opsの無人化
Devが本番環境にログインしない
開発環境 本番環境
運用チーム開発チーム
デプロイ対象の提供
本番のメトリクス
発生障害情報の連携
OpsのAntifragile化
開発環境 本番環境
運用チーム開発チーム
Tinkering / FIT
本番環境にストレスを加えて強くする
まとめ
● RobustからResilient、Antifragileへ
Javaにはそのパーツが揃いつつある
●
予測は大事だが限界がある
あれこれいじくり回せる環境とプロセスを作ろう
●
失敗を防ぎきるよりも、前提とした設計を

More Related Content

Antifragile Java - Java Day Tokyo 2017 D1-E1