Eコマース注文全フローの可観測性ベストプラクティス¶
概要¶
迅速なイテレーションとトラフィックの急増に対応するため、Eコマースシステムはマイクロサービス方式で開発・デプロイされることがよくあります。あるマイクロサービスのパフォーマンスボトルネックは、顧客のショッピング体験に直接影響を与えます。特に支払い異常や注文キャンセルが発生した場合、注文の全チェーンを観測する必要があります。リアルタイムの支払い済み注文数、異常注文数、キャンセル注文数を整理し、これらの指標を活用してビジネスのボトルネックを分析することは非常に有用です。本ベストプラクティスは、Java ベースの分散Eコマースプラットフォーム上で、Guance を活用して注文の成約数と未成約の原因をリアルタイムに分析するものです。
前提条件¶
DataKit のインストール¶
データ取り込み¶
注文データの Guance への取り込みはログを介して行います。マイクロサービスがログファイルをクラウドサーバーに出力し、このサーバーに DataKit をインストールし、ログ収集を有効にしてログファイルのパスを指定します。ログファイルから注文番号、注文者、注文ステータスを抽出するために、Pipeline を作成してこれらのフィールドをパースします。
Input の有効化¶
- ddtrace の有効化
- Pipeline の作成
ここで、%{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)
- Logging プラグインの有効化とサンプルファイルのコピー
[[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"
- DataKit の再起動
Eコマースデータの取り込み¶
プロジェクトソース:book-store。
Pipeline でパースしたログを使用します。このログはマイクロサービスが生成するため、注文者、注文番号、注文ステータスをログに出力する必要があります。この例ではログツールとして Logback を使用しており、ビジネスデータを Logback 経由で出力するには MDC メカニズムを使用します。具体的には、ログ出力前に注文者、注文番号、注文ステータスを MDC に設定し、logback-spring.xml の PATTERN で出力します。この例では、bookstore-order-service マイクロサービスのコードを変更する必要があります。
- アスペクトの作成
アスペクトを作成し、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);
}
}
- 注文データのログへの書き込み
注文成功時にログを出力します
- 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 ディレクトリが生成されます
- バックエンドのビルド: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 が生成されます
RUM の有効化¶
- Guance にログイン
【RUM】→【アプリケーションを作成】をクリックし、book-shop と入力、Web を選択、JS をコピーします。
- build ディレクトリをサーバーにコピー
index.html を開き、先ほどコピーした JS を head に貼り付け、datakitOrigin の値を現在のクラウドサーバーにデプロイされた DataKit のアドレスに、allowedDDtracingOrgins の値を Gateway のアドレスに変更します。
- 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 にログインし、【シナリオ】→【ダッシュボードを作成】→【空のダッシュボードを作成】をクリックし、「注文モニタリングビュー」と入力して【確定】をクリックします。
作成したダッシュボードをクリックし、【編集】をクリックして、時系列グラフをドラッグします。グラフのタイトルは「注文数」とし、時系列グラフで「ログ」を選択し、次に log_book_order を選択します。log_book_order は log_book_order.conf の source の値です。さらに order_no を選択し、ソート方式を「Count_distinct_by」にします。フィルター条件で order_status を選択し、値を「已下单」にします。この時系列グラフは、注文済みの注文数を集計します。最後に「+」→ 変換関数 → cumsum をクリックすると、注文数が単位時間あたりの累積値に変換されます。
時系列グラフをドラッグします。グラフのタイトルは「支払い済み注文数」とし、時系列グラフで「ログ」を選択し、次に log_book_order を選択します。log_book_order は log_book_order.conf の source の値です。さらに order_no を選択し、ソート方式を「Count_distinct_by」にします。フィルター条件で order_status を選択し、値を「已支付」にします。この時系列グラフは、支払い済みの注文数を集計します。最後に「+」→ 変換関数 → cumsum をクリックすると、注文数が単位時間あたりの累積値に変換されます。
時系列グラフをドラッグします。グラフのタイトルは「異常注文数」とし、時系列グラフで「ログ」を選択し、次に log_book_order を選択します。log_book_order は log_book_order.conf の source の値です。さらに order_no を選択し、ソート方式を「Count_distinct_by」にします。フィルター条件で order_status を選択し、値を「支付异常」にします。この時系列グラフは、支払い異常の注文数を集計します。最後に「+」→ 変換関数 → cumsum をクリックすると、注文数が単位時間あたりの累積値に変換されます。






