Upload
yoshitaka-kawashima
View
3.341
Download
0
Embed Size (px)
Citation preview
Antifragile Java
kawasima
Java Day Tokyo 2017D1-E1
TIS株式会社川島 義隆
Antifragileリーマンショックで大儲けした
ニコラス・ナシム・タレブの書いた
ブラック・スワンに続くヒット作
(日本語訳は未)
主題は、不確実なことが実際に
起きたときに、大きなゲインを
得ようというもの。
Fragile変化に対して弱い・損失が大きい仕組み
● 後戻りの計画・その分の予算確保がないウォー
ターフォールのプロジェクト
● プロビジョニングが十分でないシステム
(ex. 30分 2000PVでダウンする図書館システム)
● 例外のハンドリングが雑なアプリケーション
Robust変化に対して、十分強い仕組み(フラジャイルの裏返し)
● よく計画されたウォーターフォールの開発プロジェクト
● 急激なアクセス増や異常なデータファイルに対しても、安全に処理できるアプリケーション
● 例外を適切にハンドリング出来ているコード
Resilient大きな変化に対し、一時的にシステムのパフォーマンス
を落としてもすぐに復旧できる仕組み
Antifragile変化が起これば起こるほどメリットがある仕組み
ストレスが増せば増すほど強くなる仕組み
そんなことが可能なのでしょうか?
Benefit
Change
Cost
Antifragile
ResilientRobust
Fragile
Antifragileへの道のり
現在の知識で予測しない早期に問題を起こして対処する
1697年まではヨーロッパでは真実だった。
「白鳥は白い」
経験に基づく知識
現在の知識の限界 → 分からないことが分からない
<%@ page contentType="text/html; charset=UTF-8"%>
クローラやDDoS攻撃を受けない環境で開発し
てきた人にとっては、問題が予測できない
<%@ page contentType="text/html; charset=UTF-8" session="false"%>
不特定多数がアクセスできるサイトでは、本来セッションを使わない
ページでも、空セッションが作られメモリを圧迫する。
Five Orders of Ignorance0OI: 全部分かっている
「答え」を持っている。あとは書き写すだけで完成する。
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 := MTTFMTTF + 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の追求はFragileResilient無き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 BreakerResilient
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 DetectionMonitoring
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 TestingUnknownの早期検出
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.specUnknownの早期検出
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 ContainerFalchion Container
JVM real process
WebApplication
JVM pool
JVM virtual process
JVM virtual processJVM 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.01.0.0へ切り戻す
1.1.0へバージョンアップ
バージョン毎にディレクトリを作ってアプリケーションのjarを置いておく
Auto Repair
http://program-repair.org/
速い改善のサイクル
システムの修復には2通りある
● 状態の修復 (トランザクションのロールバックなど)
● 振る舞いの修復 (プログラムのパッチなど)
プログラムの自動修復(パッチ生成)の研究も盛んに行われている
自動的にpatchを作ってくれる
速い改善のサイクル
Auto Tuning速い改善のサイクル
Antifragile Team & Process
Bimodal ITSoR 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にはそのパーツが揃いつつある
● 予測は大事だが限界がある
あれこれいじくり回せる環境とプロセスを作ろう
● 失敗を防ぎきるよりも、前提とした設計を