Theo Dõi và Quản Lý Ứng Dụng Spring Boot với Actuator | Java Spring Roadmap

Chào mừng bạn quay trở lại với hành trình khám phá “Java Spring Roadmap”! Chúng ta đã cùng nhau đi qua những bước đầu tiên đầy hứng khởi, tìm hiểu lộ trình tổng thể, khám phá lý do Spring trở thành lựa chọn hàng đầu, giải mã các thuật ngữ cốt lõi, hiểu về kiến trúc bên trong, làm quen với cấu hình XML và Annotations, đắm mình vào Dependency Injection (DI)Spring IoC, khám phá sức mạnh của AOP, xây dựng ứng dụng web với Spring MVC, hiểu sâu hơn về Annotations, quản lý vòng đời Bean Scopes, làm chủ Spring Security từ cấu hình xác thực, RBAC đến OAuth2JWT. Gần đây, chúng ta cũng đã hiểu về sự tiện lợi của Spring Boot Starters và sự kỳ diệu của Autoconfiguration.

Cho đến nay, phần lớn kiến thức chúng ta học tập trung vào việc xây dựng ứng dụng. Nhưng điều gì xảy ra sau khi ứng dụng của bạn được triển khai lên môi trường production? Làm thế nào để bạn biết nó có đang chạy ổn định không? Hiệu suất của nó ra sao? Khi có lỗi xảy ra, làm sao bạn nhanh chóng xác định nguyên nhân?

Đây là lúc mà việc theo dõi (monitoring)quản lý (managing) ứng dụng trở nên cực kỳ quan trọng. Và may mắn thay, Spring Boot cung cấp một module mạnh mẽ giúp bạn làm điều này một cách dễ dàng: Spring Boot Actuator.

Tại Sao Việc Theo Dõi Ứng Dụng Lại Quan Trọng?

Hãy tưởng tượng ứng dụng của bạn giống như một chiếc xe hơi. Khi bạn lái xe, bạn cần nhìn vào bảng điều khiển (dashboard) để biết tốc độ, mức xăng, nhiệt độ động cơ, đèn báo lỗi… Bạn không thể lái xe an toàn và hiệu quả mà không có những thông tin đó.

Ứng dụng phần mềm cũng vậy. Đặc biệt là trong môi trường sản xuất, bạn cần biết:

  • Ứng dụng có đang hoạt động không (healthy)?
  • Có đủ tài nguyên không (bộ nhớ, CPU, disk space)?
  • Lượng request là bao nhiêu? Thời gian phản hồi trung bình?
  • Có lỗi nào đang xảy ra không?
  • Cấu hình hiện tại trên môi trường production là gì?
  • Phiên bản code nào đang chạy?

Việc thiếu thông tin này giống như lái xe trong đêm tối mà không có đèn pha và bảng điều khiển. Bạn sẽ gặp khó khăn trong việc:

  • Phát hiện sớm các vấn đề (trước khi người dùng báo cáo).
  • Phân tích nguyên nhân gốc rễ của lỗi.
  • Đánh giá hiệu suất và tìm điểm nghẽn.
  • Đưa ra quyết định tối ưu hóa tài nguyên.

Actuator ra đời để giải quyết bài toán này, cung cấp cho bạn “bảng điều khiển” cho ứng dụng Spring Boot của mình.

Spring Boot Actuator Là Gì?

Spring Boot Actuator là một dự án phụ (sub-project) của Spring Boot. Nó cung cấp các tính năng “sẵn sàng cho sản xuất” (production-ready) để giúp bạn giám sát và quản lý ứng dụng của mình khi nó được đẩy lên môi trường live. Actuator thực hiện điều này bằng cách thêm một số điểm cuối (endpoints) vào ứng dụng của bạn. Khi gọi tới các điểm cuối này, bạn sẽ nhận được thông tin chi tiết về ứng dụng đang chạy.

Các thông tin này có thể được truy cập qua nhiều giao thức khác nhau, phổ biến nhất là HTTP và JMX (Java Management Extensions).

Bắt Đầu Với Spring Boot Actuator

Việc tích hợp Actuator vào ứng dụng Spring Boot cực kỳ đơn giản nhờ vào Spring Boot Starters và Autoconfiguration. Bạn chỉ cần thêm một dependency vào file build của mình (pom.xml hoặc build.gradle).

Nếu sử dụng Maven (pom.xml):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Nếu sử dụng Gradle (build.gradle):

implementation 'org.springframework.boot:spring-boot-starter-actuator'

Chỉ với việc thêm dependency này, Spring Boot sẽ tự động cấu hình Actuator cho bạn. Khi ứng dụng của bạn chạy, Actuator sẽ đăng ký một số endpoints mặc định.

Theo mặc định, với các ứng dụng web, chỉ có các endpoint healthinfo được expose (cho phép truy cập) qua HTTP. Các endpoint khác thường chỉ được expose qua JMX vì lý do bảo mật (chúng ta sẽ nói kỹ hơn về bảo mật sau).

Các endpoint HTTP thường được truy cập qua đường dẫn gốc `/actuator`. Ví dụ: nếu ứng dụng của bạn chạy trên localhost:8080, bạn có thể truy cập trạng thái sức khỏe tại http://localhost:8080/actuator/health và thông tin chung tại http://localhost:8080/actuator/info.

Các Endpoint Chính Của Actuator

Actuator cung cấp nhiều endpoints khác nhau, mỗi endpoint cung cấp một loại thông tin hoặc chức năng quản lý cụ thể. Dưới đây là một số endpoint phổ biến và hữu ích nhất:

Để dễ hình dung, chúng ta hãy xem qua một bảng tóm tắt các endpoint chính:


Endpoint ID Mô tả Thông tin cung cấp (Ví dụ) Mặc định Expose qua HTTP? Mặc định Expose qua JMX?
health Trạng thái sức khỏe của ứng dụng UP/DOWN, trạng thái kết nối Database, Disk Space còn trống, trạng thái của các thành phần khác (Redis, Kafka, Mail server…).
info Thông tin chung về ứng dụng Thông tin build (version, timestamp), thông tin Git commit, thông tin custom bạn tự thêm vào.
metrics Các chỉ số đo lường (metrics) về ứng dụng CPU usage, Heap memory usage, Garbage collection, số lượng request HTTP, thời gian phản hồi, thông tin về DataSource pool, Cache usage, v.v. Cần thư viện hỗ trợ như Micrometer. Không
env Môi trường và cấu hình Environment variables, System properties, các giá trị từ file application.properties/.yml và các nguồn cấu hình khác. Không
beans Danh sách tất cả các Spring bean Tên bean, alias, scope, kiểu dữ liệu (class), các dependency của bean đó trong IoC Container. Không
mappings Ánh xạ (mappings) URL Danh sách tất cả các mapping HTTP (ví dụ: từ các annotation @RequestMapping, @GetMapping, v.v.) và các endpoint của Actuator. Không
httptrace Theo dõi request/response HTTP gần nhất Lịch sử các request/response HTTP gần đây bao gồm method, path, status code, thời gian, headers… Cần cấu hình thêm một bean HttpTraceRepository. Không
loggers Cấu hình logger Cho phép xem và thay đổi cấp độ log (DEBUG, INFO, ERROR, v.v.) của các logger trong ứng dụng ngay lúc runtime mà không cần deploy lại. Không
shutdown Tắt ứng dụng Thực hiện việc tắt ứng dụng một cách gracefully. Cực kỳ nguy hiểm nếu không được bảo mật cẩn thận! Không

Hãy đi sâu hơn một chút vào các endpoint quan trọng:

health

Endpoint này là “trái tim” của việc giám sát sức khỏe. Nó tổng hợp trạng thái từ các thành phần khác nhau của ứng dụng (gọi là HealthIndicator). Mặc định, Spring Boot cung cấp các HealthIndicator cho Disk Space, DataSource (Database), Redis, Elasticsearch, Kafka, v.v. Bạn cũng có thể tự viết HealthIndicator tùy chỉnh cho các dịch vụ hoặc logic nghiệp vụ riêng của mình.

Kết quả trả về thường là {"status": "UP"} hoặc {"status": "DOWN"} cùng với chi tiết trạng thái của từng thành phần nếu được cấu hình.

{
    "status": "UP",
    "components": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 249740515328,
                "free": 143585249280,
                "threshold": 10485760,
                "exists": true
            }
        },
        "db": {
            "status": "UP",
            "details": {
                "database": "MySQL",
                "validationQuery": "SELECT 1"
            }
        }
    }
}

info

Endpoint này dùng để hiển thị thông tin chung về ứng dụng. Mặc định nó trống rỗng hoặc chứa thông tin build nếu bạn cấu hình Maven/Gradle plugin phù hợp. Bạn có thể dễ dàng thêm thông tin tùy chỉnh vào đây trong file cấu hình application.properties hoặc application.yml:

info.app.name=My Awesome App
info.app.version=1.0.0
info.app.description=Ứng dụng quản lý người dùng

Hoặc bạn có thể thêm thông tin từ Git:

management.info.git.mode=full

Khi đó, endpoint /actuator/info có thể trả về:

{
    "app": {
        "name": "My Awesome App",
        "version": "1.0.0",
        "description": "Ứng dụng quản lý người dùng"
    },
    "git": {
        "commit": {
            "id": "a1b2c3d",
            "time": "2023-10-27T10:00:00Z"
        },
        "branch": "main"
    }
}

Thông tin này rất hữu ích để nhanh chóng kiểm tra xem phiên bản code nào đang chạy trên môi trường nào.

metrics

Endpoint này cung cấp một kho báu các chỉ số đo lường. Spring Boot Actuator sử dụng thư viện Micrometer làm facade cho các hệ thống đo lường. Điều này có nghĩa là bạn chỉ cần thêm dependency của hệ thống đo lường mà bạn muốn tích hợp (ví dụ: Prometheus, New Relic, Datadog) và Micrometer sẽ tự động đẩy metrics của Actuator tới hệ thống đó.

Khi truy cập /actuator/metrics, bạn sẽ thấy danh sách các metrics có sẵn:

{
    "names": [
        "jvm.memory.used",
        "jvm.gc.pause",
        "http.server.requests",
        "system.cpu.usage",
        // ... many more ...
    ]
}

Để xem chi tiết một metric cụ thể, bạn truy cập /actuator/metrics/{tên_metric}. Ví dụ: /actuator/metrics/http.server.requests sẽ cung cấp thông tin chi tiết về các request HTTP:

{
    "name": "http.server.requests",
    "description": "Timer of server completed requests",
    "baseUnit": "seconds",
    "measurements": [
        {
            "statistic": "COUNT",
            "value": 123.0
        },
        {
            "statistic": "TOTAL_TIME",
            "value": 5.67
        },
        {
            "statistic": "MAX",
            "value": 0.12
        }
    ],
    "availableTags": [
        {
            "tag": "exception",
            "values": [
                "None",
                "RuntimeException"
            ]
        },
        {
            "tag": "method",
            "values": [
                "GET",
                "POST"
            ]
        },
        // ... other tags like uri, status ...
    ]
}

Thông tin metrics là cực kỳ quan trọng để theo dõi hiệu suất, xác định điểm nghẽn và cảnh báo khi có vấn đề.

env

Endpoint này hiển thị môi trường và cấu hình của ứng dụng, bao gồm system environment variables, system properties, các giá trị từ application.properties/.yml, profile đang active, v.v. Đây là thông tin rất nhạy cảm vì nó có thể chứa mật khẩu, khóa API, v.v. Do đó, nó không được expose qua HTTP mặc định.

Khi truy cập (qua JMX hoặc sau khi cấu hình expose qua HTTP và bảo mật), bạn sẽ thấy một cấu trúc JSON phân cấp thể hiện các nguồn cấu hình khác nhau và giá trị của chúng.

beans

Endpoint này hiển thị danh sách đầy đủ tất cả các Spring beans đang tồn tại trong IoC Container của ứng dụng. Bạn có thể thấy tên bean, kiểu dữ liệu, phạm vi (scope – ví dụ: singleton, prototype, v.v.), các dependency của nó. Endpoint này rất hữu ích cho việc debug, kiểm tra xem một bean nào đó đã được tạo và cấu hình đúng chưa.

loggers

Endpoint này cho phép bạn xem và thay đổi cấp độ log của các logger trong ứng dụng ngay khi ứng dụng đang chạy. Ví dụ: bạn có thể thay đổi cấp độ log của package com.example.myapp.service từ INFO sang DEBUG để thu thập thông tin chi tiết hơn khi đang investigate một vấn đề, mà không cần deploy lại ứng dụng.

# Xem cấp độ log hiện tại của một logger cụ thể
GET /actuator/loggers/com.example.myapp.service

# Thay đổi cấp độ log
POST /actuator/loggers/com.example.myapp.service
Content-Type: application/json
{
  "configuredLevel": "DEBUG"
}

Cấu Hình và Tùy Chỉnh Actuator

Mặc định, Actuator chỉ expose healthinfo qua HTTP. Bạn có thể cấu hình để expose thêm các endpoints khác hoặc ẩn bớt đi trong file application.properties hoặc application.yml:

# expose tất cả các endpoint qua HTTP (KHÔNG NÊN LÀM TRONG PRODUCTION)
management.endpoints.web.exposure.include=*

# chỉ expose health, info, metrics qua HTTP
management.endpoints.web.exposure.include=health,info,metrics

# exclude một số endpoint cụ thể qua HTTP
management.endpoints.web.exposure.exclude=env,beans

Bạn cũng có thể thay đổi đường dẫn gốc của Actuator (mặc định là `/actuator`):

management.endpoints.web.base-path=/manage

Khi đó, các endpoint sẽ có dạng /manage/health, /manage/info, v.v.

Để tùy chỉnh thông tin hiển thị ở endpoint info, bạn có thể thêm các property bắt đầu bằng info. như đã ví dụ ở trên.

Để tùy chỉnh endpoint health, bạn có thể tạo các class implements interface HealthIndicator và đánh dấu bằng @Component. Spring Boot sẽ tự động nhận diện và tích hợp vào kết quả của /actuator/health.

Bảo Mật Các Endpoint Của Actuator

Đây là phần quan trọng NHẤT khi làm việc với Actuator, đặc biệt là trong môi trường production. Như bạn đã thấy, nhiều endpoint của Actuator cung cấp thông tin nhạy cảm (env, beans) hoặc cho phép thực hiện hành động nguy hiểm (shutdown, thay đổi loggers). Việc expose tất cả các endpoint ra ngoài internet mà không có bảo mật là một lỗ hổng cực lớn.

May mắn thay, khi bạn sử dụng Spring Security (chắc chắn bạn đã đọc các bài viết trước về Spring Security 101, Cấu hình xác thực, v.v. rồi chứ?), các endpoint của Actuator sẽ được bảo mật mặc định.

Spring Security sẽ yêu cầu xác thực (authentication) để truy cập các endpoint của Actuator. Bạn có thể cấu hình chi tiết hơn để chỉ cho phép những người dùng có quyền hạn (role) nhất định mới được truy cập (ví dụ: role ADMIN hoặc ACTUATOR). Việc này được thực hiện trong cấu hình Spring Security của bạn, tương tự như cách bạn bảo vệ các URL thông thường:

@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                // Chỉ cho phép user có role ACTUATOR hoặc ADMIN truy cập các endpoint actuator
                .requestMatchers(EndpointRequest.toAnyEndpoint()).hasAnyRole("ACTUATOR", "ADMIN")
                // Các request khác cần được xác thực
                .anyRequest().authenticated()
                .and()
            .httpBasic(); // Hoặc formLogin(), OAuth2, JWT... tùy cấu hình xác thực của bạn
    }

    // Configure UserDetailsService, PasswordEncoder, etc. as needed
}

Trong ví dụ trên, chúng ta sử dụng EndpointRequest.toAnyEndpoint() để bảo vệ tất cả các endpoint Actuator. Bạn có thể sử dụng các matcher cụ thể hơn nếu muốn (ví dụ: EndpointRequest.to("health", "info")).

Hãy luôn nhớ rằng, an toàn là trên hết khi deploy ứng dụng lên production. Đừng bao giờ expose các endpoint nhạy cảm mà không có lớp bảo vệ cần thiết.

Tích Hợp Với Các Công Cụ Theo Dõi

Sức mạnh thực sự của Actuator được thể hiện khi nó tích hợp với các hệ thống giám sát chuyên nghiệp. Nhờ có các endpoint được cấu trúc chuẩn (đặc biệt là /actuator/metrics), các công cụ này có thể dễ dàng thu thập dữ liệu từ ứng dụng của bạn.

  1. Prometheus: Một hệ thống giám sát và cảnh báo mã nguồn mở phổ biến. Bạn chỉ cần thêm dependency micrometer-registry-prometheus, Actuator sẽ tự động tạo endpoint /actuator/prometheus với định dạng mà Prometheus có thể “scrape” (thu thập) được.
  2. Grafana: Thường đi đôi với Prometheus. Grafana là công cụ tạo dashboard trực quan, cho phép bạn hiển thị các metrics thu thập được từ Prometheus dưới dạng biểu đồ, bảng, v.v., giúp bạn dễ dàng theo dõi trạng thái ứng dụng theo thời gian thực.
  3. Spring Boot Admin: Một dự án mã nguồn mở cung cấp giao diện người dùng (UI) tập trung để quản lý và theo dõi nhiều ứng dụng Spring Boot cùng lúc. Nó sử dụng Actuator endpoints để hiển thị thông tin về sức khỏe, metrics, env, log, v.v., của tất cả các instance ứng dụng của bạn tại một nơi duy nhất. Đây là một công cụ rất hữu ích cho môi trường microservices.

Việc tích hợp này biến Actuator từ một “bảng điều khiển” cơ bản thành một nguồn dữ liệu quan trọng cho hệ thống giám sát doanh nghiệp.

Kết Luận

Spring Boot Actuator là một công cụ không thể thiếu cho bất kỳ ứng dụng Spring Boot nào muốn được triển khai và vận hành một cách chuyên nghiệp. Nó cung cấp cái nhìn sâu sắc về trạng thái, hiệu suất và môi trường hoạt động của ứng dụng, giúp bạn phát hiện và khắc phục sự cố nhanh chóng, tối ưu hóa tài nguyên và đảm bảo sự ổn định.

Hãy chắc chắn rằng bạn luôn tích hợp Actuator vào các dự án Spring Boot của mình ngay từ đầu và dành thời gian cấu hình bảo mật cẩn thận trước khi đưa ứng dụng lên môi trường production. Việc làm chủ Actuator sẽ giúp bạn trở thành một developer giỏi hơn, không chỉ biết cách viết code mà còn biết cách vận hành code một cách hiệu quả.

Chúng ta đã đi được một chặng đường đáng kể trên “Java Spring Roadmap”. Từ những khái niệm cơ bản đến các module nâng cao, mỗi bài viết đều bổ sung một mảnh ghép quan trọng vào bức tranh toàn cảnh về Spring. Hãy tiếp tục theo dõi để khám phá những khía cạnh thú vị khác của Spring Boot trong các bài viết tiếp theo!

Chỉ mục