コンテンツにスキップ

Eコマース注文全フローの可観測性ベストプラクティス


概要

迅速なイテレーションとトラフィックの急増に対応するため、Eコマースシステムはマイクロサービス方式で開発・デプロイされることがよくあります。あるマイクロサービスのパフォーマンスボトルネックは、顧客のショッピング体験に直接影響を与えます。特に支払い異常や注文キャンセルが発生した場合、注文の全チェーンを観測する必要があります。リアルタイムの支払い済み注文数、異常注文数、キャンセル注文数を整理し、これらの指標を活用してビジネスのボトルネックを分析することは非常に有用です。本ベストプラクティスは、Java ベースの分散Eコマースプラットフォーム上で、Guance を活用して注文の成約数と未成約の原因をリアルタイムに分析するものです。

前提条件

DataKit のインストール

データ取り込み

注文データの Guance への取り込みはログを介して行います。マイクロサービスがログファイルをクラウドサーバーに出力し、このサーバーに DataKit をインストールし、ログ収集を有効にしてログファイルのパスを指定します。ログファイルから注文番号、注文者、注文ステータスを抽出するために、Pipeline を作成してこれらのフィールドをパースします。

Input の有効化

  1. ddtrace の有効化
cd /usr/local/datakit/conf.d/ddtrace
cp ddtrace.conf.sample ddtrace.conf  
  1. Pipeline の作成
cd /usr/local/datakit/pipeline
vi log_book_order.p

ここで、%{DATA:username} は注文者、%{DATA:order_no} は注文番号、%{DATA:order_status} は注文ステータスです。

#2021-12-22 10:09:53.443 [http-nio-7001-exec-7] INFO  c.d.s.b.s.i.OrderServiceImpl - [createOrder,164] - ecs009-book-order 7547183777837932733 2227975860088333788 test d6a3337d-ff82-4b00-9b4d-c07fb00c0cfb - ユーザー:test 已下单,注文番号: d6a3337d-ff82-4b00-9b4d-c07fb00c0cfb


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

default_time(time)
  1. Logging プラグインの有効化とサンプルファイルのコピー

cd /usr/local/datakit/conf.d/log
cp logging.conf.sample log_book_order.conf
log_book_order.conf ファイルを編集し、logfiles にログファイルを指定、pipeline に先ほど作成した log_book_order.p を指定します。source には log_book_order を指定し、ビューでこのログを利用できるようにします。

[[inputs.logging]]
  ## required
  logfiles = [
    "/usr/local/df-demo/book-shop/logs/order/log.log"    
  ]

  ## glob filteer
  ignore = [""]

  ## your logging source, if it's empty, use 'default'
  source = "log_book_order"

  ## add service tag, if it's empty, use $source.

  service = "book-store"

  ## grok pipeline script path
  pipeline = "log_book_order.p"

  ## optional status:
  ##   "emerg","alert","critical","error","warning","info","debug","OK"
  ignore_status = []

  ## optional encodings:
  ##    "utf-8", "utf-16le", "utf-16le", "gbk", "gb18030" or ""
  character_encoding = ""

  ## The pattern should be a regexp. Note the use of '''this regexp'''
  ## regexp link: https://golang.org/pkg/regexp/syntax/#hdr-Syntax
  multiline_match = '''^\d{4}-\d{2}-\d{2}'''

  ## removes ANSI escape codes from text strings
  remove_ansi_escape_codes = false

  [inputs.logging.tags]
    app = "book-shop"
  # some_tag = "some_value"
  # more_tag = "some_other_value"
  1. DataKit の再起動
systemctl restart datakit

Eコマースデータの取り込み

プロジェクトソース:book-store

Pipeline でパースしたログを使用します。このログはマイクロサービスが生成するため、注文者、注文番号、注文ステータスをログに出力する必要があります。この例ではログツールとして Logback を使用しており、ビジネスデータを Logback 経由で出力するには MDC メカニズムを使用します。具体的には、ログ出力前に注文者、注文番号、注文ステータスを MDC に設定し、logback-spring.xml の PATTERN で出力します。この例では、bookstore-order-service マイクロサービスのコードを変更する必要があります。

  1. アスペクトの作成

アスペクトを作成し、userName、orderNo、orderStatus を MDC に追加し、リクエスト終了時に削除します。

@Component
@Aspect
public class LogAop {
    private static final String USER_NAME = "userName";
    private static final String ORDER_NO = "orderNo";
    private static final String ORDER_STATUS = "orderStatus";

    @Pointcut("execution(public * com.devd.spring.bookstoreorderservice.controller..*.*(..))")
    public void controllerCall() {
    }

    @Before("controllerCall()")
    public void logInfoBefore(JoinPoint jp) throws UnsupportedEncodingException {
        MDC.put(USER_NAME, "");
        MDC.put(ORDER_NO, "");
        MDC.put(ORDER_STATUS, "");
    }

    @AfterReturning(returning = "req", pointcut = "controllerCall()")
    public void logInfoAfter(JoinPoint jp, Object req) throws Exception {
        MDC.remove(USER_NAME);
        MDC.remove(ORDER_NO);
        MDC.remove(ORDER_STATUS);
    }

}
  1. 注文データのログへの書き込み

注文成功時にログを出力します

1641289006.png

  1. logback-spring.xml の設定
<property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %X{dd.service} %X{dd.trace_id} %X{dd.span_id} %X{userName} %X{orderNo} %X{orderStatus} - %msg%n" />

ビルドとデプロイ

  • フロントエンドのビルド:build ディレクトリが生成されます
cd bookstore-frontend-react-app
yarn  build
  • バックエンドのビルド:bookstore-account-service-0.0.1-SNAPSHOT.jar、

bookstore-payment-service-0.0.1-SNAPSHOT.jar、

bookstore-api-gateway-service-0.0.1-SNAPSHOT.jar、

bookstore-billing-service-0.0.1-SNAPSHOT.jar、

bookstore-catalog-service-0.0.1-SNAPSHOT.jar、

bookstore-eureka-discovery-service-0.0.1-SNAPSHOT.jar、

bookstore-order-service-0.0.1-SNAPSHOT.jar が生成されます

mvn clean install -DskipTests

RUM の有効化

【RUM】→【アプリケーションを作成】をクリックし、book-shop と入力、Web を選択、JS をコピーします。

image.png

  • build ディレクトリをサーバーにコピー

index.html を開き、先ほどコピーした JS を head に貼り付け、datakitOrigin の値を現在のクラウドサーバーにデプロイされた DataKit のアドレスに、allowedDDtracingOrgins の値を Gateway のアドレスに変更します。

image.png

  • Nginx のインストールと Web プロジェクトのデプロイ
server {
        listen       80;
        location / {            
            proxy_set_header   Host    $host:$server_port;
            proxy_set_header   X-Real-IP   $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
                  root   /usr/local/df-demo/book-shop/build;
            index  index.html index.htm;
        }
}

APM の有効化

Guance で Trace データを取得するには、/usr/local/datakit/data/dd-java-agent.jar を使用します。

java -jar bookstore-eureka-discovery-service-0.0.1-SNAPSHOT.jar


java  -javaagent:/usr/local/datakit/data/dd-java-agent.jar \
 -Ddd.service.name=book-gateway \
 -Ddd.env=dev  \
 -Ddd.agent.port=9529   \
 -jar bookstore-api-gateway-service-0.0.1-SNAPSHOT.jar


java  -javaagent:/usr/local/datakit/data/dd-java-agent.jar \
 -Ddd.service.name=book-account \
 -Ddd.env=dev  \
 -Ddd.agent.port=9529   \
 -jar bookstore-account-service-0.0.1-SNAPSHOT.jar  

java  -javaagent:/usr/local/datakit/data/dd-java-agent.jar \
 -Ddd.service.name=book-order \
 -Ddd.env=dev  \
 -Ddd.agent.port=9529   \
 -jar bookstore-order-service-0.0.1-SNAPSHOT.jar


java  -javaagent:/usr/local/datakit/data/dd-java-agent.jar \
 -Ddd.service.name=book-billing \
 -Ddd.env=dev  \
 -Ddd.agent.port=9529   \
 -jar bookstore-billing-service-0.0.1-SNAPSHOT.jar


java  -javaagent:/usr/local/datakit/data/dd-java-agent.jar \
 -Ddd.service.name=book-payment \
 -Ddd.env=dev  \
 -Ddd.agent.port=9529   \
 -jar bookstore-payment-service-0.0.1-SNAPSHOT.jar


java  -javaagent:/usr/local/datakit/data/dd-java-agent.jar \
 -Ddd.service.name=book-catalog \
 -Ddd.env=dev  \
 -Ddd.agent.port=9529   \
 -jar bookstore-catalog-service-0.0.1-SNAPSHOT.jar 

注文モニタリングビュー

Guance にログインし、【シナリオ】→【ダッシュボードを作成】→【空のダッシュボードを作成】をクリックし、「注文モニタリングビュー」と入力して【確定】をクリックします。

1641360132(1).png

作成したダッシュボードをクリックし、【編集】をクリックして、時系列グラフをドラッグします。グラフのタイトルは「注文数」とし、時系列グラフで「ログ」を選択し、次に log_book_order を選択します。log_book_order は log_book_order.conf の source の値です。さらに order_no を選択し、ソート方式を「Count_distinct_by」にします。フィルター条件で order_status を選択し、値を「已下单」にします。この時系列グラフは、注文済みの注文数を集計します。最後に「+」→ 変換関数 → cumsum をクリックすると、注文数が単位時間あたりの累積値に変換されます。

1642059188(1).png

時系列グラフをドラッグします。グラフのタイトルは「支払い済み注文数」とし、時系列グラフで「ログ」を選択し、次に log_book_order を選択します。log_book_order は log_book_order.conf の source の値です。さらに order_no を選択し、ソート方式を「Count_distinct_by」にします。フィルター条件で order_status を選択し、値を「已支付」にします。この時系列グラフは、支払い済みの注文数を集計します。最後に「+」→ 変換関数 → cumsum をクリックすると、注文数が単位時間あたりの累積値に変換されます。

1642059204(1).png

時系列グラフをドラッグします。グラフのタイトルは「異常注文数」とし、時系列グラフで「ログ」を選択し、次に log_book_order を選択します。log_book_order は log_book_order.conf の source の値です。さらに order_no を選択し、ソート方式を「Count_distinct_by」にします。フィルター条件で order_status を選択し、値を「支付异常」にします。この時系列グラフは、支払い異常の注文数を集計します。最後に「+」→ 変換関数 → cumsum をクリックすると、注文数が単位時間あたりの累積値に変換されます。

1642059222(1).png

フィードバック

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