전자상거래 주문 전체 프로세스 관측 가능성 모범 사례¶
개요¶
빠른 반복과 트래픽 급증에 대응하기 위해 전자상거래 시스템은 종종 마이크로서비스 방식으로 개발 및 배포됩니다. 특정 마이크로서비스 시스템의 성능 병목 현상은 고객의 쇼핑 경험에 직접적인 영향을 미치며, 특히 결제 이상이나 주문 취소가 발생한 경우 주문의 전체 링크를 관측하여 실시간 결제 완료 주문 수, 이상 주문 수, 취소 주문 수를 파악하는 것이 중요합니다. 이러한 지표를 통해 비즈니스 병목 현상을 분석하는 데 큰 도움이 됩니다. 본 모범 사례는 Java 기반 분산 전자상거래 플랫폼으로, 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 플러그인 활성화, sample 파일 복사
[[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 재시작
전자상거래 데이터 수집¶
프로젝트 소스 코드: book-store.
Pipeline을 사용하여 파싱한 로그입니다. 이 로그는 마이크로서비스에서 생성된 로그이므로 주문자, 주문 번호, 주문 상태를 로그에 출력해야 합니다. 본 예시의 로그 도구는 Logback이며, 비즈니스 데이터를 Logback을 통해 출력하려면 MDC 메커니즘을 사용해야 합니다. 즉, 로그를 출력하기 전에 주문자, 주문 번호, 주문 상태를 MDC에 Put한 후 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에 로그인
[사용자 분석] - [애플리케이션 생성]을 클릭하고 book-shop을 입력한 후 Web을 선택하고 js를 복사합니다.
- build 디렉터리를 서버에 복사
index.html을 열고, 위에서 복사한 js를 head에 붙여넣은 후 datakitOrigin 값을 현재 클라우드 서버에 배포된 DataKit 주소로 수정하고, allowedDDtracingOrgins 값은 Gateway 주소로 설정합니다.
- Nginx 설치 및 웹 프로젝트 배포
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을 클릭하면 단위 시간 내 주문 수가 누적값으로 변환됩니다.






