$30 off During Our Annual Pro Sale. View Details »

クラウド時代だからSpring-Retryフレームワーク

 クラウド時代だからSpring-Retryフレームワーク

Yu Watanabe

July 23, 2019
Tweet

More Decks by Yu Watanabe

Other Decks in Technology

Transcript

  1. クラウド時代だから
    Spring-Retry
    フレームワーク
    Y.Watanabe
    2019-07-12
    JSUG勉強会2019その7 ビズリーチにおけるSpringの活用

    View Slide

  2. ストップウォッチ スタート 確認
    2

    View Slide

  3. ビズリーチでは
    エンジニアを募集しています
    3

    View Slide

  4. Who?
    ● 渡辺 祐

    ● (株)ビズリーチ

    ● SREグループ

    ○ Site Reliability
    Engeneering

    4

    View Slide

  5. アンケート
    ● Java 5, 6, 7
    ● Java 8
    ● Java 9,10,11,12…
    ● まさかのJava1.3, 1.4
    ● わからない
    5

    View Slide

  6. RDBMSは?
    ● オンプレミス
    ● AWS-RDS, Google Cloud SQL
    ● その他クラウド
    ● わからない
    6

    View Slide

  7. コネクションプールライブラリ
    ● apache commons-pool 1.x
    ● apache commons-pool 2.x
    ● Tomcat DBCP
    ● HikariCP
    ● その他 (c3po….
    ● わからない
    7

    View Slide

  8. 今日お話したいこと
    ● 数回の自動リトライで
    得られる安眠がある
    ● 自動リトライを実装する前に
    やるべきことがある
    ● Spring-Retryの原始的な使い方
    8

    View Slide

  9. ある日の出来事
    1. RDSが障害でフェイルオーバー
    2. 90秒で自動復旧した
    3. しかしアプリのエラーログアラートは10分以上鳴
    りっぱなし
    9

    View Slide

  10. 誰かがイイこと言った
    DBがフェイルオーバーしたくらいで
    なんでこんなに騒いでんの?
    10

    View Slide

  11. ある日の出来事(2)
    Slack APIが
    「429 Too Many Request」を返却。
    20分くらいエラーログアラートラッシュ
    11

    View Slide

  12. 自動リトライに向いているのは?
    ● 短期間(数分レベル)で復旧している可能
    性が高いなら自動リトライ
    ● そもそも通信過多の場合はスロットリング
    12

    View Slide

  13. aws-sdk-javaの場合
    スロットリングとリトライの両方を内蔵している
    13

    View Slide

  14. 1. JDBC接続のリトライ
    ↑今日はコレ
    2. REST-APIへのhttpリクエストのリトライ
    ↑ ググった結果のコピペでイケます
    14

    View Slide

  15. RDSのフェイルオーバーとは?
    15

    View Slide

  16. RDSのフェイルオーバーとは
    ● 主系に障害が発生すると
    自動的に副系に切り替わる
    ● 公式マニュアルでは
    「60秒から120秒かかる」
    ● 経験値では90秒
    16

    View Slide

  17. DBが90秒で復帰してるのに
    アプリが90秒で復帰できないってどゆこと?
    17

    View Slide

  18. jdbc:mysql://db.biz.internal/hogedb
    $ host db.biz.internal
    db.biz.internal is an alias for
    a.rds.amazonaws.com.
    a.rds.amazonaws.com has address 10.1.1.1
    $ host db.biz.internal
    db.biz.internal is an alias for
    b.rds.amazonaws.com.
    b.rds.amazonaws.com has address 10.2.2.2
    フェイルオーバー前
    フェイルオーバー後
    18

    View Slide

  19. フェイルオーバーメカニズムでは、スタンバイ DB インスタンスをポイントするように DB
    インスタンスの DNS レコードが自動的に変更されます。したがって、DB インスタンスへ
    の既存の接続の再確立が必要になります。Java DNS キャッシュメカニズムがどのよう
    に機能するかによって、JVM 環境の再設定が必要になる場合があります。フェイルオー
    バーの際に DNS 値をキャッシュする Java アプリケーションの管理方法の詳細につい
    ては、「AWS SDK for Java」を参照してください。
    https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html
    RDSのマニュアルなのになぜか
    「Javaの場合は注意しろ」とわざわざ書いてある(笑)
    19

    View Slide

  20. まずやるべきこと
    -Dnetworkaddress.cache.ttl=3
    デフォルトは”-1”
    つまりJVMが生きてる間はDNS検索結果を
    ずっとキャッシュするのがデフォルト
    20

    View Slide

  21. (講演後の追記)
    実は前の -Dnetworkaddress.cache.ttl=3 は嘘です。これじゃ設定できないっす。
    正確にはこんな感じのコードをpublic static void main(args)を持つクラスの最初の方に
    埋め込んでいます。
    java.security.Security.setProperty("networkaddress.cache.ttl", "3");
    java.security.Security.setProperty("networkaddress.cache.negative.ttl", "3");
    21

    View Slide

  22. 他にもまだあるんじゃね?
    22

    View Slide

  23. @Bean
    public DataSource dataSource() {
    ds = new BasicDataSource();
    ds.setUrl()...setUser()... setPassword()...
    ds.maxActive(10? 50? アプリによりけり)
    ds.setValidationQuery(“SELECT 1”)
    return new TransactionAwareDatasourceProxy(ds)
    } // えっ?これだけ?
    23

    View Slide

  24. commons-pool 1.x の他のパラメータ
    ● minEvictableIdleTimeMills
    ● numTestPerEvictionRun
    ● testWhileIdle
    ● validationQueryTimeout
    ● 他多数
    24

    View Slide

  25. commons-pool 2.x で増えたパラメータ
    ● fastFailValidation
    ● logAbandoned
    ● removeAbandonedOnBorrow
    ● 他多数
    25

    View Slide

  26. ● Tomcat-DBCPというのも速いらしい
    ● 最近はやはりHikariCPがデファクトらしい
    26

    View Slide

  27. commons-pool 1.x は2012年で打ち止め
    27

    View Slide

  28. クラウド時代のRDBに向かって
    7年前に開発打ち止めの
    コネクションプール機構を使い続けるとでも?
    28

    View Slide

  29. @Bean
    public DataSource dataSource() {
    conf = new HikariConfig();
    conf.setUrl()...setUser()...
    conf.setMaxIdle(10? 50? アプリによりけり)
    conf.setConnectionInitSql(...)
    conf.setConnectionTimeout(数秒)
    conf.setValidationTimeout(数秒)
    意外と少ない設
    定で良さげ
    29

    View Slide

  30. 1. ここまでで最低限の準備が完了
    2. ここからが本番の
    「RDSがフェイルオーバーしたときの
    エラーログアラートラッシュ緩和のための
    Spring-Retry」
    30

    View Slide

  31. ちょっと休憩
    時間を確認
    25分くらい?
    31

    View Slide

  32. @Configuration
    @EnableRetry
    public HogeConfig {... Javaコンフィグ ...}
    @Retryable(value = {FooException.class}, maxAttempts=3)
    public Bar barMethod(args...) {
    // なんか不安定かもしれない外部通信
    }
    32

    View Slide

  33. ● AOPはちょっぴり遅くなる
    ● RetryTemplateを明示的に使うほうが
    わかりやすくて確実
    33

    View Slide

  34. やりたいこと
    DB(RDS)
    JDBCドライバ
    コネプ
    アプリケーション
    DBコネクション取得失敗の場合
    に、4回までリトライする
    1sec後 -> 2sec -> 4sec -> 8sec
    34

    View Slide

  35. retryTemplate = new RetryTemplate();
    retryTemplate.setBackOffPolicy(省略);
    retryTemplate.setRetryPolicy(省略);
    例: Excepation.classはリトライ対象だが
    RuntimeExceptionは対象外にする、等
    まずRetryTemplateを準備しておく
    35

    View Slide

  36. spring-jdbc提供のDataSourceを拡張
    public class FooDataSource extends DelegatingDataSource {
    @Override
    public Connection getConnection() throws SQLException {
    return retryTemplate.execute(context -> {
    if (context.getRetryCount() > 0) { /* warnログなど */ }
    return super.getConnection();
    });
    36

    View Slide

  37. @Bean
    public java.sql.DataSource dataSource() {
    conf = new HikariConfig();
    conf.set…(jdbc-url, user, その他もろもろ)
    hikariDs = new HikariDataSource(conf);
    fooDs = new 前ページのFooDataSource(hikariDs);
    ds = new TransactionAwareDatasourceProxy(fooDs);
    return ds;
    37

    View Slide

  38. 手動でフェイルオーバーさせて試す
    38

    View Slide

  39. DBAさん
    39

    View Slide

  40. まとめ
    40

    View Slide

  41. ● クラウドの向こう側の障害が90秒で回復しても、
    それに依存する自分のアプリケーションも90秒で
    回復するとは限らない。
    ● フェイルオーバー試験するしかない。
    41

    View Slide

  42. AWS-SDKならその配布ライブラリ自体で
    リトライ機構が組み込み済みだが...
    aws-java-sdk-s3
    aws-java-sdk-sqs
    aws-java-sdk-rdb ?
    aws-java-sdk-jdbc ?
    存在しません
    42

    View Slide

  43. リトライは 最悪、無くてもいい。
    リトライがあれば、DBがfail overから復帰するまでの90
    秒のエラーログの飽和(からの精神的苦痛)をやわらげ
    ることができる
    DBCPの設定が
    ちゃんとできてれば
    43

    View Slide

  44. ほとんどのコードを書いてくれたS君に感謝
    (自分はほぼレビューのみ)
    44

    View Slide

  45. 週明け、皆さんのプロジェクトでやることは?
    ● DBCPライブラリ、何使ってるか確認する?
    ● DBCPの設定、確認する?
    ● fail over試験、する?
    ● (DBまわりに限らず)Spring-Retry どこかで使えそう?
    45

    View Slide

  46. ビズリーチでは
    エンジニアを募集しています
    46

    View Slide