+1

Sử dụng OpenTelemetry để lấy Traces cho ứng dụng Java (Phần 1)

Theo như bên trên thì Traces hay dấu vết là một loại dữ liệu telemetry giúp theo dõi và ghi lại luồng thực thi của các yêu cầu trong hệ thống phân tán. Mỗi trace cung cấp một bản ghi chi tiết về cách một yêu cầu di chuyển qua các dịch vụ, thành phần và lớp khác nhau của ứng dụng. Để hiểu một cách đơn giản thì ta có thể ví dụ với luồng xử lý của ứng dụng như sau:

Một ứng dụng sẽ có 3 phần chính đó là Frontend (FE), Backend (BE) và Database (DB). Khi người dùng thao tác trên giao diện của ứng dụng là FE để yêu cầu một cái gì đó thì FE sẽ gửi yêu cầu đến BE, BE sẽ gửi yêu cầu đến DB, rồi tiếp tục DB sẽ gửi lại data đến BE và BE sẽ trả cho chúng ta cái mà ta cần khi thao tác trên giao diện FE. Vậy khoảng mà FE gửi yêu cầu đến BE rồi từ BE đến DB rồi lại từ DB đến BE rồi tới FE chính là một traces. Hay một lần load lại trang cũng chính là một traces.

Lợi ích của Traces

  • Hiểu rõ hơn về luồng yêu cầu: Traces giúp theo dõi chi tiết từng bước của một yêu cầu khi nó di chuyển qua các dịch vụ và thành phần khác nhau.
  • Phát hiện và chẩn đoán sự cố: Traces cung cấp thông tin chi tiết về các lỗi và thời gian phản hồi, giúp phát hiện các nút thắt cổ chai và lỗi trong hệ thống.
  • Tối ưu hóa hiệu suất: Bằng cách phân tích traces, bạn có thể tối ưu hóa luồng yêu cầu và cải thiện hiệu suất của hệ thống.

Hoặc đơn giản là traces sẽ giúp cho chúng ta biết được thời gian cũng như tốc độ phản hồi của ứng dụng, từ đó giúp ta cải thiện được ứng dụng để đáp ứng được nhu cầu của người dùng cuối.

Để thực hiện bài này ta cần chuẩn bị một ứng dụng Java Backend có cả Database nhé! Các bạn có thể clone project này tại đây hoặc có thể clone từ repo của anh Mai Trung Đức trong series Docker và CI/CD nhé!

Lưu ý là máy của bạn phải có Java 11, docker và docker compose nhé!

Sau khi clone về xong ta mở Dockerfile lên xem thử nhé! Nội dung sẽ như sau:

# Build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /app

COPY build.gradle settings.gradle gradlew ./
COPY gradle /app/gradle

RUN ./gradlew build || return 0
COPY . .
RUN ./gradlew build -x test

RUN ./gradlew build -x test

# Production stage
FROM eclipse-temurin:17-jre-alpine as production
WORKDIR /app

COPY --from=build /app/build/libs/demo-0.0.1-SNAPSHOT.jar app.jar
COPY otel/opentelemetry-javaagent.jar /app/otel-agent.jar

ENV OTEL_SERVICE_NAME=spring-boot-application
ENV OTEL_TRACES_EXPORTER=otlp
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://172.16.1.24:4318

ENTRYPOINT ["java", "-jar", "app.jar"]

Dockerfile này có hai bước chính là build và production. Bạn có thể tìm hiểu quá trình build cũng như xây dựng app java trên google nhé, mình sẽ không giải thích ở đây. Ở đây chúng ta sẽ sử dụng image là eclipse-temurin:17-jdk với bản phân phối là alpine.

Bước build chúng ta sẽ build ra một file là demo-0.0.1-SNAPSHOT.jar đã được định nghĩa trước đó trong file cấu hình và sử dụng file này để chạy ở bước production. Dockerfile sẽ tiến hành copy file này vào trong container để tiến hành chạy lên. Tạm thời chúng ta sẽ không quan tâm đến opentelemetry-javaagent.jar và ba biến môi trường nhé, các bạn xóa dòng copy và 3 biến môi trường đi đã nha, chút nữa mình sẽ giải thích sau:

COPY otel/opentelemetry-javaagent.jar /app/otel-agent.jar

ENV OTEL_SERVICE_NAME=spring-boot-application
ENV OTEL_TRACES_EXPORTER=otlp
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://172.16.1.24:4318

Bây giờ chúng ta sẽ chạy lên xem thử app như thế nào nhé! Đầu tiên chúng ta sẽ tiến hành build image, ở đây mình sẽ đặt tên cho image này là java-spring và tag là v1:

docker build -t java-spring:v1 .

Nếu như bạn đặt một tên khác cho image thì bạn cần phải thay đổi tên image trong file docker-compose.yml nhé! Ở đây ta sử dụng thêm DB là MySQL và Redis để có thể thao tác tốt hơn.

version: '3.7'

services:
  app:
    image: java-spring:v1
    restart: always
    ports:
      - "8081:8081"
    volumes:
      - ./docker_application.properties:/app/application.properties:ro
    depends_on:
      - db
      - redis

  db:
    image: mysql:8
    restart: always
    volumes:
      - ./.docker/data/db:/var/lib/mysql
      - ./db.sql:/docker-entrypoint-initdb.d/db.sql:ro
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: demo_app

  redis:
    image: redis:6-alpine
    restart: always
    volumes:
      - ./.docker/data/redis:/data

Sau khi đã setup đầy đủ ta tiến hành chạy ứng dụng lên, chúng ta sẽ sử dụng docker compose để chạy ứng dụng này.

docker compose up -d

Sau khi chạy xong đợi tầm 15s sau đó vào google truy cập http://localhost:8081 để xem thử. Nếu ra như thế này thì OK rồi đó!

Ta sử dụng username là user và password và Password1 để đăng nhập vào. Các bạn có thể thử tạo account mới, edit và xóa account xem sao nhé!

Vậy là setup ứng dụng Java Backend chạy trên Docker đã thành công. Phần sau chúng ta sẽ setup Otel Collector để thu thập các traces. Mình sẽ hướng dẫn bạn hai cách để trực quan hóa các traces đó là sử dụng công cụ Zipkin và Grafana.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí