かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その15 )( Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする+domaGen タスクを doma-codegen-plugin を利用したものに作り直す )

概要

記事一覧はこちらです。

その14 ( Docker コンテナの image をバージョンアップする、Spring Boot Statistics のデータが表示されていない Panel を修正する+Dashboard に JVM (Micrometer) を追加する ) の続きです。

参照したサイト・書籍

  1. Doma 2 - User Documentation - Building an application - Build with Gradle
    https://doma.readthedocs.io/en/latest/build/?highlight=org.seasar.doma%3Adoma#build-with-gradle

  2. domaframework / doma-codegen-plugin
    https://github.com/domaframework/doma-codegen-plugin

  3. Doma入門 - ログライブラリにSLF4Jを使う
    https://qiita.com/nakamura-to/items/0f8195c45eb3630a8daf

  4. domaframework / getting-started
    https://github.com/domaframework/getting-started

  5. Doma入門
    https://qiita.com/nakamura-to/items/deaff05ba530317f3cf8

目次

  1. Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする
  2. domaGen タスクを doma-codegen-plugin を利用したものに作り直す
  3. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  4. 警告:[MissingSummary] A summary line is required on public/protected Javadocs. の警告が出力されないようにする

手順

Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする

https://doma.readthedocs.io/en/latest/build/?highlight=org.seasar.doma%3Adoma#build-with-gradle に従い build.gradle の以下の点を変更します。また Doma入門 - ログライブラリにSLF4Jを使うDoma 2 が SLF4J に対応したとの記事を読みました。org.seasar.doma:doma-slf4j を追加することにします。

..........

dependencies {
    def jdbcDriver = "org.postgresql:postgresql:42.2.14"
    def spockVersion = "1.3-groovy-2.5"
    def domaVersion = "2.44.3"
    def lombokVersion = "1.18.12"
    def errorproneVersion = "2.4.0"
    def powermockVersion = "2.0.7"
    def spotbugsVersion = "4.1.1"

    ..........

    // for Doma
    implementation("org.seasar.doma:doma-core:${domaVersion}")
    implementation("org.seasar.doma:doma-slf4j:${domaVersion}")
    annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}")
    domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")
    domaGenRuntime("${jdbcDriver}")
  • dependencies block の以下の点を変更します。
    • def domaVersion = "2.26.0"def domaVersion = "2.44.3" に変更します。
    • implementation("org.seasar.doma:doma:${domaVersion}")implementation("org.seasar.doma:doma-core:${domaVersion}") に変更します。
    • implementation("org.seasar.doma:doma-slf4j:${domaVersion}") を追加します。
    • annotationProcessor("org.seasar.doma:doma:${domaVersion}")annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}") に変更します。

domaGen タスクを doma-codegen-plugin を利用したものに作り直す

build.gradle を以下のように変更します。

buildscript {
    ..........
    dependencies {
        // for doma-codegen-plugin
        classpath "org.postgresql:postgresql:42.2.14"
    }
}

plugins {
    ..........
    id "com.gorylenko.gradle-git-properties" version "2.2.3"
    id "org.seasar.doma.codegen" version "1.2.1"
}

..........

configurations {
    compileOnly.extendsFrom annotationProcessor

    // annotationProcessor と testAnnotationProcessor、compileOnly と testCompileOnly を併記不要にする
    testAnnotationProcessor.extendsFrom annotationProcessor
    testImplementation.extendsFrom compileOnly

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}

..........

// for doma-codegen-plugin
// まず変更が必要なもの
def rootPackageName = "ksbysample.webapp.lending"
def rootPackagePath = "src/main/java/ksbysample/webapp/lending"
def dbUrl = "jdbc:postgresql://localhost/ksbylending"
def dbUser = "ksbylending_user"
def dbPassword = "xxxxxxxx"
def dbTableNamePattern = ".*"
//def dbTableNamePattern = "user_info"
// おそらく変更不要なもの
def packageEntityPath = rootPackagePath + "/entity"
def packageDaoPath = rootPackagePath + "/dao"
def importOfComponentAndAutowiredDomaConfig = "${rootPackageName}.util.doma.ComponentAndAutowiredDomaConfig"
def workPath = "work"
def workEntityPath = "${workPath}/entity"
def workDaoPath = "${workPath}/dao"
task domaGen(group: "doma code generation") {
    // このタスク自体は何もしない。実行する時の起点用タスクとして作成している。
}
task beforeDomaCodeGen {
    doLast {
        // 作業用ディレクトリを削除する
        delete "${workPath}"

        // 現在の dao, entity パッケージのバックアップを取得する
        copy() {
            from "${packageDaoPath}"
            into "${workDaoPath}/org"
        }
        copy() {
            from "${packageEntityPath}"
            into "${workEntityPath}/org"
        }

        // dao, entity パッケージを削除する
        delete "${packageDaoPath}"
        delete "${packageEntityPath}"
    }
}
domaCodeGen {
    db {
        url = "${dbUrl}"
        user = "${dbUser}"
        password = "${dbPassword}"
        tableNamePattern = "${dbTableNamePattern}"
        ignoredTableNamePattern = "flyway_schema_history|SPRING_SESSION.*"
        entity {
            packageName = "${rootPackageName}.entity"
            useListener = false
            useMappedSuperclass = false
        }
        dao {
            packageName = "${rootPackageName}.dao"
        }
    }
}
task afterDomaCodeGen {
    doLast {
        // 生成された Entity クラスを作業用ディレクトリにコピーし、
        // @SuppressWarnings({"PMD.TooManyFields"}) アノテーションを付加する
        copy() {
            from "${packageEntityPath}"
            into "${workEntityPath}/replace"
            filter {
                line ->
                    line.replaceAll('@Entity', '@SuppressWarnings({"PMD.TooManyFields"})\n@Entity')
            }
        }

        // 生成された Dao インターフェースからバックアップにあるクラスを削除する
        // ※生成済の Dao インターフェースを再生成したい場合には事前に削除すること!
        for (workDaoFile in new File("${workDaoPath}/org").listFiles()) {
            def packageDaoFile = new File("${packageDaoPath}/${workDaoFile.name}")
            if (packageDaoFile.exists()) {
                packageDaoFile.delete()
            }
        }

        // 生成された Dao インターフェースを作業用ディレクトリにコピーし、
        // @ComponentAndAutowiredDomaConfig アノテーションを付加し、
        // Javadoc の @param に説明文を追加する
        copy() {
            from "${packageDaoPath}"
            into "${workDaoPath}/replace"
            filter {
                line ->
                    line.replaceAll('import org.seasar.doma.Dao;', "import ${importOfComponentAndAutowiredDomaConfig};\nimport org.seasar.doma.Dao;")
                            .replaceAll('@Dao', '@Dao\n@ComponentAndAutowiredDomaConfig')
                            .replaceAll('@param (\\S+)$', '@param $1 $1')
            }
        }

        // 元々 dao, entity パッケージ内にあったファイルを元に戻す
        copy() {
            from "${workDaoPath}/org"
            into "${packageDaoPath}"
        }
        copy() {
            from "${workEntityPath}/org"
            into "${packageEntityPath}"
        }

        // @ComponentAndAutowiredDomaConfig アノテーションを付加した Dao インターフェースを
        // dao パッケージへ戻す
        copy() {
            from "${workDaoPath}/replace"
            into "${packageDaoPath}"
        }

        // @SuppressWarnings({"PMD.TooManyFields"}) アノテーションを付加した Entity クラスを
        // entity パッケージへ戻す
        copy() {
            from "${workEntityPath}/replace"
            into "${packageEntityPath}"
        }

        // 作業用ディレクトリを削除する
        delete "${workPath}"
    }
}
// beforeDomaCodeGen --> domaCodeGenDbEntity --> domaCodeGenDbDao --> domaGen --> afterDomaCodeGen
domaCodeGenDbEntity.dependsOn beforeDomaCodeGen
domaCodeGenDbDao.dependsOn domaCodeGenDbEntity
domaGen.dependsOn domaCodeGenDbDao
domaGen.finalizedBy afterDomaCodeGen

..........
  • buildscript block に dependencies { classpath "org.postgresql:postgresql:42.2.14" } を追加します。
  • plugins block に id "org.seasar.doma.codegen" version "1.2.1" を追加します。
  • configurations block から domaGenRuntime を削除します。
  • dependencies block から以下の2行を削除します。
    • domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")
    • domaGenRuntime("${jdbcDriver}")
  • // for doma-codegen-plugindomaGen.finalizedBy afterDomaCodeGen の部分を追加します。
    • 実現したい内容は以下の点でした。
      • Entity クラス、Dao インターフェースは doma-codegen-plugin で既存のテーブルから生成する。
      • 生成された Entity クラス には @SuppressWarnings({"PMD.TooManyFields"}) を追加する。
      • 生成された Dao インターフェースには @ComponentAndAutowiredDomaConfig とその import 文を追加する。
    • Spring Boot + npm + Geb で入力フォームを作ってテストする ( その91 )( Doma 2 を 2.28.0 → 2.34.0 へバージョンアップする+domaGen タスクを doma-codegen-plugin を利用したものに作り直す ) で1度変更版を作成しましたが、domaGen タスクを何度も実行すると Enttiy クラスの @SuppressWarnings({"PMD.TooManyFields"}) や Dao インターフェースの @ComponentAndAutowiredDomaConfig が何度も追加されるという問題があることに今回見直していて気づきました。
    • そこで以下のように修正しています。
      • Dao インターフェースだけでなく Entity クラスもバックアップを取得する。
      • doma-codegen-plugin のタスク実行前に dao、entity パッケージを丸ごと削除する(dbTableNamePattern 変数に設定したテーブルの Dao インターフェース、Entity クラスだけが dao、entity パッケージに作成されるようにする)。
      • 既に生成したことがある Dao インターフェースの再生成は禁止したいので、afterDomaCodeGen タスク内でバックアップに存在する Dao インターフェースは dao パッケージから削除する。

変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

今回改修した domaGen タスクでは dao、entity パッケージの下には何も変更が入っていない状態で、

f:id:ksby:20201223231110p:plain

domaGen タスクを実行しても、

f:id:ksby:20201223231239p:plain

dao、entity パッケージの下には何も変更はありません(色の付いたクラス、インターフェースがありません)。

f:id:ksby:20201223231336p:plain

user_info テーブルに test_column カラムを追加してから、

f:id:ksby:20201223231920p:plain

domaGen タスクを実行すると、

f:id:ksby:20201223232327p:plain

Dao インターフェースはそのままで UserInfo Entity クラスだけに変更が入ります。

f:id:ksby:20201223232814p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージは出力されたのですが、警告:[MissingSummary] A summary line is required on public/protected Javadocs. (see http://google.github.io/styleguide/javaguide.html#s7.2-summary-fragment) という警告メッセージも出力されました。compileJava タスクで出力されているので Error Prone が出力しているようです。

f:id:ksby:20201223234656p:plain

警告:[MissingSummary] A summary line is required on public/protected Javadocs. の警告が出力されないようにする

今回変更しているのは build.gradle と Entity クラス(上には記述していませんが domaGen タスクで作り直しています)で、http://google.github.io/styleguide/javaguide.html#s7.2-summary-fragment を見たところ、Entity クラスのクラスコメントが空だったことが原因でした。

f:id:ksby:20201223235314p:plain

??? を書いておくことにします。

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると今度は警告メッセージは出力されませんでした。

f:id:ksby:20201224000205p:plain

履歴

2020/12/24
初版発行。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その14 )( Docker コンテナの image をバージョンアップする、Spring Boot Statistics のデータが表示されていない Panel を修正する+Dashboard に JVM (Micrometer) を追加する )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その13 )( Docker コンテナの image をバージョンアップする、Grafana の RabbitMQ 用の Dashboard を RabbitMQ Monitoring → RabbitMQ-Overview に切り替える ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Grafana の Dashboard の Spring Boot Statistics にデータが表示されていない Panel があるので表示されるように修正します。
    • Grafana の DashboardJVM (Micrometer) を追加します。

参照したサイト・書籍

  1. Actuator metrics do not include http.server.requests
    https://stackoverflow.com/questions/60345738/actuator-metrics-do-not-include-http-server-requests

  2. micrometer-metrics / micrometer
    https://github.com/micrometer-metrics/micrometer

  3. Spring Boot default metrics
    https://tomgregory.com/spring-boot-default-metrics/

目次

  1. Spring Boot Statistics のデータが表示されていない Panel を修正する
    1. Process Open Files
    2. $memory_pool_nonheap (non-heap)
    3. Classes Loaded、Classes Unloaded
    4. Threads
    5. 「HikariCP Statistics」の下の全ての Panel
    6. 「HTTP Statistics」の下の全ての Panel
    7. 「Tomcat Statistics」の下の全ての Panel
  2. Dashboard に JVM (Micrometer) を追加する

手順

Spring Boot Statistics のデータが表示されていない Panel を修正する

docker-compose up -d コマンドでコンテナを起動+IntelliJ IDEA から Web アプリを起動して作業します。

Process Open Files

Edit 画面で参照している metrics を確認すると process_files_openprocess_files_max の2つでした。

f:id:ksby:20201220164659p:plain

http://localhost:8080/actuator/prometheus にアクセスして出力されている metrics を確認してみましたが、どちらもありません。。。

調べていた時に Actuator metrics do not include http.server.requests を見つけました。/acutator/metrics という endpoint があるらしく、この endpoint にアクセスすると取得可能な metrics 一覧が出力されますが process_files_open ではなく process.files.open と表示されるようです。

micrometer-metrics / micrometerprocess.files.open で検索してみると micrometer/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/FileDescriptorMetrics.java がヒットしましたが、この中に this.osBeanClass = getFirstClassFound(UNIX_OPERATING_SYSTEM_BEAN_CLASS_NAMES); というコードがありました。おそらく Web アプリを Unix 系の OS で動作させた時しか process_files_openprocess_files_max は取れないのでしょう。

試してみます。まず /acutator/metrics の endpoint を使用できるようにするために src/main/resources/application.properties の management.endpoints.web.exposure.include に metrics を追加します。

..........

management.endpoints.web.exposure.include=health,info,loggers,prometheus,metrics
management.metrics.tags.application=lending
..........

コンテナで Web アプリを起動する時の JDK を AdoptOpenJDK 11.0.9.1+1 にします。docker/app/Dockerfile の以下の点を変更します。

FROM adoptopenjdk/openjdk11:jdk-11.0.9.1_1-alpine-slim
RUN apk add --no-cache tzdata
ENV TZ="Asia/Tokyo"
ENV LANG="ja_JP.UTF-8"
VOLUME /tmp
EXPOSE 8080
ENTRYPOINT ["docker-entrypoint.sh"]
  • FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine-slimFROM adoptopenjdk/openjdk11:jdk-11.0.9.1_1-alpine-slim に変更します。

app コンテナを起動する時の jar ファイルを ksbysample-webapp-lending-2.3.7-RELEASE.jar にします。docker-compose.app.yml の以下の点を変更します。

  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    image: ksbysample-webapp-lending
    volumes:
      - ./build/libs/ksbysample-webapp-lending-2.3.7-RELEASE.jar:/app.jar
      - ./docker/app/docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh
    environment:
      - SPRING_DATASOURCE_HIKARI_JDBC_URL=jdbc:postgresql://postgresql/ksbylending
      - SPRING_MAIL_HOST=mail-server
      - SPRING_RABBITMQ_HOST=haproxy
    deploy:
      mode: replicated
      replicas: 3
    # entrypoint: /bin/sh
    # stdin_open: true
    # tty: true

  haproxy-app:
    image: haproxy:2.3.2-alpine
    container_name: haproxy-app
    volumes:
      - ./docker/app/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    ports:
      - "8080:8080"
    depends_on:
      - app
  ..........
  • app コンテナの volumes の設定で - ./build/libs/ksbysample-webapp-lending-2.2.2-RELEASE.jar:/app.jar- ./build/libs/ksbysample-webapp-lending-2.3.7-RELEASE.jar:/app.jar に変更します。
  • haproxy-app コンテナの image の設定で haproxy:2.1.2-alpinehaproxy:2.3.2-alpine に変更します。

以下の手順で Alpine Linux 上で Web アプリを起動します。

  1. Gradle の build コマンドで ksbysample-webapp-lending-2.3.7-RELEASE.jar を生成する。
  2. docker-compose -f docker-compose.app.yml --compatibility build --no-cache コマンドを実行して app コンテナ起動用の Docker image を作成する。
  3. docker-compose -f docker-compose.mail.yml up -d コマンドを実行してメールサーバのコンテナを起動する。
  4. docker-compose -f docker-compose.app.yml --compatibility up -d コマンドを実行して app コンテナを起動する。

http://localhost:8080/actuator/metrics にアクセスすると以下の JSON が出力され、process.files.openprocess.files.max が入っていました。

{
  "names": [
    "hikaricp.connections",
    "hikaricp.connections.acquire",
    "hikaricp.connections.active",
    "hikaricp.connections.creation",
    "hikaricp.connections.idle",
    "hikaricp.connections.max",
    "hikaricp.connections.min",
    "hikaricp.connections.pending",
    "hikaricp.connections.timeout",
    "hikaricp.connections.usage",
    "http.server.requests",
    "jdbc.connections.active",
    "jdbc.connections.idle",
    "jdbc.connections.max",
    "jdbc.connections.min",
    "jvm.buffer.count",
    "jvm.buffer.memory.used",
    "jvm.buffer.total.capacity",
    "jvm.classes.loaded",
    "jvm.classes.unloaded",
    "jvm.gc.live.data.size",
    "jvm.gc.max.data.size",
    "jvm.gc.memory.allocated",
    "jvm.gc.memory.promoted",
    "jvm.gc.pause",
    "jvm.memory.committed",
    "jvm.memory.max",
    "jvm.memory.used",
    "jvm.threads.daemon",
    "jvm.threads.live",
    "jvm.threads.peak",
    "jvm.threads.states",
    "logback.events",
    "process.cpu.usage",
    "process.files.max",
    "process.files.open",
    "process.start.time",
    "process.uptime",
    "rabbitmq.acknowledged",
    "rabbitmq.acknowledged_published",
    "rabbitmq.channels",
    "rabbitmq.connections",
    "rabbitmq.consumed",
    "rabbitmq.failed_to_publish",
    "rabbitmq.not_acknowledged_published",
    "rabbitmq.published",
    "rabbitmq.rejected",
    "rabbitmq.unrouted_published",
    "system.cpu.count",
    "system.cpu.usage",
    "system.load.average.1m",
    "tomcat.sessions.active.current",
    "tomcat.sessions.active.max",
    "tomcat.sessions.alive.max",
    "tomcat.sessions.created",
    "tomcat.sessions.expired",
    "tomcat.sessions.rejected"
  ]
}

ただし Prometheus の画面で検索すると process_files_open はなく process_files_open_files になっていました。process_files_maxprocess_files_max_files でした。

f:id:ksby:20201220192823p:plain f:id:ksby:20201220192920p:plain

Edit 画面で参照する metrics を process_files_open_filesprocess_files_max_files に変更すると「Process Open Files」に metrics が表示されるようになりました。

f:id:ksby:20201220193344p:plain f:id:ksby:20201220193643p:plain

$memory_pool_nonheap (non-heap)

Edit 画面で参照している metrics を確認すると以下の Query が記述されていました。

  • jvm_memory_used_bytes{instance="$instance", application="$application", id="$memory_pool_nonheap"}
  • jvm_memory_committed_bytes{instance="$instance", application="$application", id="$memory_pool_nonheap"}
  • jvm_memory_max_bytes{instance="$instance", application="$application", id="$memory_pool_nonheap"}

f:id:ksby:20201220200956p:plain

Query で使用されている Variable $memory_pool_nonheap の定義を見ると以下のようになっていました。「Preview of values」に値が複数表示されています。

f:id:ksby:20201220201212p:plain

Query で参照している Variable $memory_pool_nonheap が復数の値を返すのに、Query で単一の値が返る想定の記述がされているのが原因でした。 id="$memory_pool_nonheap"id=~"$memory_pool_nonheap" のように変更することにします。

f:id:ksby:20201220202727p:plain f:id:ksby:20201220202822p:plain

Classes Loaded、Classes Unloaded

Edit 画面で参照している metrics を確認すると以下の Query が記述されていました。

  • irate(jvm_classes_unloaded_total{instance="$instance", application="$application"}[5m])
  • jvm_classes_loaded{instance="$instance", application="$application"}

f:id:ksby:20201220212717p:plain f:id:ksby:20201220212821p:plain

Prometheus の画面で確認すると jvm_classes_unloaded_totaljvm_classes_unloaded_classes_totaljvm_classes_loadedjvm_classes_loaded_classes に変更されていました。

f:id:ksby:20201220213304p:plain f:id:ksby:20201220213412p:plain

Edit 画面で参照している metrics を修正します。

f:id:ksby:20201220213838p:plain f:id:ksby:20201220214455p:plain

f:id:ksby:20201220214234p:plain f:id:ksby:20201220214600p:plain

Threads

Edit 画面で参照している metrics を確認すると以下の Query が記述されていました。

  • jvm_threads_daemon{instance="$instance", application="$application"}
  • jvm_threads_live{instance="$instance", application="$application"}
  • jvm_threads_peak{instance="$instance", application="$application"}

f:id:ksby:20201220215532p:plain

Prometheus の画面で確認すると jvm_threads_daemonjvm_threads_daemon_threadsjvm_threads_livejvm_threads_live_threadsjvm_threads_peakjvm_threads_peak_threads に変更されていました。

f:id:ksby:20201220215928p:plain f:id:ksby:20201220220042p:plain f:id:ksby:20201220220139p:plain

Edit 画面で参照している metrics を修正します。

f:id:ksby:20201220220421p:plain f:id:ksby:20201220220539p:plain

「HikariCP Statistics」の下の全ての Panel

今見たら表示されていました。IntelliJ IDEA から Web アプリを起動している時は表示されず、jar ファイルから起動している時は表示される metrics でした(Windows でも Linux でも表示されました)。

「HTTP Statistics」の下の全ての Panel

こちらも今見たら表示されていました。IntelliJ IDEA から Web アプリを起動している時は表示されず、jar ファイルから起動している時は表示される metrics でした(Windows でも Linux でも表示されました)。

Tomcat Statistics」の下の全ての Panel

Edit 画面で参照している metrics を確認すると以下の Query が記述されていました。

f:id:ksby:20201220224040p:plain

  • Total Error Count
    • tomcat_global_error_total{instance="$instance", application="$application"}
  • Thread Config Max
    • tomcat_threads_config_max{instance="$instance", application="$application"}
  • Active Sessions
    • tomcat_sessions_active_current{instance="$instance", application="$application"}
  • Sent & Recieved Bytes
    • irate(tomcat_global_sent_bytes_total{instance="$instance", application="$application"}[5m])
    • irate(tomcat_global_received_bytes_total{instance="$instance", application="$application"}[5m])
  • Threads
    • tomcat_threads_current{instance="$instance", application="$application"}
    • tomcat_threads_busy{instance="$instance", application="$application"}

Prometheus の画面で確認すると tomcat_sessions_active_currenttomcat_sessions_active_current_sessions に変更すれば良いのですが、それ以外の metrics はそもそも出力されていませんでした。

Web で検索すると Disable Tomcat's MBean Registry by default and provide a property to enable it の Issue が見つかり、Spring Boot の Manual の Common Application properties の 11. Server Propertiesserver.tomcat.mbeanregistry.enabled が見つかりました。default は false なので true にすれば良いようです。

src/main/resources/application.properties に server.tomcat.mbeanregistry.enabled=true を追加します。

..........

management.endpoints.web.exposure.include=health,info,loggers,prometheus,metrics
management.metrics.tags.application=lending
management.endpoint.health.show-details=always
management.endpoint.health.probes.enabled=true
management.endpoint.health.group.liveness.include=livenessStateProbeIndicator,cacheCheck
management.endpoint.health.group.readiness.include=readinessStateProbeIndicator,cacheCheck
server.tomcat.mbeanregistry.enabled=true

..........

Gradle の build タスクを実行して jar ファイルを作成し直した後、docker-compose -f docker-compose.app.yml --compatibility downdocker-compose -f docker-compose.app.yml --compatibility up -d コマンドを実行して app コンテナを再起動します。

最後に Grafana の Edit 画面で参照する metrics を以下のように変更すると表示されるようになりました。

  • Total Error Count
    • tomcat_global_error_total{instance="$instance", application="$application"}
  • Thread Config Max
    • tomcat_threads_config_max_threads{instance="$instance", application="$application"}
  • Active Sessions
    • tomcat_sessions_active_current_sessions{instance="$instance", application="$application"}
  • Sent & Recieved Bytes
    • irate(tomcat_global_sent_bytes_total{instance="$instance", application="$application"}[5m])
    • irate(tomcat_global_received_bytes_total{instance="$instance", application="$application"}[5m])
  • Threads
    • tomcat_threads_current_threads{instance="$instance", application="$application"}
    • tomcat_threads_busy_threads{instance="$instance", application="$application"}

f:id:ksby:20201220232236p:plain

DashboardJVM (Micrometer) を追加する

「Import」画面で「Import via grafana.com」に 4701 を入力して import します。

f:id:ksby:20201220235011p:plain f:id:ksby:20201220235102p:plain

JVM (Micrometer) の画面が表示されます(面倒なので画面キャプチャは1画面目のみ)。

f:id:ksby:20201220235253p:plain

履歴

2020/12/20
初版発行。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その13 )( Docker コンテナの image をバージョンアップする、Grafana の RabbitMQ 用の Dashboard を RabbitMQ Monitoring → RabbitMQ-Overview に切り替える )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その12 )( Docker コンテナの image をバージョンアップする、prometheus・grafana 編 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Grafana の RabbitMQ 用の Dashboard を RabbitMQ Monitoring → RabbitMQ-Overview に切り替えます。
    • RabbitMQ 3.8 から support された Monitoring with Prometheus & Grafana の機能を利用して metrics を収集する方式に変更します。rabbitmq_exporter を削除します。

参照したサイト・書籍

  1. Monitoring with Prometheus & Grafana
    https://www.rabbitmq.com/prometheus.html

目次

  1. rabbitmq_prometheus plugin が有効になっていることを確認する
  2. rabbitmq-diagnostics -q cluster_status コマンドで Cluster Name を確認する
  3. docker/prometheus/prometheus.yml を変更する
  4. docker-compose.yml を変更する
  5. docker-compose up -d コマンドを実行する
  6. RabbitMQ Monitoring → RabbitMQ-Overview に切り替える
  7. kbudde/rabbitmq-exporter の docker image を削除する

手順

rabbitmq_prometheus plugin が有効になっていることを確認する

RabbitMQ は起動時のログに有効になっている plugin 一覧を出力してくれるので、docker-compose up -d コマンドで起動して確認してみます。

f:id:ksby:20201220092054p:plain

確かに rabbitmq_prometheus が出力されていました。4つ出力されているのは前から気づいていたのですが、prometheus の文字が入った plugin があることに全く気づいていなかったですね。。。

rabbitmq-diagnostics -q cluster_status コマンドで Cluster Name を確認する

https://www.rabbitmq.com/prometheus.html#installation を見ると rabbitmq-diagnostics -q cluster_status コマンドで Cluster Name を確認できるようなので確認してみます。

docker exec -it rabbitmq1 /bin/sh コマンドで rabbitmq1 コンテナに接続してから rabbitmq-diagnostics -q cluster_status コマンドを実行すると Cluster Name は rabbit@rabbitmq1 でした。これは変更せずにこのまま進めます。

f:id:ksby:20201220092921p:plain

docker/prometheus/prometheus.yml を変更する

Prometheus の RabbitMQ の metrics 取得先を rabbitmq_exporter コンテナから rabbitmq1~3 コンテナに変更します。

https://www.rabbitmq.com/prometheus.html#installationNotice that RabbitMQ exposes the metrics on a dedicated TCP port, 15692 by default. と記述されていますので、docker/prometheus/prometheus.yml を以下のように変更します。

..........

- job_name: 'rabbitmq'
  static_configs:
    - targets:
        - rabbitmq1:15692
        - rabbitmq2:15692
        - rabbitmq3:15692

..........
  • job_name: 'rabbitmq_exporter'job_name: 'rabbitmq' に変更します。
  • targets は ['rabbitmq_exporter:9419'] の記述を削除し、以下の3行を追加します。
    • rabbitmq1:15692
    • rabbitmq2:15692
    • rabbitmq3:15692

docker-compose.yml を変更する

rabbitmq_exporter コンテナの記述を削除します。

docker-compose up -d コマンドを実行する

docker-compose up -d コマンドを実行してコンテナを起動します。

RabbitMQ Monitoring → RabbitMQ-Overview に切り替える

「Import」画面で「Import via grafana.com」に 10991 を入力して import します。

f:id:ksby:20201220102527p:plain f:id:ksby:20201220102620p:plain

RabbitMQ-Overview の画面が表示されます。

f:id:ksby:20201220103417p:plain f:id:ksby:20201220103515p:plain f:id:ksby:20201220103623p:plain f:id:ksby:20201220103723p:plain f:id:ksby:20201220103819p:plain

rabbitmq3 コンテナを停止すると Nodes の数が 3 → 2 に変わり、NODES の一覧から rabbitmq3 が消えました。

f:id:ksby:20201220104414p:plain f:id:ksby:20201220104608p:plain

「Dashboards」-「Manage」の画面で「RabbitMQ Monitoring」を削除します。

kbudde/rabbitmq-exporter の docker image を削除する

以下の docker image を削除します。

  • kbudde/rabbitmq-exporter:latest

履歴

2020/12/20
初版発行。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その12 )( Docker コンテナの image をバージョンアップする、prometheus・grafana 編 )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その11 )( Docker コンテナの image をバージョンアップする、rabbitmq・haproxy・rabbitmq_exporter 編 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 今回は以下の Docker コンテナの image をバージョンアップします。
      • prom/prometheus
      • grafana/grafana

参照したサイト・書籍

目次

  1. docker-compose.yml を変更する
  2. docker-compose up -d コマンドを実行する
  3. Grafana の各 dashboard を確認する
    1. PostgreSQL Statistics
    2. Prometheus Redis
    3. RabbitMQ Monitoring
    4. Spring Boot Statistics
  4. PostgreSQL Statistics → PostgreSQL Database に切り替える
  5. Redis Dashboard for Prometheus Redis Exporter 1.x → Redis Dashboard for Prometheus Redis Exporter (helm stable/redis-ha) に切り替える
  6. 変更前の docker image を削除する
  7. 続く。。。

手順

docker-compose.yml を変更する

  prometheus:
    image: prom/prometheus:v2.23.0
    container_name: prometheus
    ports:
      - "9090:9090"
    # TZ=Asia/Tokyo を設定してみたが日本時間に変わらなかったのでコメントアウトしておく
    # environment:
    #   - TZ=Asia/Tokyo
    volumes:
      - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./docker/prometheus/storage:/prometheus
    extra_hosts:
      - "app:${HOST_IP_ADDRESS}"

  grafana:
    image: grafana/grafana:7.3.6
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/grafana/storage:/var/lib/grafana
  • image: prom/prometheus:v2.15.1image: prom/prometheus:v2.23.0 に変更します。
  • image: grafana/grafana:6.5.2image: grafana/grafana:7.3.6 に変更します。

docker-compose up -d コマンドを実行する

以下のコマンドを実行して docker image を更新・ダウンロードします(画面キャプチャはなし)。

  1. docker-compose up -d コマンドを実行してコンテナ一式(メールサーバ・rainloop を除く)を起動します。

Grafana の各 dashboard を確認する

PostgreSQL Statistics

f:id:ksby:20201219181315p:plain

Prometheus Redis

f:id:ksby:20201219183409p:plain

  • 以下の問題がありました。
    • 画面上部の Variables の addr に何も表示されていませんでした。
    • 以下の Panel にデータが表示されていませんでした。
      • Uptime
      • Clients
      • Command Calls / sec
  • 使用しているのは Redis Dashboard for Prometheus Redis Exporter 1.x、https://grafana.com/grafana/dashboards/763
  • 最新は Revision 3、Created July 3rd 2019, 2:07 am
  • https://grafana.com/grafana/dashboardsRedis で検索して、ヒットした中で一番 Downloads が多いものを確認すると(AWS や Azure が付くものは除く)、Redis Dashboard for Prometheus Redis Exporter (helm stable/redis-ha)、https://grafana.com/grafana/dashboards/11835
  • Redis Dashboard for Prometheus Redis Exporter (helm stable/redis-ha) の最新は Revision 1、Created March 2nd 2020, 7:37 pm
  • 今回は Redis Dashboard for Prometheus Redis Exporter 1.x を削除して Redis Dashboard for Prometheus Redis Exporter (helm stable/redis-ha) に切り替えることにします。

RabbitMQ Monitoring

f:id:ksby:20201219184648p:plain

  • 以下の問題がありました。
    • 以下の Panel にデータが表示されていませんでした。
      • Connections, channels and consumers
    • 画面上部の rabbit@rabbitmq1、rabbit@rabbitmq2、rabbit@rabbitmq3 の Panel はデータが表示されたりされなかったりします。
  • 使用しているのは RabbitMQ Monitoring、https://grafana.com/grafana/dashboards/4279
  • 最新は Revision 4、Created January 18th 2020, 12:22 am
  • https://grafana.com/grafana/dashboardsRabbitMQ で検索して、ヒットした中で一番 Downloads が多いものを確認すると(AWS や Azure が付くものは除く)、RabbitMQ-Overview、https://grafana.com/grafana/dashboards/10991
  • RabbitMQ-Overview の最新は Revision 7、Created November 13th 2020, 9:57 pm
  • RabbitMQ-Overview の説明を読むと RabbitMQ 3.8 から Prometheus & Grafana がサポートされていて(Monitoring with Prometheus & Grafana に記述があります)、rabbitmq-prometheus を有効にする必要があるとのこと。
  • 今回は RabbitMQ Monitoring を削除して RabbitMQ-Overview に切り替えることにします。

Spring Boot Statistics

f:id:ksby:20201219195225p:plain

  • 以下の問題がありました。
    • 以下の Panel にデータが表示されていませんでした。
      • Process Open Files
      • $memory_pool_nonheap (non-heap)
      • Classes Loaded
      • Classes Unloaded
      • Threads
      • 「HikariCP Statistics」の下の全ての Panel
      • 「HTTP Statistics」の下の全ての Panel
      • Tomcat Statistics」の下の全ての Panel
  • 使用しているのは Spring Boot Statistics、https://grafana.com/grafana/dashboards/6756
  • 最新は Revision 2、Created July 2nd 2018, 5:53 pm
  • https://grafana.com/grafana/dashboardsSpring Boot で検索して、ヒットした中で一番 Downloads が多いものを確認すると(AWS や Azure が付くものは除く)、JVM (Micrometer)、https://grafana.com/grafana/dashboards/4701
  • JVM (Micrometer) の最新は Revision 9、Created November 4th 2019, 1:59 am
  • ただしこれは JVM の情報のみです。
  • また検索結果を見ると Spring Boot Statistics、https://grafana.com/grafana/dashboards/12464 があり、This is a fork of dashboard 6756, fixed for Spring Boot 2.3 and support for Jetty instead of Tomcat. という記述がありました。使用しているのは Tomcat なので、これは選択できませんね。
  • 今回は Spring Boot Statistics は残してデータが表示されていない Panel を修正しつつ、JVM (Micrometer) を追加してみることにします。

PostgreSQL Statistics → PostgreSQL Database に切り替える

最初に PostgreSQL DatabaseDashboard に追加します。

画面左側のメニューから「Dashboards」-「Manage」をクリックします。

f:id:ksby:20201219213010p:plain

下の画面が表示されるので、「Import」ボタンをクリックします。

f:id:ksby:20201219213144p:plain

「Import」画面が表示されるので「Import via grafana.com」に 9628 を入力後「Load」ボタンをクリックします。

f:id:ksby:20201219213519p:plain

「DS_PROMETHEUS」で「spring-actuator」を選択した後、「Import」ボタンをクリックします。

f:id:ksby:20201219213752p:plain

PostgreSQL Database の画面が表示されます。画面右上を「Last 6 hours」「10s」→「Last 15 minutes」「5s」に変更しています。

f:id:ksby:20201219215859p:plain

次に PostgreSQL Statistics を削除します。

「Dashboards」-「Manage」の画面で「PostgreSQL Statistics」をチェックした後、「Delete」ボタンをクリックして削除します。

f:id:ksby:20201219220853p:plain

Redis Dashboard for Prometheus Redis Exporter 1.x → Redis Dashboard for Prometheus Redis Exporter (helm stable/redis-ha) に切り替える

「Import」画面で「Import via grafana.com」に 9628 を入力して import します。

f:id:ksby:20201219223530p:plain f:id:ksby:20201219223657p:plain

Redis Dashboard for Prometheus Redis Exporter (helm stable/redis-ha) の画面が表示されます。画面右上を「Last 24 hours」「30s」→「Last 15 minutes」「5s」に変更しています。

f:id:ksby:20201219224148p:plain

「Dashboards」-「Manage」の画面で「Prometheus Redis」を削除します。

変更前の docker image を削除する

以下の docker image を削除します。

  • prom/prometheus:v2.15.1
  • grafana/grafana:6.5.2

続く。。。

RabbitMQ Monitoring → RabbitMQ-Overview 切替、Spring Boot Statistics のデータが表示されていない Panel の修正+JVM (Micrometer) 追加、の2つは次回以降に記載します。

履歴

2020/12/19
初版発行。
2020/12/20
変更前の docker image を削除する を追加しました。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その11 )( Docker コンテナの image をバージョンアップする、rabbitmq・haproxy・rabbitmq_exporter 編 )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その10 )( Spring Boot を 2.3.2 → 2.3.7 へバージョンアップする+Docker コンテナの image をバージョンアップする、redis・redis_exporter 編 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 今回は以下の Docker コンテナの image をバージョンアップします。
      • rabbitmq
      • haproxy
      • kbudde/rabbitmq-exporter

参照したサイト・書籍

目次

  1. .env を変更する
  2. docker-compose.yml を変更する
  3. docker-compose up -d コマンドを実行する
  4. rabbitmq が起動しない。。。
  5. 環境変数 RABBITMQ_ERLANG_COOKIE をやめて .erlang.cookie file に変更する
  6. HTTP access denied: user 'rabbitmq' - invalid credentials が出力されないようにする+管理画面からログインできるようにする
  7. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  8. 変更前の docker image を削除する

手順

.env を変更する

..........

RABBITMQ_VERSION=3.8.9-management
RABBITMQ_ERLANG_COOKIE=Uzkm93w5e1Lz8AcP
RABBITMQ_DEFAULT_USER=rabbitmq
RABBITMQ_DEFAULT_PASS=12345678
RABBITMQ_DEFAULT_VHOST=/

..........
  • RABBITMQ_VERSION=3.8.2-managementRABBITMQ_VERSION=3.8.9-management に変更します。

docker-compose.yml を変更する

  ..........
  # http://localhost:1936/haproxy?stats
  haproxy:
    image: haproxy:2.3.2-alpine
    container_name: haproxy
    ports:
      - "1936:1936"
      - "5672:5672"
      - "15672:15672"
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    depends_on:
      - rabbitmq1
      - rabbitmq2
      - rabbitmq3
  ..........
  • image: haproxy:2.1.2-alpineimage: haproxy:2.3.2-alpine に変更します。

docker-compose up -d コマンドを実行する

以下のコマンドを実行して docker image を更新・ダウンロードします(画面キャプチャはなし)。

  1. docker-compose build --no-cache コマンドを実行し、Dockerfile で作成している image を更新します。
  2. kbudde/rabbitmq-exporter は latest の docker image をダウンロードしているので、ローカルの docker image を削除します。
  3. docker-compose up -d コマンドを実行してコンテナ一式(メールサーバ・rainloop を除く)を起動します。

rabbitmq が起動しない。。。

docker-compose up -d コマンドを実行した後、haproxy の画面で rabbitmq が起動するのを待っても rabbitmq2、rabbitmq3 がいつまでたっても起動しません。

f:id:ksby:20201215003222p:plain

IntelliJ IDEA でコンテナの状況を確認すると rabbitmq2、rabbitmq3 は停止しており、

  • RABBITMQ_ERLANG_COOKIE env variable support is deprecated and will be REMOVED in a future version. Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead. というログが出力されていました。ただし、あくまでも deprecated なので起動しない原因ではないようです。
  • 起動しない理由は以下3つのいずれかのようです。
    • Target node is unreachable (e.g. due to hostname resolution, TCP connection or firewall issues)
    • CLI tool fails to authenticate with the server (e.g. due to CLI tool's Erlang cookie not matching that of the server)
    • Target node is not running

f:id:ksby:20201215003616p:plain

環境変数 RABBITMQ_ERLANG_COOKIE をやめて .erlang.cookie file に変更する

deprecated のメッセージが出ているので、先に環境変数 RABBITMQ_ERLANG_COOKIE をやめて .erlang.cookie file に変更します。

docker/rabbitmq の下に .erlang.cookie を新規作成し、以下の内容を記述します。

Uzkm93w5e1Lz8AcP

.env から RABBITMQ_ERLANG_COOKIE=Uzkm93w5e1Lz8AcP を削除します。

RABBITMQ_VERSION=3.8.9-management
RABBITMQ_DEFAULT_USER=rabbitmq
RABBITMQ_DEFAULT_PASS=12345678
RABBITMQ_DEFAULT_VHOST=/

docker-compose.yml の rabbitmq1、rabbitmq2、rabbitmq3 の environment から - RABBITMQ_ERLANG_COOKIE を削除します。

  # RabbitMQ Clustering
  rabbitmq1:
    build:
      context: ./docker/rabbitmq
      args:
        - RABBITMQ_VERSION=${RABBITMQ_VERSION}
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
      - RABBITMQ_DEFAULT_VHOST
  rabbitmq2:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq2
    hostname: rabbitmq2
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /bin/sh -c /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1
  rabbitmq3:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq3
    hostname: rabbitmq3
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1

https://www.rabbitmq.com/clustering.html#cookie-file-locations を見ると .erlang.cookie は /var/lib/rabbitmq/.erlang.cookie に配置すると記述されているので、docker/rabbitmq/Dockerfile を以下のように変更します。

ARG RABBITMQ_VERSION
FROM rabbitmq:${RABBITMQ_VERSION}-alpine
RUN apk add --no-cache tzdata
COPY .erlang.cookie /var/lib/rabbitmq/
  • COPY .erlang.cookie /var/lib/rabbitmq/ を追加します。

docker-compose build --no-cache コマンドを実行してから docker-compose up -d コマンドを実行します。。。が、Cookie file /var/lib/rabbitmq/.erlang.cookie must be accessible by owner only というメッセージが表示されて rabbitmq が起動しません。

f:id:ksby:20201217003125p:plain

docker/rabbitmq/Dockerfile の最後に RUN ls -al /var/lib/rabbitmq/ を追加して .erlang.cookie の owner、permission を確認すると -rwxr-xr-x 1 root root でした。

f:id:ksby:20201217004205p:plain

owner/group は https://github.com/docker-library/rabbitmq/blob/master/3.8/alpine/Dockerfile を見ると addgroup、adduser コマンドで rabbitmq が指定されており、permission は -rw------- にすれば良いはずなので、docker/rabbitmq/Dockerfile を以下のように変更してみます。

ARG RABBITMQ_VERSION
FROM rabbitmq:${RABBITMQ_VERSION}-alpine
RUN apk add --no-cache tzdata
COPY --chown=rabbitmq:rabbitmq .erlang.cookie /var/lib/rabbitmq/
RUN chmod 600 /var/lib/rabbitmq/.erlang.cookie
RUN ls -al /var/lib/rabbitmq/
  • COPY コマンドに --chown=rabbitmq:rabbitmq オプションを追加します。
  • RUN chmod 600 /var/lib/rabbitmq/.erlang.cookie を追加します。

docker-compose build --no-cache コマンドを実行すると owner、group は rabbitmq に変更されましたが、permission は -rwxr-xr-x のままでした。。。

f:id:ksby:20201217005337p:plain

この permission を変更する方法が最初全然分からなかったのですが、いろいろ検索してみた結果、以下の方法で解消できました。

  • chmod not working correctly in Docker を読むと VOLUME /var/lib/rabbitmq が指定されているから RUN コマンドで chmod できないらしい。VOLUME コマンドで指定していないディレクトリで chmod してからコピーすればよいとのこと。
  • ただし Dockerfile 内で COPY --chown=rabbitmq:rabbitmq .erlang.cookie /tmp/RUN chmod 600 /tmp/.erlang.cookie の後に RUN cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/ を実行してもコピーされませんでした。これは Dockerfile ではなくコンテナ起動時に command あるいは entrypoint で実行するシェルスクリプトでやればコピーできます。

    f:id:ksby:20201217011651p:plain

最終的に以下のようになりました。

■docker/rabbitmq/Dockerfile

ARG RABBITMQ_VERSION
FROM rabbitmq:${RABBITMQ_VERSION}-alpine
RUN apk add --no-cache tzdata
COPY --chown=rabbitmq:rabbitmq .erlang.cookie /tmp/
RUN chmod 600 /tmp/.erlang.cookie
  • 以下の2行を追加しました。.erlang.cookie を /tmp にコピー後、owner を rabbitmq:rabbitmq へ、permission を -rw------- へ変更します。
    • COPY --chown=rabbitmq:rabbitmq .erlang.cookie /tmp/
    • RUN chmod 600 /tmp/.erlang.cookie

■docker-compose.yml

  # RabbitMQ Clustering
  rabbitmq1:
    build:
      context: ./docker/rabbitmq
      args:
        - RABBITMQ_VERSION=${RABBITMQ_VERSION}
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
      - RABBITMQ_DEFAULT_VHOST
    command:
      - /bin/sh
      - -c
      - |
        cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
        ls -al /var/lib/rabbitmq/
        rabbitmq-server
  rabbitmq2:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq2
    hostname: rabbitmq2
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1
  rabbitmq3:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq3
    hostname: rabbitmq3
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1
  • rabbitmq1 に command を追加しました。ここで /tmp/.erlang.cookie を /var/lib/rabbitmq/ の下へコピーした後、rabbitmq-server を起動します。
  • rabbitmq2 の entrypoint を /bin/sh -c /usr/local/bin/cluster-entrypoint.sh/usr/local/bin/cluster-entrypoint.sh に修正しました(rabbitmq3 と違っていたのと /bin/sh -c があるとなぜかうまく動作しなかったためです)。

■docker/rabbitmq/cluster-entrypoint.sh

#!/bin/bash

set -e

cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
ls -al /var/lib/rabbitmq/
rabbitmq-diagnostics erlang_cookie_sources

# Start RMQ from entry point.
# This will ensure that environment variables passed
# will be honored
rabbitmq-server -detached

# Wait a while for rabbitmq1 to start
sleep 15s

# Do the cluster dance
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmq1

# Stop the entire RMQ server. This is done so that we
# can attach to it again, but without the -detached flag
# making it run in the forground
rabbitmqctl stop

# Wait a while for the app to really stop
sleep 3s

# Start it
rabbitmq-server
  • 以下の3行を追加しました。/tmp/.erlang.cookie を /var/lib/rabbitmq/ の下へコピーします。また https://www.rabbitmq.com/clustering.html#cookie-file-troubleshooting に .erlang.cookie をチェックするコマンドが記載されていたのでそれも追加します。
    • cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
    • ls -al /var/lib/rabbitmq/
    • rabbitmq-diagnostics erlang_cookie_sources
  • /usr/local/bin/docker-entrypoint.sh rabbitmq-server -detachedrabbitmq-server -detached に変更します(/usr/local/bin/docker-entrypoint.sh がなくても動いたので削除しました)。また rabbitmq1 の起動が完了するまで時間がかかるため sleep 15s を追加しました。
  • https://www.rabbitmq.com/clustering.html#creating に記載があったので rabbitmqctl reset を追加しました。
  • rabbitmqctl stop の後の待機時間を sleep 2ssleep 3s に変更しました。

docker-compose build --no-cache コマンドを実行してから docker-compose up -d コマンドを実行すると無事 rabbitmq1、rabbitmq2、rabbitmq3 の全てが起動しました。

f:id:ksby:20201217083004p:plain

rabbitmq2 のログを見ると RABBITMQ_ERLANG_COOKIE env variable support is deprecated ... のメッセージは出力されておらずサーバが問題なく起動していますが、今度は HTTP access denied: user 'rabbitmq' - invalid credentials という warning が延々と出力されていました(この warning は rabbitmq1、rabbitmq3 にも出力されています)。

f:id:ksby:20201217083221p:plain f:id:ksby:20201217083353p:plain

rabbitmq の管理画面から rabbitmq / 12345678 でログインしようしてもログインできませんでした。

f:id:ksby:20201217083835p:plain

HTTP access denied: user 'rabbitmq' - invalid credentials が出力されないようにする+管理画面からログインできるようにする

使っている RabbitMQ のバージョンは違いますが、CentOS7 RabbitMQ 3.7.4 cluster installation and use の記事を見つけました。「Report an error」のところに記述があり、rabbitmqctl add_user コマンドで rabbitmq ユーザを作成すればよいみたいです。

docker-compose.yml の rabbitmq1 コンテナの command で rabbitmqctl add_user コマンドを実行してもエラーが出て登録できなかったので、rabbitmqctl add_user コマンド実行用のコンテナを作成して対応することにします。

docker/rabbitmq の下に create-user-entrypoint.sh を新規作成し、以下の内容を記述します。sleep の時間は 15s だと rabbitmq1 が起動完了する前に rabbitmqctl add_user コマンドを実行する時があったのでここでは 30s にしました。

#!/bin/bash

set -e

cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
ls -al /var/lib/rabbitmq/
rabbitmq-diagnostics erlang_cookie_sources

# Wait a while for rabbitmq1 to start
sleep 30s

rabbitmqctl -n rabbit@rabbitmq1 add_user ${RABBITMQ_DEFAULT_USER} ${RABBITMQ_DEFAULT_PASS}
rabbitmqctl -n rabbit@rabbitmq1 set_user_tags ${RABBITMQ_DEFAULT_USER} administrator
rabbitmqctl -n rabbit@rabbitmq1 set_permissions -p / ${RABBITMQ_DEFAULT_USER} ".*" ".*" ".*"

docker-compose.yml に rabbitmq-create-user コンテナの記述を追加します。

  # RabbitMQ Clustering
  rabbitmq1:
    build:
      context: ./docker/rabbitmq
      args:
        - RABBITMQ_VERSION=${RABBITMQ_VERSION}
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
      - RABBITMQ_DEFAULT_VHOST
    command:
      - /bin/sh
      - -c
      - |
        cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
        ls -al /var/lib/rabbitmq/
        rabbitmq-server
  rabbitmq-create-user:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq-create-user
    hostname: rabbitmq-create-user
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
    volumes:
      - ./docker/rabbitmq/create-user-entrypoint.sh:/usr/local/bin/create-user-entrypoint.sh
    entrypoint: /usr/local/bin/create-user-entrypoint.sh
    depends_on:
      - rabbitmq1
  rabbitmq2:
    ..........
  • 作成するユーザ名、パスワードは環境変数 RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS の設定をそのまま使っています。
  • rabbitmq1 コンテナの environment の RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS は不要なのでは?と思って削除したらエラーが出たので残しています。

動作確認します。docker-compose up -d コマンドを実行して起動した後、

f:id:ksby:20201218095100p:plain

rabbitmq-create-user コンテナのログを確認すると rabbitmqctl add_user コマンド等は全て正常に実行できており、

f:id:ksby:20201218095204p:plain

rabbitmq1、rabbitmq2 コンテナのログを見ると HTTP access denied: user 'rabbitmq' - invalid credentials は出力されていません。

f:id:ksby:20201218095618p:plain f:id:ksby:20201218095801p:plain

http://localhost:15672/ にアクセスして rabbitmq / 12345678 でログインすると無事ログインできました。

f:id:ksby:20201218100117p:plain f:id:ksby:20201218100204p:plain

rabbitmq_exporter の方は、Grafana で RabbitMQ の情報を表示させてみると問題なさそうです。

f:id:ksby:20201218102115p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20201218101652p:plain

変更前の docker image を削除する

以下の docker image を削除します。

  • rabbitmq:3.8.2-management-alpine
  • rabbitmq:3.8.2-management-alpine-custom

履歴

2020/12/18
初版発行。
2020/12/19
ユーザを作成できない場合があったため、docker/rabbitmq/create-user-entrypoint.sh 内の rabbitmq1 の起動待機時間を sleep 20ssleep 30s に変更しました。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その10 )( Spring Boot を 2.3.2 → 2.3.7 へバージョンアップする+Docker コンテナの image をバージョンアップする、redis・redis_exporter 編 )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その9 )( Docker コンテナの image をバージョンアップする、postgres・pgadmin4・flyway・docker-mailserver 編 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Spring Boot を 2.3.2 → 2.3.7 へバージョンアップします。
    • 今回は以下の Docker コンテナの image をバージョンアップします。
      • redis
      • oliver006/redis_exporter
  • Redis を 5 → 6 にバージョンアップしますが、spring-boot-starter-data-redis が利用している lettuce-core の release notes を見ると Lettuce 6 supports Redis 2.6+ up to Redis 6.x. の記述が出てくるのは 5.3.5.RELEASE からでした。現時点では spring-boot-starter-data-reids が 2.3.2.RELEASE、lettuce-core が 5.3.2-RELEASE であり、lettuce-core が 5.3.5-RELEASE になるのは spring-boot-starter-data-reids:2.3.5.RELEASE 以降です。
  • Redis のバージョンアップの前に Spring Boot を 2.3.2 → 2.3.7 へバージョンアップすることにします。
  • Redis 6.0.0 GA アップデート内容紹介 を読むと Redis 6 でかなり大きな機能追加が行われているとのことですが、この追加機能が利用できるようになるのが lettuce-core の 6.0.0 以降でした。lettuce-core が 6.0.0 以降になるのは Spring Boot 2.4 からなので、2.4 系にバージョンアップした時に新機能を試してみようと思います。

参照したサイト・書籍

目次

  1. Spring Boot を 2.3.2 → 2.3.7 へバージョンアップする
  2. .env を変更する
  3. docker-compose.yml を変更する
  4. docker-compose up -d コマンドを実行する
  5. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  6. 変更前の docker image を削除する

手順

Spring Boot を 2.3.2 → 2.3.7 へバージョンアップする

build.gradle の以下の点を変更します。

buildscript {
    ext {
        group "ksbysample"
        version "2.3.7-RELEASE"
    }
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/release/" }
        gradlePluginPortal()
    }
}

plugins {
    id "java"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.3.7.RELEASE"
    id "io.spring.dependency-management" version "1.0.10.RELEASE"
    id "groovy"
    id "checkstyle"
    id "com.github.spotbugs" version "4.5.0"
    id "pmd"
    id "net.ltgt.errorprone" version "1.2.1"
    id "com.gorylenko.gradle-git-properties" version "2.2.3"
}

..........
  • buildscript block の以下の点を変更します。
    • version "2.3.2-RELEASE"version "2.3.7-RELEASE"
  • plugins block の以下の点を変更します。
    • id "org.springframework.boot" version "2.3.2.RELEASE"id "org.springframework.boot" version "2.3.7.RELEASE"
    • id "io.spring.dependency-management" version "1.0.9.RELEASE"id "io.spring.dependency-management" version "1.0.10.RELEASE"

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20201214002327p:plain

gradlew dependencies を実行すると io.lettuce:lettuce-core:5.3.5.RELEASE が依存関係に追加されていることが確認できます。

+--- org.springframework.boot:spring-boot-starter-data-redis -> 2.3.7.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:2.3.7.RELEASE (*)
|    +--- org.springframework.data:spring-data-redis:2.3.6.RELEASE
|    |    +--- org.springframework.data:spring-data-keyvalue:2.3.6.RELEASE
|    |    |    +--- org.springframework.data:spring-data-commons:2.3.6.RELEASE (*)
|    |    |    +--- org.springframework:spring-context:5.2.12.RELEASE (*)
|    |    |    +--- org.springframework:spring-tx:5.2.12.RELEASE (*)
|    |    |    \--- org.slf4j:slf4j-api:1.7.26 -> 1.7.30
|    |    +--- org.springframework:spring-tx:5.2.12.RELEASE (*)
|    |    +--- org.springframework:spring-oxm:5.2.12.RELEASE
|    |    |    +--- org.springframework:spring-beans:5.2.12.RELEASE (*)
|    |    |    \--- org.springframework:spring-core:5.2.12.RELEASE (*)
|    |    +--- org.springframework:spring-aop:5.2.12.RELEASE (*)
|    |    +--- org.springframework:spring-context-support:5.2.12.RELEASE (*)
|    |    \--- org.slf4j:slf4j-api:1.7.26 -> 1.7.30
|    \--- io.lettuce:lettuce-core:5.3.5.RELEASE
|         +--- io.netty:netty-common:4.1.53.Final -> 4.1.55.Final
|         +--- io.netty:netty-handler:4.1.53.Final -> 4.1.55.Final
|         |    +--- io.netty:netty-common:4.1.55.Final
|         |    +--- io.netty:netty-resolver:4.1.55.Final
|         |    |    \--- io.netty:netty-common:4.1.55.Final
|         |    +--- io.netty:netty-buffer:4.1.55.Final
|         |    |    \--- io.netty:netty-common:4.1.55.Final
|         |    +--- io.netty:netty-transport:4.1.55.Final
|         |    |    +--- io.netty:netty-common:4.1.55.Final
|         |    |    +--- io.netty:netty-buffer:4.1.55.Final (*)
|         |    |    \--- io.netty:netty-resolver:4.1.55.Final (*)
|         |    \--- io.netty:netty-codec:4.1.55.Final
|         |         +--- io.netty:netty-common:4.1.55.Final
|         |         +--- io.netty:netty-buffer:4.1.55.Final (*)
|         |         \--- io.netty:netty-transport:4.1.55.Final (*)
|         +--- io.netty:netty-transport:4.1.53.Final -> 4.1.55.Final (*)
|         \--- io.projectreactor:reactor-core:3.3.11.RELEASE -> 3.3.12.RELEASE
|              \--- org.reactivestreams:reactive-streams:1.0.3

.env を変更する

..........
REDIS_VERSION=6.0.9
REDIS_CLUSTER_1_PORT=6379
REDIS_CLUSTER_2_PORT=6380
REDIS_CLUSTER_3_PORT=6381
REDIS_CLUSTER_4_PORT=6382
REDIS_CLUSTER_5_PORT=6383
REDIS_CLUSTER_6_PORT=6384

..........
  • REDIS_VERSION=5.0.7REDIS_VERSION=6.0.9 に変更します。

docker-compose.yml を変更する

  redis_exporter:
    image: oliver006/redis_exporter:v1.14.0-alpine
    container_name: redis_exporter
    ports:
      - "9121:9121"
  • image: oliver006/redis_exporter:v1.3.5-alpineimage: oliver006/redis_exporter:v1.14.0-alpine に変更します。

docker-compose up -d コマンドを実行する

以下のコマンドを実行して docker image をダウンロード+Redis Cluster を起動します(画面キャプチャはなし)。

  1. docker-compose up -d コマンドを実行してコンテナ一式(メールサーバ・rainloop を除く)を起動します。

redis-cluster-6379 ~ 6384 のコンテナは起動したままになっており、redis-cluster-make コンテナのログを確認すると問題なく Redis Cluster が構成できているようです。

f:id:ksby:20201214004336p:plain

Spring Boot 1.5.x の Web アプリを 2.0.x へバージョンアップする ( その19 )( Docker で Redis の環境を構築する2(Redis Cluster 構成)) を参考に docker exec -it redis-cluster-6379 redis-cli コマンドで redis-cli を起動してから cluster nodes コマンドを実行すると master が3台、slave が3台あることが確認できます。

f:id:ksby:20201214005010p:plain

Spring Boot のアプリケーションを起動してから Endpoints - Health の redis の情報を確認すると cluster_size に 3 と表示されていました。

f:id:ksby:20201214005539p:plain

redis_exporter の方は、Grafana で Redis の情報を表示させてみると metrics は取得できているようですが、一部エラーが出ていました。今はこのままにして prometheus・grafana をバージョンアップする時に修正します。

f:id:ksby:20201214011932p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20201214010149p:plain

変更前の docker image を削除する

以下の docker image を削除します。

  • redis:5.0.7-alpine
  • redis:5.0.7-custom
  • oliver006/redis_exporter:v1.3.5-alpine

履歴

2020/12/14
初版発行。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その9 )( Docker コンテナの image をバージョンアップする、postgres・pgadmin4・flyway・docker-mailserver 編 )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その8 )( SpotBugs を 4.0.0-beta4 → 4.1.1 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Docker コンテナの image を1度にバージョンアップしようとしたらいろいろうまく動かないものがあったので、何回かに分割してバージョンアップします。
    • 今回は以下の Docker コンテナの image をバージョンアップします。
      • postgres
      • dpage/pgadmin4
      • flyway/flyway
      • tvial/docker-mailserver

参照したサイト・書籍

目次

  1. .env を変更する
  2. docker-compose up -d コマンドを実行する
  3. pgadmin4 にログインできない問題を解消する
  4. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  5. 変更前の docker image を削除する

手順

.env を変更する

..........

POSTGRESQL_VERSION=12.5
PGADMIN4_VERSION=4.29

FLYWAY_VERSION=7.3.1
FLYWAY_URL=jdbc:postgresql://postgresql/ksbylending
FLYWAY_USER=ksbylending_user
FLYWAY_PASSWORD=xxxxxxxx

..........

MAILSERVER_VERSION=release-v7.2.0
  • POSTGRESQL_VERSION=12.1POSTGRESQL_VERSION=12.5 に変更します。
  • PGADMIN4_VERSION=4.16PGADMIN4_VERSION=4.29 に変更します。
  • FLYWAY_VERSION=6.1.3FLYWAY_VERSION=7.3.1 に変更します。
  • MAILSERVER_VERSION=release-v6.2.1MAILSERVER_VERSION=release-v7.2.0 に変更します。

docker-compose up -d コマンドを実行する

以下のコマンドを実行して docker image をダウンロードします(画面キャプチャはなし)。

  1. docker-compose up -d コマンドを実行してコンテナ一式(メールサーバ・rainloop を除く)を起動します。
  2. docker-compose -f docker-compose.mail.yml up -d コマンドを実行してメールサーバ・rainloop のコンテナを起動します。
  3. docker-compose -f docker-compose.mail.yml down コマンドを実行してメールサーバ・rainloop のコンテナを停止・削除します。

pgadmin4 にログインできない問題を解消する

バージョンアップ後に動作確認をしてみたところ、pgAdmin 4 でログインができません。Email/Username is not valid というメッセージが表示されます。

f:id:ksby:20201213174208p:plain f:id:ksby:20201213174335p:plain

4.16 → 4.29 へ一気にバージョンアップしていたので 4.17, 4.18, ..... と1つずつバージョンアップして確認したところ、4.25 までは PGADMIN_DEFAULT_EMAIL、PGADMIN_DEFAULT_PASSWORD に設定した postgres / yyyyyyyy でログインできましたが、4.26 でログインできなくなりました。

https://github.com/postgres/pgadmin4/blob/master/web/pgadmin/authenticate/internal.py を見ると validate_email 関数から False が返ってくるからで、https://github.com/postgres/pgadmin4/blob/c79614786f7250f4ddb14fd63c42d4cc87198b32/web/pgadmin/utils/validation_utils.py#L13 を見ると validate_email 関数でメールアドレスのフォーマットチェックを行っていました。postgres ではログインできないはずです。。。

あと pgAdmin 4 が Flask で作成されていることを初めて知りました。

docker-compose.yml で PGADMIN_DEFAULT_EMAIL=postgresPGADMIN_DEFAULT_EMAIL=postgres@example.com に変更して再度ログインを試してみると、今度は Incorrect username or password. のメッセージが表示されてまだログインできません。

docker/pgadmin4/data/pgadmin4.db に pgAdmin 4 のデータベースがあるので IntelliJ IDEA の Database Tools で開いて中を確認してみます。

f:id:ksby:20201213181007p:plain

Database Tool Window で Data Source に SQLite を選択した後、「File」に docker/pgadmin4/data/pgadmin4.db を指定してから「OK」ボタンをクリックします。

f:id:ksby:20201213181230p:plain f:id:ksby:20201213181347p:plain f:id:ksby:20201213181525p:plain

Database Tool Window に pgadmin4.db が表示されてテーブル一覧の中に user テーブルがあるので開いてみると、

f:id:ksby:20201213181730p:plain

username も email も postgres のままで postgres@example.com に変更されていませんでした。

f:id:ksby:20201213181904p:plain

email を postgrespostgres@example.com に変更してみます。

f:id:ksby:20201213182137p:plain

今度は無事ログインできました。

f:id:ksby:20201213182246p:plain f:id:ksby:20201213182840p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20201213191119p:plain

docker-compose -f docker-compose.mail.yml up -d コマンドを実行してメールサーバを起動した後、Spring Boot 2.1.x の Web アプリを 2.2.x へバージョンアップする ( その14 )( Docker で複数の Tomcat を起動して動作確認する ) に記載してある手順で動作確認しても問題ありませんでした。

変更前の docker image を削除する

以下の docker image を削除します。

  • postgres:12.1-alpine
  • dpage/pgadmin4:4.16
  • flyway/flyway:6.1.3-alpine
  • tvial/docker-mailserver:release-v6.2.1

履歴

2020/12/13
初版発行。