コンテンツにスキップ

Tomcat 環境における RuoYi モノリシックアプリケーションのデプロイと可観測性のベストプラクティス

本ドキュメントは、RuoYi のモノリシックアプリケーション をベースに、外部 Tomcat 環境で可観測性を実現するためのベストプラクティスを説明します。

実現目標

  • メトリクス情報の収集
  • トレース情報の収集
  • ログ情報の収集
  • リアルユーザーモニタリング(RUM)情報の収集
  • セッションリプレイ ユーザーがフロントエンドにアクセスする一連のセッション録画情報(ボタンクリック、画面操作、滞在時間など)を取得します。これにより、ユーザーの真の意図や操作の再現に役立ちます。

バージョン情報

  • Tomcat (9.0.81)
  • Springboot(2.6.2)
  • JDK (>=8)
  • DDTrace (>=1.0)
特記事項

Springboot プロジェクトの場合、Tomcat のメジャーバージョンは Springboot に内蔵されている Tomcat のメジャーバージョンと一致している必要があります。そうしないと、起動時に異常が発生する可能性があります。

RuoYi のモノリシックアプリケーション

  • ソースコードのダウンロード

RuoYi のモノリシックアプリケーション

git clone https://gitee.com/y_project/RuoYi.git
  • 内蔵 Tomcat の削除

プロジェクトルートディレクトリの pom.xml を修正します。

......
    <dependencyManagement>
        <dependencies>

            <!-- SpringBootの依存関係設定-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.5.15</version>
                <type>pom</type>
                <scope>import</scope>
                <!-- 内蔵 Tomcat を除外 -->
                <exclusions>
                    <exclusion>
                        <artifactId>spring-boot-starter-tomcat</artifactId>
                        <groupId>org.springframework.boot</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
......
  • war 出力

ruoyi-admin モジュール配下の pom.xml ファイルを修正します。

<packaging>war</packaging>
  • ログ設定の調整

ruoyi-admin/src/main/resources に新規ファイル logback-spring.xml を作成します。内容は以下の通りです。

logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- ログ保存先パス -->
    <property name="log.path" value="/home/root/ruoyi/logs" />
    <!-- ログ出力フォーマット -->
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - [%method,%line] %X{dd.service} %X{dd.trace_id} %X{dd.span_id} - %msg%n" />

    <!-- コンソール出力 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>

    <!-- システムログ出力 -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-info.log</file>
        <!-- ローテーションポリシー:時間ベースでログファイルを作成 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- ログファイル名フォーマット -->
            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- ログの最大保持期間 60日 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- フィルタリングするレベル -->
            <level>INFO</level>
            <!-- マッチ時の動作:受け入れ(記録) -->
            <onMatch>ACCEPT</onMatch>
            <!-- マッチしない場合の動作:拒否(記録しない) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-error.log</file>
        <!-- ローテーションポリシー:時間ベースでログファイルを作成 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- ログファイル名フォーマット -->
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- ログの最大保持期間 60日 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- フィルタリングするレベル -->
            <level>ERROR</level>
            <!-- マッチ時の動作:受け入れ(記録) -->
            <onMatch>ACCEPT</onMatch>
            <!-- マッチしない場合の動作:拒否(記録しない) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- ユーザーアクセスログ出力 -->
    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-user.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日次ローテーション -->
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- ログの最大保持期間 60日 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>

    <!-- システムモジュールのログレベル制御 -->
    <logger name="com.ruoyi" level="info" />
    <!-- Spring のログレベル制御 -->
    <logger name="org.springframework" level="warn" />

    <root level="info">
        <appender-ref ref="console" />
    </root>

    <!-- システム操作ログ -->
    <root level="debug">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>

    <!-- システムユーザー操作ログ -->
    <logger name="sys-user" level="info">
        <appender-ref ref="sys-user"/>
    </logger>
</configuration> 
  • コンパイル

プロジェクトルートディレクトリで以下のコマンドを実行してコンパイルします。

mvn clean package

Maven がインストールされていない場合は、事前に Maven をインストールしてからコンパイルを実行してください。

[INFO] --- spring-boot:2.5.15:repackage (default) @ ruoyi-admin ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for ruoyi 4.7.7:
[INFO] 
[INFO] ruoyi .............................................. SUCCESS [  0.179 s]
[INFO] ruoyi-common ....................................... SUCCESS [  4.622 s]
[INFO] ruoyi-system ....................................... SUCCESS [  0.770 s]
[INFO] ruoyi-framework .................................... SUCCESS [  0.950 s]
[INFO] ruoyi-quartz ....................................... SUCCESS [  0.388 s]
[INFO] ruoyi-generator .................................... SUCCESS [  0.378 s]
[INFO] ruoyi-admin ........................................ SUCCESS [  4.554 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  12.287 s
[INFO] Finished at: 2023-10-13T16:30:12+08:00
[INFO] ------------------------------------------------------------------------

DataKit

  • DataKit のインストール
  • コレクターの有効化

DataKit のインストール

DataKit インストールドキュメント を参照してください。

DataKit で DDTrace コレクターを有効化

DDTrace コレクターはアプリケーションのトレース情報を収集するために使用します。DDTrace コレクター の導入ドキュメントを参照してください。

DataKit で Log コレクターを有効化

Log コレクターはログ情報を収集するために使用します。Log コレクター の導入ドキュメントを参照してください。

以下の設定を調整する必要があります。

 logfiles = [
    "/home/liurui/ruoyi/logs/*.log",
  ]
  ## サービス名を追加。空の場合は $source を使用。
  service = "ruoyi"

  ## Grok パイプラインスクリプト名。
  pipeline = "ruoyi.p"
  • logfiles:収集するログファイルのパス
  • service:サービス名
  • pipeline:ログ解析

Pipeline 設定

Pipeline はデータガバナンスに使用され、ここでは主にログ情報を抽出してトレース情報と関連付けます。

datakit/pipeline/ ディレクトリに ruoyi.p ファイルを作成し、内容は以下の通りです。

grok(_, "%{TIMESTAMP_ISO8601:time} %{NOTSPACE:thread_name} %{LOGLEVEL:status}%{SPACE}%{NOTSPACE:class_name} - \\[%{NOTSPACE:method_name},%{NUMBER:line}\\] %{DATA:service_name2} %{DATA:trace_id} %{DATA:span_id} - %{GREEDYDATA:msg}")

default_time(time,"Asia/Shanghai")

DataKit で StatsD コレクターを有効化

StatsD コレクターはメトリクス情報を収集するために使用します。StatsD コレクター の導入ドキュメントを参照してください。

DataKit で RUM コレクターを有効化

RUM コレクター: RUM コレクターは、Web ページまたはモバイル端末から報告されるユーザーアクセス監視データを収集するために使用します。RUM コレクター の導入ドキュメントを参照してください。

DataKit の再起動

DataKit の再起動 を参照してください。

DDTrace

dd-trace-java をダウンロードします。可能な限り最新バージョンをダウンロードしてください。

RUM の作成

  1. Guance にログインします。
  2. ユーザーアクセスモニタリング を選択し、アプリケーション一覧 を選択して、アプリケーションを作成 をクリックします。
  3. アプリケーション名ruoyi-admin を入力し、アプリケーション ID は自由に設定するか、ランダム生成 ボタンをクリックします。
  4. アプリケーションタイプweb を選択します。右側の SDK 設定 にはいくつかのタイプがありますが、ここでは CDN 同期読み込み を選択します。スクリプトの内容をコピーしておいてください。後で使用します。
  5. 作成 ボタンをクリックして作成を完了します。

Tomcat

Tomcat のダウンロード

対応するバージョンの Tomcat をダウンロードします。

DDTrace の設定

Tomcat の bin ディレクトリにスクリプトファイル setenv.sh を新規作成します。

export CATALINA_OPTS="-javaagent:/home/root/agent/dd-java-agent-1.14.0-guance.jar \
                      -Ddd.tags=env:test \
                      -Ddd.jmxfetch.enabled=true \
                      -Ddd.jmxfetch.statsd.host=localhost \
                      -Ddd.jmxfetch.statsd.port=8125 \
                      -Ddd.jmxfetch.tomcat.enabled=true\
                      -Dlogging.config=classpath:logback-spring.xml"
  • javaagent: ddtrace のパスを指定します。
  • Dlogging.config: アプリケーションのログを logback 形式で出力するように指定します。アプリケーション内部で log4j を使用している場合は、対応するファイルを指定してください。

アプリケーションのデプロイ

パッケージ化済みのアプリケーション RuoYi/ruoyi-admin/target/ruoyi-admin.war を Tomcat の webapps ディレクトリにコピーします。

Tomcat の起動

bin/startup.sh を実行します。

apache-tomcat-9.0.81/bin$ ./startup.sh 
Using CATALINA_BASE:   /home/root/middleware/apache-tomcat-9.0.81
Using CATALINA_HOME:   /home/root/middleware/apache-tomcat-9.0.81
Using CATALINA_TMPDIR: /home/root/middleware/apache-tomcat-9.0.81/temp
Using JRE_HOME:        /home/root/middleware/jdk/jdk-11.0.18
Using CLASSPATH:       /home/root/middleware/apache-tomcat-9.0.81/bin/bootstrap.jar:/home/root/middleware/apache-tomcat-9.0.81/bin/tomcat-juli.jar
Using CATALINA_OPTS:   -javaagent:/home/root/agent/dd-java-agent-1.14.0-guance.jar                       -Ddd.tags=env:test                       -Ddd.jmxfetch.enabled=true                       -Ddd.jmxfetch.statsd.host=localhost                       -Ddd.jmxfetch.statsd.port=8125                       -Ddd.jmxfetch.tomcat.enabled=true                      -Dlogging.config=classpath:logback-spring.xml
Tomcat started.

RUM の組み込み

Tomcat 起動後、war アプリケーションが自動的に展開されます。/webapps/ruoyi-admin/WEB-INF/classes/templates ディレクトリに移動し、include.html を修正して、前の手順でコピーしたスクリプトコードを head タグ内に貼り付けます。

<head th:fragment="header(title)">
...
<script src="https://static.guance.com/browser-sdk/v3/dataflux-rum.js" type="text/javascript"></script>
<script>
  window.DATAFLUX_RUM &&
    window.DATAFLUX_RUM.init({
      applicationId: 'APP_ID',
      datakitOrigin: 'http://localhost:9529', // プロトコル(//を含む)、ドメイン名(またはIPアドレス)[およびポート番号]
      env: 'production',
      version: '1.0.0',
      service: 'browser',
      sessionSampleRate: 100,
      sessionReplaySampleRate: 70,
      trackInteractions: true,
      traceType: 'ddtrace', // 任意。デフォルトは ddtrace。現在サポートされているのは ddtrace、zipkin、skywalking_v3、jaeger、zipkin_single_header、w3c_traceparent の6種類
      allowedTracingOrigins: ['http://localhost:8080','http://localhost:8080/ruoyi-admin'],  // 任意。トレースコレクターに必要なヘッダーを注入するリクエストのリスト。リクエストのオリジンまたは正規表現で指定可能
    });
    window.DATAFLUX_RUM && window.DATAFLUX_RUM.startSessionReplayRecording()
</script>
...
</head>
  • applicationId:コピーした内容をそのまま使用します。調整は不要です。
  • datakitOrigin:RUM データを受け取る DataKit のアドレスです。
  • allowedTracingOrigins:バックエンドの APM と連携するために使用します。フロントエンドが API を呼び出す際に、指定されたオリジンに対してトレースに必要なヘッダー情報を追加します。

動作確認

http://localhost:8080/ruoyi-admin にアクセスします。デフォルトのユーザー名は admin、パスワードは admin123 です。

Img

ログ

Img

ログの詳細画面では、現在のログに対応するトレース情報を確認できます。

Img

トレース情報

Img

トレースからログやメトリクス情報を確認することもできます。

Img

メトリクス情報

Img

RUM ダッシュボード

Img

セッションリプレイ

Img

フィードバック

このページは役に立ちましたか?