Tích hợp Spring Cloud Tencent cho Kiến trúc Microservice

Spring Cloud Tencent là một giải pháp mã nguồn mở toàn diện cho kiến trúc microservice, được phát triển bởi Tencent. Nền tảng này tích hợp chặt chẽ với Polaris, một hệ thống khám phá và quản lý dịch vụ mã nguồn mở của Tencent, cung cấp các chuẩn SPI của Spring Cloud để phát triển ứng dụng phân tán.

Các tính năng chính của Spring Cloud Tencent bao gồm:

  • Đăng ký và khám phá dịch vụ (Service Registration & Discovery)
  • Quản lý cấu hình động (Dynamic Configuration Management)
  • Quản lý dịch vụ (Service Governance):
    • Giới hạn tốc độ truy cập (Rate Limiting)
    • Ngắt mạch (Circuit Breaking)
    • Định tuyến dịch vụ (Service Routing)
    • ...
  • Truyền tải siêu dữ liệu (Metadata Transfer)

Để bắt đầu sử dụng, các nhà phát triển chỉ cần thêm các dependency cần thiết vào dự án Maven hoặc Gradle. Dưới đây là ví dụ về cách thêm Bill of Materials (BOM) và module khám phá dịch vụ:

<!-- Khai báo BOM của Nền tảng Dịch vụ Phân tán -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.tencent.cloud</groupId>
            <artifactId>spring-cloud-tencent-dependencies</artifactId>
            <version>${sct.platform.version}</version> <!-- Thay đổi thành phiên bản phù hợp -->
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- Thêm dependency cho tính năng khám phá dịch vụ Polaris -->
<dependencies>
    <dependency>
        <groupId>com.tencent.cloud</groupId>
        <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
    </dependency>
</dependencies>

1. Khám phá và Đăng ký Dịch vụ (Discovery)

Module khám phá và đăng ký dịch vụ là một trong những thành phần cốt lõi của Spring Cloud Tencent, thực hiện giao diện SPI chuẩn của Spring Cloud Discovery (ví dụ: PolarisDiscoveryClient.java). Điều này cho phép bất kỳ ứng dụng Spring Cloud tiêu chuẩn nào cũng có thể dễ dàng tích hợp chức năng khám phá dịch vụ từ Spring Cloud Tencent.

Phía sau module này là nền tảng quản lý và khám phá dịch vụ phổ biến Polaris.

1.1. Chuẩn bị Môi trường Polaris

Để sử dụng chức năng khám phá dịch vụ, bạn cần có một máy chủ Polaris đang chạy. Có hai cách chính để chuẩn bị môi trường này:

  • Cài đặt cục bộ Polaris: Tham khảo tài liệu hướng dẫn bắt đầu của Polaris để cài đặt máy chủ Polaris trên môi trường của bạn. Polaris hỗ trợ cài đặt trên nhiều hệ điều hành (Linux, Windows, macOS) và môi trường container (Kubernetes).
  • Sử dụng môi trường thử nghiệm công khai: Polaris thường cung cấp các môi trường thử nghiệm công khai để người dùng có thể trải nghiệm nhanh chóng mà không cần cài đặt. Thông tin về địa chỉ bảng điều khiển và máy chủ thường được cung cấp trên trang web chính thức của Polaris.

Sau khi cài đặt, bạn có thể truy cập bảng điều khiển Polaris qua trình duyệt web (ví dụ: http://127.0.0.1:8080 với tài khoản mặc định polaris/polaris) để quản lý dịch vụ.

1.2. Xây dựng Dịch vụ Spring Cloud Tencent

Để tích hợp chức năng khám phá dịch vụ, hãy làm theo các bước sau:

1.2.1. Cấu hình Maven Parent POM

Trong tệp pom.xml của dự án cha (parent project), hãy khai báo BOM của Spring Cloud Tencent để quản lý phiên bản dependency:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>dev.example</groupId>
    <artifactId>microservice-platform</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>service-provider-app</module>
        <module>shared-libs</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <lombok.version>1.18.24</lombok.version>
        <springboot.version>2.6.7</springboot.version>
        <sct.platform.version>1.5.3-2021.0.2</sct.platform.version> <!-- Phiên bản Spring Cloud Tencent -->
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.tencent.cloud</groupId>
                <artifactId>spring-cloud-tencent-dependencies</artifactId>
                <version>${sct.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>sonatype-snapshots</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

1.2.2. Tạo Module Commons (Thư viện dùng chung)

Module này chứa các lớp và tiện ích dùng chung cho các dịch vụ khác nhau:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>microservice-platform</artifactId>
        <groupId>dev.example</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shared-libs</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.11</version>
        </dependency>
    </dependencies>
</project>

1.2.3. Tạo Module Dịch vụ Cung cấp (Provider)

Module này sẽ là dịch vụ Spring Boot và đăng ký với Polaris:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>dev.example</groupId>
    <artifactId>service-provider-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <parent>
        <groupId>dev.example</groupId>
        <artifactId>microservice-platform</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>dev.example</groupId>
            <artifactId>shared-libs</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>

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

        <!-- Starter cho khám phá dịch vụ Polaris -->
        <dependency>
            <groupId>com.tencent.cloud</groupId>
            <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
        </dependency>
    </dependencies>
</project>

1.2.4. Lớp Khởi động Ứng dụng

Tạo một lớp khởi động Spring Boot cơ bản:

package dev.example.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProviderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderServiceApplication.class, args);
    }
}

1.2.5. Cấu hình Dịch vụ

Trong tệp bootstrap.yml, hãy cấu hình tên ứng dụng và địa chỉ máy chủ Polaris. Lưu ý rằng địa chỉ Polaris thường là một URL gRPC.

server:
  port: 8001

spring:
  application:
    name: my-provider-service # Tên dịch vụ của bạn
  cloud:
    polaris:
      address: grpc://127.0.0.1:8091 # Thay thế bằng địa chỉ máy chủ Polaris của bạn
      namespace: default # Namespace mặc định, có thể thay đổi

1.3. Khởi động và Xác minh Ứng dụng

Sau khi cấu hình, khởi động ứng dụng ProviderServiceApplication. Khi ứng dụng chạy thành công, nó sẽ tự động đăng ký với Polaris. Bạn có thể kiểm tra bảng điều khiển Polaris để xác nhận rằng dịch vụ my-provider-service đã được đăng ký và hiển thị thông tin instance.

Service registration verified on Polaris console

1.4. Sử dụng Mở rộng

1.4.1. Siêu dữ liệu (Metadata)

Các instance dịch vụ thường mang theo các thông tin bổ sung như vị trí datacenter, khu vực, môi trường, v.v. Những thông tin này được gọi là siêu dữ liệu và được đăng ký cùng với instance dịch vụ.

Spring Cloud Tencent hỗ trợ nhiều nguồn để cấu hình siêu dữ liệu:

  1. Từ tệp cấu hình (application.yml):

    Bạn có thể định nghĩa siêu dữ liệu trực tiếp trong tệp cấu hình của ứng dụng. Tuy nhiên, phương pháp này đòi hỏi phải biên dịch lại ứng dụng nếu siêu dữ liệu thay đổi.

    spring:
      cloud:
        tencent:
          metadata:
            content:
              zone: hanoi
              environment: development
    
  2. Từ tham số khởi động ứng dụng (-D):

    Có thể ghi đè các giá trị siêu dữ liệu thông qua tham số khởi động JVM, cho phép điều chỉnh động mà không cần biên dịch lại.

    java -jar -Dspring.cloud.tencent.metadata.content.environment=production service-provider-app.jar
    
  3. Từ biến môi trường:

    Đây là cách tiếp cận linh hoạt nhất, đặc biệt phù hợp cho các môi trường triển khai PaaS hoặc container. Spring Cloud Tencent sẽ tự động đọc các biến môi trường có tiền tố SCT_METADATA_CONTENT_ làm siêu dữ liệu.

    export SCT_METADATA_CONTENT_ZONE=hochiminh
    export SCT_METADATA_CONTENT_ENVIRONMENT=staging
    

    Kiểm tra log khởi động để xác minh siêu dữ liệu đã được tải:

    grep "Loaded static metadata info" app.log
    
  4. Tùy chỉnh thông qua SPI:

    Spring Cloud Tencent cung cấp giao diện SPI để người dùng có thể triển khai nguồn siêu dữ liệu tùy chỉnh của riêng họ, ví dụ: đọc từ tệp cục bộ hoặc gọi API CMDB.

1.4.2. Quản lý Instance qua Bảng điều khiển

Bảng điều khiển Polaris cho phép bạn thực hiện các thao tác quản lý trên các instance dịch vụ đã đăng ký, như điều chỉnh trọng số (weight) hoặc đưa instance vào trạng thái ngoại tuyến (offline) để bảo trì.

Instance control options on Polaris console

1.4.3. Tham số Tùy chỉnh

Ngoài các cấu hình qua bảng điều khiển, bạn có thể điều chỉnh nhiều tham số của Spring Cloud Tencent Discovery thông qua tệp bootstrap.yml, ví dụ như trọng số mặc định của dịch vụ.

Bảng dưới đây liệt kê một số cấu hình quan trọng:

Cấu hình Key Giá trị Mặc định Bắt buộc Mô tả
spring.cloud.polaris.address Không có Địa chỉ máy chủ Polaris.
spring.cloud.polaris.namespace default Không Tên namespace mà dịch vụ thuộc về.
spring.cloud.polaris.service ${spring.application.name} Không Tên dịch vụ.
spring.cloud.polaris.local-ip-address Không có Không Địa chỉ IP của instance được đăng ký. Mặc định Spring Boot sẽ tự động lấy.
spring.cloud.polaris.discovery.enabled true Không Bật/tắt tính năng khám phá dịch vụ.
spring.cloud.polaris.discovery.register true Không Bật/tắt tính năng đăng ký dịch vụ.
spring.cloud.polaris.discovery.instance-enabled true Không Xác định liệu instance dịch vụ hiện tại có thể truy cập được hay không.
spring.cloud.polaris.discovery.token Không có Không Token xác thực.
spring.cloud.polaris.discovery.version null Không Phiên bản microservice.
spring.cloud.polaris.discovery.protocol null Không Loại giao thức microservice.
spring.cloud.polaris.discovery.weight 100 Không Trọng số của microservice.
spring.cloud.polaris.discovery.service-list-refresh-interval 60000 Không Khoảng thời gian làm mới danh sách dịch vụ (miligiây).

2. Trung tâm Cấu hình (Config)

Module trung tâm cấu hình là một thành phần quan trọng khác của Spring Cloud Tencent, triển khai giao diện Spring Cloud PropertySourceLoader SPI (ví dụ: PolarisConfigFileLocator.java). Trong giai đoạn khởi động của ứng dụng, Spring Cloud sẽ sử dụng PolarisConfigFileLocator để tải cấu hình từ máy chủ Polaris và đưa chúng vào ngữ cảnh Spring.

Bạn có thể truy cập nội dung cấu hình bằng các chú thích Spring Boot tiêu chuẩn như @Value@ConfigurationProperties. Khả năng làm mới cấu hình động được hiện thực hóa thông qua cơ chế @RefreshScope chuẩn của Spring Cloud.

Lưu ý quan trọng: Do Spring Cloud PropertySourceLoader SPI được gọi trong giai đoạn Bootstrap, các cấu hình liên quan đến Polaris Config (ví dụ: địa chỉ máy chủ Polaris) cần được đặt trong tệp bootstrap.yml thay vì application.yml để đảm bảo khởi tạo đúng cách.

2.1. Bắt đầu Nhanh

2.1.1. Thêm Dependency

Để sử dụng chức năng trung tâm cấu hình, hãy thêm dependency sau:

<dependency>
    <groupId>com.tencent.cloud</groupId>
    <artifactId>spring-cloud-starter-tencent-polaris-config</artifactId>
</dependency>

2.1.2. Cấu hình bootstrap.yml

Trong tệp bootstrap.yml của dự án, hãy thêm các cấu hình sau. Đảm bảo cấu hình này nằm trong bootstrap.yml.

Các cấu hình chính bao gồm địa chỉ máy chủ Polaris và thông tin về các tệp cấu hình sẽ được inject.

  • Địa chỉ Polaris Config:

    Nếu bạn sử dụng cùng một cụm Polaris cho cả trung tâm cấu hình và đăng ký dịch vụ, chỉ cần cấu hình spring.cloud.polaris.address. Nếu bạn triển khai các cụm Polaris riêng biệt, hãy sử dụng spring.cloud.polaris.config.address để chỉ định địa chỉ của trung tâm cấu hình.

    spring:
      application:
        name: ${application.name}
      cloud:
        polaris:
          address: grpc://127.0.0.1:8091 # Bắt buộc, địa chỉ máy chủ Polaris
          namespace: default # Namespace toàn cầu
          config:
            address: grpc://127.0.0.1:8093 # Tùy chọn, chỉ khi trung tâm cấu hình có địa chỉ khác
            auto-refresh: true # Tùy chọn, tự động làm mới ngữ cảnh Spring khi cấu hình thay đổi (mặc định là true)
    
  • Inject các tệp cấu hình:

    Spring Cloud Tencent Config tự động inject các tệp cấu hình theo quy ước đặt tên của Spring Boot (ví dụ: application.properties, application.yml, bootstrap.properties, bootstrap.yml và các phiên bản theo profile) từ một nhóm cấu hình có tên giống với tên ứng dụng (${spring.application.name}) trên bảng điều khiển Polaris.

    Nếu bạn cần inject các tệp cấu hình tùy chỉnh bổ sung, hãy cấu hình spring.cloud.polaris.config.groups:

    spring:
      cloud:
        polaris:
          config:
            groups:
              - name: ${spring.application.name} # Tên nhóm cấu hình của ứng dụng
                files: [ "custom/app-settings.properties", "custom/db-config.yml" ] # Danh sách các tệp cấu hình tùy chỉnh
    

    Ví dụ cấu hình đầy đủ:

    server:
      port: 8001
    
    spring:
      application:
        name: my-provider-service
      cloud:
        polaris:
          address: grpc://127.0.0.1:8091
          namespace: dev
          config:
            address: grpc://127.0.0.1:8093
            auto-refresh: true
            groups:
              - name: my-provider-service
                files: ["app-config-dev.yml"] # Tệp cấu hình tùy chỉnh theo profile dev
    

2.1.3. Sử dụng Cấu hình trong Mã nguồn

Bạn có thể truy cập các giá trị cấu hình theo các cách chuẩn của Spring Boot:

  • Sử dụng @Value:
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/config-demo")
    @RefreshScope // Kích hoạt làm mới động
    public class ConfigController {
    
        @Value("${app.timeout:5000}") // Giá trị mặc định 5000ms
        private int serviceTimeout;
    
        @GetMapping("/timeout")
        public String getTimeout() {
            return "Service timeout is: " + serviceTimeout + "ms";
        }
    }
    
  • Sử dụng @ConfigurationProperties:

    Để inject một nhóm các thuộc tính liên quan vào một lớp Java:

    package dev.example.config;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.stereotype.Component;
    
    @RefreshScope
    @Component
    @ConfigurationProperties(prefix = "app.settings")
    @Data
    public class ApplicationSettings {
        private String adminName;
        private int maxConnections;
    
        @Override
        public String toString() {
            return "ApplicationSettings{" + "adminName='" + adminName + '\'' + ", maxConnections=" + maxConnections + '}';
        }
    }
    

2.1.4. Quản lý Cấu hình trên Bảng điều khiển Polaris

Để cung cấp cấu hình từ Polaris, bạn cần thực hiện các bước sau trên bảng điều khiển:

  1. Tạo Namespace: Namespace dùng để cô lập logic các tài nguyên, thường được sử dụng để phân biệt môi trường (dev, staging, prod) hoặc các cụm dịch vụ khác nhau.
  2. Tạo Nhóm cấu hình: Nên tạo một nhóm cấu hình có tên trùng với tên ứng dụng của bạn (ví dụ: my-provider-service) để dễ dàng quản lý tất cả cấu hình của ứng dụng đó.
  3. Tạo và Phát hành Tệp cấu hình:

    Trên bảng điều khiển Polaris, bạn có thể tạo các tệp cấu hình với tên có hậu tố (ví dụ: .properties, .yml, .json). Hậu tố này giúp client phân tích cú pháp nội dung tệp. Ví dụ, tạo tệp app-config-dev.yml trong nhóm my-provider-service với nội dung:

    app:
      timeout: 2000
      settings:
        adminName: JohnDoe
        maxConnections: 50
    

    Sau đó, phát hành (publish) cấu hình này.

    Creating a configuration file in Polaris console

2.1.5. Khởi động Ứng dụng và Kiểm tra

Khi ứng dụng khởi động với các cấu hình trên, nó sẽ tải giá trị từ Polaris. Bạn có thể kiểm tra bằng cách gọi API:

curl http://127.0.0.1:8001/config-demo/timeout
# Kết quả: Service timeout is: 2000ms

Nếu bạn thay đổi giá trị app.timeout trên bảng điều khiển Polaris (ví dụ: thành 3000) và phát hành lại, sau đó gọi lại API, bạn sẽ thấy giá trị được làm mới mà không cần khởi động lại ứng dụng:

curl http://127.0.0.1:8001/config-demo/timeout
# Kết quả: Service timeout is: 3000ms

Điều này hoàn tất việc tích hợp Spring Cloud Tencent Config.

2.2. Làm mới Cấu hình Động

Spring Cloud đạt được khả năng làm mới cấu hình động bằng cách xây dựng lại các Bean khi cấu hình thay đổi. Để kích hoạt tính năng này:

  1. Bật công tắc làm mới động: Đảm bảo spring.cloud.polaris.config.auto-refresh=true trong bootstrap.yml (mặc định đã bật).
  2. Gắn chú thích @RefreshScope: Đặt chú thích @RefreshScope lên các Bean hoặc Controller cần được làm mới khi cấu hình thay đổi.

2.3. Listener Cấu hình Tùy chỉnh (phiên bản 1.6.0+)

Từ phiên bản 1.6.0 trở đi, bạn có thể sử dụng chú thích @PolarisConfigKVFileChangeListener để lắng nghe sự thay đổi của các thuộc tính cấu hình cụ thể hoặc các tiền tố thuộc tính. Khi cấu hình thay đổi, phương thức được chú thích sẽ được gọi.

Lưu ý: Hiện tại, tính năng này chỉ hỗ trợ các tệp cấu hình có cấu trúc Key-Value.

package dev.example.config.listener;

import com.tencent.cloud.polaris.config.config.ConfigChangeEvent;
import com.tencent.cloud.polaris.config.config.annotation.PolarisConfigKVFileChangeListener;
import org.springframework.stereotype.Component;

import java.util.Set;

@Component
public class MyConfigChangeListener {

    @PolarisConfigKVFileChangeListener(interestedKeyPrefixes = "app.settings")
    public void handleApplicationSettingsChange(ConfigChangeEvent event) {
        System.out.println("Cấu hình 'app.settings' đã thay đổi:");
        Set<String> changedKeys = event.changedKeys();
        for (String key : changedKeys) {
            System.out.printf("  Key: %s, Giá trị cũ: %s, Giá trị mới: %s\n",
                    key, event.getChange(key).getOldValue(), event.getChange(key).getNewValue());
        }
    }
}

2.4. Tham số Cấu hình Đầy đủ

Dưới đây là bảng các tham số cấu hình chính cho module Polaris Config:

Cấu hình Key Giá trị Mặc định Bắt buộc Mô tả
spring.cloud.polaris.config.enabled true Không Bật/tắt module cấu hình.
spring.cloud.polaris.config.address Không có Không Địa chỉ máy chủ Polaris Config. Chỉ cần cấu hình khi Config và Discovery sử dụng các cụm Polaris khác nhau.
spring.cloud.polaris.config.port 8093 Không Cổng của Polaris Config, mặc định là 8093.
spring.cloud.polaris.config.auto-refresh true Không Có tự động cập nhật cấu hình động hay không.
spring.cloud.polaris.config.groups Không có Không Danh sách các nhóm cấu hình tùy chỉnh sẽ được lấy từ máy chủ Polaris.
spring.cloud.polaris.config.connect-remote-server true Không Có kết nối với máy chủ Polaris Config từ xa hay không. Có thể tắt khi không có môi trường mạng hoặc không có máy chủ Polaris.

2.5. Nguyên lý Hoạt động của Trung tâm Cấu hình Polaris (Đơn giản hóa)

Về cơ bản, Polaris Config Center hoạt động theo mô hình Client-Server để đảm bảo cấu hình được đồng bộ và cập nhật động:

  • Phía Client (Ứng dụng):
    1. Khi ứng dụng khởi động, nó yêu cầu và nhận một bản sao cấu hình mới nhất từ máy chủ.
    2. Sau đó, client tạo danh sách các tệp cấu hình và phiên bản của chúng (List<File->Version>) và gửi yêu cầu đăng ký theo dõi cấu hình tới máy chủ.
    3. Khi nhận được thông báo đẩy (push notification) về việc cấu hình thay đổi, client sẽ yêu cầu lại tệp cấu hình mới nhất từ máy chủ.
  • Phía Server (Polaris):
    1. Máy chủ kiểm tra yêu cầu từ client để xem có tệp cấu hình nào có phiên bản cũ hơn không. Nếu có, máy chủ sẽ phản hồi ngay lập tức với nội dung File -> NewVersion.
    2. Nếu tất cả cấu hình của client đều là mới nhất, máy chủ sẽ giữ kết nối trong khoảng thời gian nhất định (ví dụ: 30 giây). Nếu có bất kỳ cấu hình nào được phát hành trong thời gian này, máy chủ sẽ phản hồi ngay lập tức cho tất cả các client đang theo dõi.
    3. Khi người dùng phát hành cấu hình mới trên bảng điều khiển, máy chủ sẽ cập nhật cơ sở dữ liệu và bộ nhớ cache, sau đó gửi thông báo đến các client đang theo dõi.

3. Giới hạn Tốc độ Truy cập (Rate Limiting)

Giới hạn tốc độ truy cập (Rate Limiting) là một biện pháp bảo vệ dịch vụ phổ biến, giúp ngăn chặn tình trạng quá tải do lưu lượng truy cập đột biến. Module Spring Cloud Tencent Rate Limit cung cấp các Filter giới hạn tốc độ cho Spring Web và Spring WebFlux, tích hợp với chức năng giới hạn tốc độ của Polaris để giúp các ứng dụng dễ dàng triển khai tính năng này.

Các kịch bản giới hạn tốc độ được hỗ trợ bao gồm:

  • Giới hạn tốc độ ở cấp độ dịch vụ.
  • Giới hạn tốc độ theo đường dẫn (path) của yêu cầu.
  • Giới hạn tốc độ chi tiết dựa trên các tham số từ QueryParam, Header trong yêu cầu HTTP.

3.1. Bắt đầu Nhanh

3.1.1. Thêm Dependency

Để sử dụng chức năng giới hạn tốc độ, hãy thêm dependency sau:

<dependency>
    <groupId>com.tencent.cloud</groupId>
    <artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>

3.1.2. Cấu hình bootstrap.yml

Thêm cấu hình Polaris vào tệp bootstrap.yml của bạn:

spring:
  application:
    name: my-provider-service
  cloud:
    polaris:
      address: grpc://127.0.0.1:8091 # Địa chỉ máy chủ Polaris của bạn
      namespace: default

3.1.3. Cấu hình Quy tắc Giới hạn Tốc độ

Bạn có thể cấu hình các quy tắc giới hạn tốc độ một cách linh hoạt trên bảng điều khiển Polaris.

  1. Tạo Dịch vụ: Nếu bạn chưa sử dụng Spring Cloud Tencent Discovery, bạn cần tạo thông tin dịch vụ thủ công trên bảng điều khiển.
  2. Tạo Quy tắc Giới hạn Tốc độ:

    Truy cập trang dịch vụ, chuyển đến tab "Quy tắc Giới hạn Tốc độ" và tạo quy tắc mới. Bạn có thể chọn giới hạn tốc độ đơn lẻ (Single-instance rate limit) hoặc giới hạn tốc độ phân tán (Distributed rate limit).

    • Giới hạn tốc độ đơn lẻ: Có thể cấu hình hiệu ứng là từ chối ngay lập tức (fail-fast) hoặc xếp hàng đều (steady queue).
    • Giới hạn tốc độ phân tán: Hiện tại chỉ hỗ trợ từ chối ngay lập tức và yêu cầu một cụm máy chủ giới hạn tốc độ riêng để phối hợp giữa các node.

    Nhãn biểu thức cho Query, Header, Cookie: Bạn có thể sử dụng các biểu thức đặc biệt để trích xuất các tham số từ yêu cầu HTTP và sử dụng chúng làm nhãn lưu lượng. Ví dụ, ${http.query.userId} sẽ lấy giá trị của tham số userId từ Query String. Điều này cho phép giới hạn tốc độ chi tiết, ví dụ chỉ giới hạn yêu cầu từ userId=1000.

    Rate limit rule based on query parameters in Polaris console

    Các nhãn biểu thức được hỗ trợ:

    • ${http.query.KEY}: Tham số từ Query String.
    • ${http.header.KEY}: Tham số từ Header của yêu cầu.
    • ${http.cookie.KEY}: Tham số từ Cookie.
    • ${http.method}: Phương thức HTTP (GET, POST, PUT, v.v.).
    • ${http.path}: Đường dẫn yêu cầu (bắt đầu bằng /, ví dụ: /user).

    Giới hạn tốc độ với tham số trong Path: Đối với các đường dẫn RESTful có tham số (ví dụ: /users/{userId}/orders), bạn có thể sử dụng biểu thức chính quy để khớp và áp dụng giới hạn tốc độ, ví dụ: /users/.*/orders.

    Rate limit rule with path regex in Polaris console

    Sử dụng Giới hạn tốc độ Phân tán: Nếu chọn giới hạn tốc độ phân tán, bạn cần triển khai một máy chủ giới hạn tốc độ riêng biệt và đăng ký nó với Polaris. Client giới hạn tốc độ sẽ tự động phát hiện máy chủ này qua Polaris. Tên dịch vụ mặc định cho máy chủ giới hạn tốc độ là polaris.limiter trong namespace Polaris, nhưng có thể cấu hình lại.

3.1.4. Khởi động Ứng dụng

Sau khi khởi động ứng dụng, hãy kiểm tra các API HTTP của bạn để xem giới hạn tốc độ có hoạt động không. Nếu một yêu cầu bị từ chối do vượt quá ngưỡng, bạn sẽ nhận được phản hồi mặc định:

The request is deny by rate limit because the throttling threshold is reached

Mã HTTP mặc định khi bị từ chối là 429 (Too Many Requests). Bạn có thể tùy chỉnh nội dung phản hồi bằng thuộc tính spring.cloud.polaris.ratelimit.rejectRequestTips hoặc chỉ định một tệp chứa nội dung phản hồi (ví dụ: HTML) thông qua spring.cloud.polaris.ratelimit.rejectRequestTipsFilePath.

Việc tích hợp giới hạn tốc độ đã hoàn tất.

3.2. Bảng Cấu hình

Dưới đây là một số cấu hình quan trọng cho module giới hạn tốc độ:

Cấu hình Key Giá trị Mặc định Bắt buộc Mô tả
spring.cloud.polaris.ratelimit.enabled true Không Bật/tắt chức năng giới hạn tốc độ dịch vụ.
spring.cloud.polaris.ratelimit.rejectRequestTips Không Nội dung văn bản tùy chỉnh khi từ chối yêu cầu.
spring.cloud.polaris.ratelimit.rejectRequestTipsFilePath Không Đường dẫn đến tệp chứa nội dung phản hồi tùy chỉnh (ví dụ: tệp HTML), thường đặt trong thư mục resources.
spring.cloud.polaris.ratelimit.rejectHttpCode 429 Không Mã trạng thái HTTP tùy chỉnh khi từ chối yêu cầu.
spring.cloud.polaris.ratelimit.maxQueuingTime 1000 Không Thời gian xếp hàng tối đa (miligiây) cho giới hạn tốc độ kiểu xếp hàng đều.

4. Ngắt mạch (Circuit Breaker)

Ngắt mạch (Circuit Breaking) là một cơ chế chịu lỗi phổ biến, giúp bảo vệ hệ thống khỏi các instance dịch vụ bị lỗi hoặc có tỷ lệ lỗi cao. Cơ chế này tự động cô lập các instance gây lỗi, đồng thời thiết lập các nhiệm vụ thăm dò định kỳ để kiểm tra trạng thái của chúng. Khi các điều kiện phục hồi được đáp ứng, instance sẽ chuyển sang trạng thái bán mở (half-open), cho phép một lượng nhỏ yêu cầu đi qua để thăm dò thực tế. Dựa trên kết quả thăm dò này, hệ thống sẽ quyết định có hoàn toàn phục hồi instance hay không.

Ví dụ, nếu instance 3 của dịch vụ được gọi gặp sự cố, hệ thống sẽ tự động chuyển hướng các yêu cầu đến instance 1 và instance 2 còn hoạt động, đảm bảo rằng dịch vụ vẫn có thể được gọi bình thường.

Circuit Breaker Diagram

4.1. Các Chiến lược Ngắt mạch

  • Ngắt mạch theo tỷ lệ lỗi (Fault Ratio Circuit Breaking): Khi số lượng yêu cầu thành công trong một khoảng thời gian nhất định (mặc định 1 phút) đạt hoặc vượt ngưỡng tối thiểu (mặc định 10 yêu cầu), và tỷ lệ lỗi đạt hoặc vượt ngưỡng tỷ lệ lỗi (mặc định 50%), instance sẽ bị cô lập. Ngưỡng tỷ lệ lỗi nằm trong khoảng [0.0, 1.0].
  • Ngắt mạch theo lỗi liên tiếp (Consecutive Fault Circuit Breaking): Nếu số lượng yêu cầu thất bại liên tiếp trong một khoảng thời gian nhất định (mặc định 1 phút) đạt hoặc vượt ngưỡng lỗi liên tiếp (mặc định 10 yêu cầu), instance sẽ bị cô lập.
  • Thời gian cô lập ngắt mạch (Circuit Breaking Isolation Time): Mặc định là 30 giây và có thể cấu hình được.

Spring Cloud Tencent CircuitBreaker tích hợp với khả năng ngắt mạch của Polaris để cung cấp một triển khai ngắt mạch chuẩn.

4.2. Bắt đầu Nhanh

4.2.1. Thêm Dependency

Để sử dụng chức năng ngắt mạch, cả dịch vụ gọi (caller) và dịch vụ được gọi (callee) đều cần có dependency khám phá dịch vụ. Dịch vụ gọi cần thêm dependency ngắt mạch:

  • Cho cả Caller và Callee (Discovery):
    <dependency>
        <groupId>com.tencent.cloud</groupId>
        <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
    </dependency>
    
  • Chỉ cho Caller (Circuit Breaker):
    <dependency>
        <groupId>com.tencent.cloud</groupId>
        <artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
    </dependency>
    

4.2.2. Cấu hình bootstrap.yml

Thêm cấu hình Polaris vào tệp bootstrap.yml của bạn:

spring:
  application:
    name: my-calling-service # Hoặc tên dịch vụ của bạn
  cloud:
    polaris:
      address: grpc://127.0.0.1:8091 # Địa chỉ máy chủ Polaris
      namespace: default
    loadbalancer:
      configurations: polaris # Cần thiết cho các phiên bản SDK 2020.0.x

4.2.3. Khởi động và Xác minh Ứng dụng

Sau khi cấu hình, khởi động ứng dụng. Các ứng dụng sẽ đăng ký với Polaris. Để xác minh chức năng ngắt mạch, bạn nên chạy ít nhất hai instance cho dịch vụ được gọi (callee). Ví dụ, một instance hoạt động bình thường (example-b) và một instance mô phỏng lỗi (example-b2).

Khi dịch vụ gọi gửi yêu cầu, ban đầu một số yêu cầu có thể đến instance bị lỗi, kích hoạt cơ chế ngắt mạch. Sau đó, tất cả các yêu cầu tiếp theo sẽ chỉ được gửi đến các instance hoạt động bình thường, chứng tỏ rằng cơ chế ngắt mạch đã hoạt động.

Circuit Breaker instances on Polaris console

Việc tích hợp Spring Cloud Tencent Circuitbreaker đã hoàn tất.

4.3. Điều chỉnh Cấu hình Ngắt mạch

Bảng điều khiển Polaris cho phép bạn điều chỉnh động các tham số ngắt mạch để phù hợp với các kịch bản kinh doanh cụ thể của bạn. Các quy tắc ngắt mạch cần được cấu hình trên dịch vụ được gọi.

Circuit Breaker rules configuration in Polaris console

4.4. Bảng Cấu hình

Dưới đây là cấu hình chính cho module ngắt mạch:

Cấu hình Key Giá trị Mặc định Bắt buộc Mô tả
spring.cloud.polaris.circuitbreaker.enabled true Không Bật/tắt chức năng ngắt mạch do lỗi.

5. Định tuyến Dịch vụ (Router)

Khi dịch vụ A gọi dịch vụ B, trước tiên nó sẽ lấy toàn bộ địa chỉ của các instance dịch vụ B từ trung tâm đăng ký. Nếu không có định tuyến dịch vụ, bộ cân bằng tải sẽ trực tiếp chọn một instance từ danh sách này dựa trên thuật toán cân bằng tải. Tuy nhiên, khi định tuyến dịch vụ được thêm vào, việc chọn instance sẽ diễn ra qua hai giai đoạn:

  • Giai đoạn 1: Định tuyến Dịch vụ - Từ toàn bộ danh sách instance dịch vụ, chọn ra một tập hợp các instance mục tiêu dựa trên các quy tắc định tuyến.
  • Giai đoạn 2: Cân bằng Tải - Từ tập hợp các instance mục tiêu đã chọn ở giai đoạn 1, sử dụng thuật toán cân bằng tải để chọn một instance duy nhất để gửi yêu cầu.

Định tuyến dịch vụ có nhiều ứng dụng rộng rãi, như triển khai Canary (Canary Release), triển khai theo thang độ xám (Grey Release), triển khai Blue/Green, hoặc giới hạn lưu lượng truy cập theo khu vực (datacentre convergence).

Spring Cloud Tencent Router mở rộng khả năng định tuyến dịch vụ và tích hợp với tính năng định tuyến của Polaris, cung cấp các tính năng định tuyến sẵn sàng sử dụng.

5.1. Nguyên lý Hoạt động của Định tuyến Dịch vụ

Nguyên lý của định tuyến dịch vụ khá đơn giản: lấy danh sách đầy đủ các instance dịch vụ khỏe mạnh từ trung tâm đăng ký, sau đó áp dụng một loạt các plugin RouterFilter để lọc ra các instance thỏa mãn điều kiện. Mỗi loại định tuyến dịch vụ (ví dụ: định tuyến theo siêu dữ liệu, định tuyến theo độ gần) là một triển khai của RouterFilter, và người dùng cũng có thể tự định nghĩa RouterFilter để đáp ứng các kịch bản định tuyến đặc biệt.

5.2. Sử dụng Định tuyến Dịch vụ

Hiện tại, Spring Cloud Tencent Router tích hợp ba khả năng định tuyến dịch vụ chính:

  • Định tuyến theo siêu dữ liệu (Metadata Routing)
  • Định tuyến theo độ gần (Proximity Routing)
  • Định tuyến theo quy tắc (Rule-based Routing)

Trước khi sử dụng bất kỳ loại định tuyến nào, bạn cần tham khảo tài liệu hướng dẫn cơ bản về định tuyến dịch vụ để thêm dependency của Router và cấu hình các thiết lập liên quan để kích hoạt khả năng định tuyến dịch vụ.

5.3. Điều chỉnh Chiến lược Cân bằng Tải

Spring Cloud Tencent cung cấp một cách để điều chỉnh chiến lược cân bằng tải thông qua cấu hình spring.cloud.polaris.loadbalancer.strategy. Các giá trị có thể đặt là:

Giá trị Chiến lược Cân bằng Tải
random Thuật toán ngẫu nhiên
roundRobin Thuật toán vòng tròn (Round Robin)
polarisWeighted Thuật toán trọng số của Polaris (yêu cầu cấu hình trọng số trên bảng điều khiển Polaris)
responseTimeWeighted Thuật toán trọng số dựa trên thời gian phản hồi
bestAvailable Thuật toán số lượng kết nối đồng thời thấp nhất

6. Truyền tải Siêu dữ liệu (Metadata Transfer)

Trong kiến trúc microservice, việc quản lý siêu dữ liệu (metadata) bên trong hoặc giữa các instance dịch vụ là rất quan trọng. Siêu dữ liệu này có thể là thông tin hệ thống cơ bản để sử dụng nội bộ, hoặc dữ liệu cần được truyền tải giữa các instance trong toàn bộ chuỗi cuộc gọi dịch vụ (full-link tracing). Các thành phần mặc định của Spring Cloud không cung cấp chức năng này, do đó, Spring Cloud Tencent đã phát triển một giải pháp quản lý siêu dữ liệu để hỗ trợ các thành phần của mình và cung cấp cho nhà phát triển.

6.1. Phân loại Siêu dữ liệu

Chức năng quản lý siêu dữ liệu cho phép ứng dụng đọc siêu dữ liệu từ nhiều nguồn khác nhau để phù hợp với các kịch bản sử dụng đa dạng. Siêu dữ liệu có thể được phân loại theo nguồn gốc:

  • Đọc từ biến môi trường hệ thống.
  • Đọc từ tệp cấu hình.
  • Được truyền từ dịch vụ upstream (phía trên trong chuỗi gọi).

Ngoài ra, siêu dữ liệu còn được phân loại theo loại truyền tải:

  • Siêu dữ liệu có thể truyền tải (Transitive Metadata): Được truyền xuống các dịch vụ downstream.
  • Siêu dữ liệu không thể truyền tải (Non-Transitive Metadata): Chỉ được sử dụng trong phạm vi instance dịch vụ hiện tại.

6.2. Hướng dẫn Sử dụng

6.2.1. Đọc từ Biến môi trường Hệ thống

Bạn có thể thêm các biến môi trường bắt đầu bằng SCT_METADATA_CONTENT_ để định nghĩa các cặp khóa-giá trị siêu dữ liệu. Biến môi trường SCT_METADATA_CONTENT_TRANSITIVE (với các khóa được phân tách bằng dấu phẩy) chỉ định siêu dữ liệu nào sẽ được truyền xuống dịch vụ downstream.

Spring Cloud Tencent cũng hỗ trợ ba biến môi trường đặc biệt để chỉ định thông tin vị trí của instance dịch vụ: SCT_METADATA_ZONE, SCT_METADATA_REGIONSCT_METADATA_CAMPUS, được sử dụng cho định tuyến theo độ gần (proximity routing).

Ví dụ:

SCT_METADATA_CONTENT_environment=test
SCT_METADATA_CONTENT_label=versionA
SCT_METADATA_CONTENT_userId=12345
SCT_METADATA_CONTENT_TRANSITIVE=environment,label
SCT_METADATA_ZONE=north-zone
SCT_METADATA_REGION=hanoi-region
SCT_METADATA_CAMPUS=datacenter-1

Trong ví dụ trên, (environment, test)(label, versionA) sẽ được truyền xuống các dịch vụ downstream, trong khi (userId, 12345) chỉ được sử dụng cục bộ. Ba dòng cuối cùng là thông tin vị trí.

6.2.2. Đọc từ Tệp Cấu hình

Siêu dữ liệu tùy chỉnh có thể được khai báo trong tệp application.yml (hoặc bootstrap.yml) dưới spring.cloud.tencent.metadata.content. Các khóa được liệt kê trong spring.cloud.tencent.metadata.transitive sẽ được truyền đi.

Ví dụ, (correlationId, abc) sẽ được truyền đi, còn (debugMode, true) thì không:

spring:
  cloud:
    tencent:
      metadata:
        content:
          correlationId: abc
          debugMode: true
        transitive:
          - correlationId

6.2.3. Truyền từ Dịch vụ Upstream

Siêu dữ liệu cũng có thể được truyền qua chuỗi gọi dịch vụ thông qua HTTP header. Các header bắt đầu bằng X-SCT-Metadata-Transitive- sẽ được module spring-cloud-starter-tencent-metadata-transfer nhận diện và đưa vào siêu dữ liệu có thể truyền tải.

Ví dụ, một yêu cầu HTTP có thể trông như sau:

curl -L -X GET 'localhost:8080/my-service/data' -H 'X-SCT-Metadata-Transitive-env: production'

Ở đây, giá trị production cho khóa env sẽ được trích xuất và truyền đi.

6.2.4. Thêm Dependency

Để sử dụng chức năng truyền tải siêu dữ liệu, hãy thêm dependency sau:

<!-- Khai báo BOM -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.tencent.cloud</groupId>
            <artifactId>spring-cloud-tencent-dependencies</artifactId>
            <version>${sct.platform.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- Thêm dependency Metadata Transfer -->
<dependencies>
    <dependency>
        <groupId>com.tencent.cloud</groupId>
        <artifactId>spring-cloud-starter-tencent-metadata-transfer</artifactId>
    </dependency>
</dependencies>

6.3. API Siêu dữ liệu

Để truy cập siêu dữ liệu trong mã nguồn của bạn, bạn có thể sử dụng các API sau:

6.3.1. Truy cập Metadata có thể truyền tải

Sử dụng MetadataContextHolder để truy cập các siêu dữ liệu trong ngữ cảnh của luồng hiện tại (ThreadLocal):

import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;

// Lấy Map chứa siêu dữ liệu có thể truyền tải
Map<String, String> transitiveMetadata = MetadataContextHolder.get().getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
System.out.println("Transitive Metadata: " + transitiveMetadata);

6.3.2. Truy cập Metadata Tĩnh (Static)

Sử dụng StaticMetadataManager (cần inject bean này) để truy cập các siêu dữ liệu tĩnh được tải từ biến môi trường hoặc tệp cấu hình:

import com.tencent.cloud.common.metadata.StaticMetadataManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class MetadataReader {

    @Autowired
    private StaticMetadataManager staticMetadataManager;

    public void printMetadata() {
        System.out.println("Zone: " + staticMetadataManager.getZone());
        System.out.println("Region: " + staticMetadataManager.getRegion());
        System.out.println("Campus: " + staticMetadataManager.getCampus());

        // Lấy tất cả metadata địa lý
        Map<String, String> locationMetadata = staticMetadataManager.getLocationMetadata();
        System.out.println("Location Metadata: " + locationMetadata);

        // Lấy tất cả metadata từ biến môi trường
        Map<String, String> envMetadata = staticMetadataManager.getAllEnvMetadata();
        System.out.println("All Environment Metadata: " + envMetadata);

        // Lấy metadata từ biến môi trường có thể truyền tải
        Map<String, String> envTransitiveMetadata = staticMetadataManager.getEnvTransitiveMetadata();
        System.out.println("Environment Transitive Metadata: " + envTransitiveMetadata);

        // Lấy tất cả metadata từ tệp cấu hình
        Map<String, String> configMetadata = staticMetadataManager.getAllConfigMetadata();
        System.out.println("All Config Metadata: " + configMetadata);

        // Lấy metadata từ tệp cấu hình có thể truyền tải
        Map<String, String> configTransitiveMetadata = staticMetadataManager.getConfigTransitiveMetadata();
        System.out.println("Config Transitive Metadata: " + configTransitiveMetadata);

        // Lấy tất cả metadata tĩnh đã được hợp nhất
        Map<String, String> mergedStaticMetadata = staticMetadataManager.getMergedStaticMetadata();
        System.out.println("Merged Static Metadata: " + mergedStaticMetadata);

        // Lấy tất cả metadata tĩnh có thể truyền tải đã được hợp nhất
        Map<String, String> mergedStaticTransitiveMetadata = staticMetadataManager.getMergedStaticTransitiveMetadata();
        System.out.println("Merged Static Transitive Metadata: " + mergedStaticTransitiveMetadata);
    }
}

Thẻ: spring-cloud-tencent polaris Microservices service-discovery configuration-management

Đăng vào ngày 6 tháng 8 lúc 22:02