Spring Cloud Gateway: JWT Authentication, Dynamic Routing và Rate Limiting với Redis

1. Vai Trò Của API Gateway Trong Kiến Trúc Microservices Java
Trong một hệ thống Microservices điển hình, có thể có hàng chục hoặc hàng trăm service nhỏ giao tiếp với nhau. Nếu để Client (Web, Mobile, Third-party) gọi trực tiếp vào từng service, bạn sẽ phải đối mặt với hàng loạt vấn đề: lộ thông tin nội bộ, khó quản lý bảo mật, CORS phức tạp, và khả năng scaling kém.
API Gateway xuất hiện như một Single Entry Point duy nhất, đứng trước toàn bộ hệ thống Microservices, đóng vai trò:
- Điều hướng (Routing): Chuyển tiếp request đến đúng service dựa trên path, header, method…
- Bảo mật tập trung (Authentication/Authorization): Xác thực JWT token ngay tại tầng gateway.
- Giới hạn lưu lượng (Rate Limiting): Bảo vệ hệ thống khỏi các cuộc tấn công DDoS hoặc quá tải do request đột biến.
- Cross-Cutting Concerns: Logging, Monitoring, CORS, Retry, Circuit Breaker…
1.1 Khái niệm Single Entry Point, Cross-Cutting Concerns
Single Entry Point nghĩa là tất cả request từ bên ngoài đều phải đi qua Gateway trước khi chạm tới các service nội bộ. Điều này giúp:
- Che giấu cấu trúc nội bộ của hệ thống.
- Tập trung các xử lý chung (Cross-Cutting Concerns) như bảo mật, logging, rate limit tại một nơi duy nhất, tránh lặp code trong từng service.
Cross-Cutting Concerns là những nghiệp vụ “ngang” xuyên suốt toàn bộ hệ thống, không thuộc riêng một service nào: xác thực, ghi log, giám sát hiệu năng, xử lý CORS, v.v.
1.2 So sánh Spring Cloud Gateway (Non-blocking) vs Zuul 1.x (Blocking)
| Tiêu chí | Spring Cloud Gateway | Netflix Zuul 1.x |
|---|---|---|
| Mô hình I/O | Non-blocking (dựa trên Netty + WebFlux) | Blocking (Servlet-based, mỗi request một thread) |
| Hiệu năng | Cao, xử lý tốt hàng nghìn concurrent connections | Kém hơn, thread-per-request dễ gây tắc nghẽn |
| Khả năng mở rộng | Rất tốt nhờ Reactive Streams | Hạn chế |
| Hỗ trợ WebSocket | Có hỗ trợ | Hạn chế |
| Tương lai | Được Spring tích cực phát triển | Zuul 2.x ra đời nhưng ít phổ biến |
2. Chuẩn Bị Dự Án Spring Cloud Gateway
Trước khi đi vào chi tiết, bạn cần khởi tạo một project Spring Boot với các dependency cần thiết.
2.1 Khởi tạo project với Spring Initializr
Truy cập start.spring.io và chọn:
- Project: Maven
- Language: Java
- Spring Boot: 3.2.x hoặc 3.3.x
- Dependencies:
Spring Cloud Gateway(Reactive)Spring Boot Starter Data Redis ReactiveSpring Boot Starter Actuator(tuỳ chọn, giám sát)Lombok(tuỳ chọn, rút gọn code)
pom.xml (các dependency chính):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/>
</parent>
<properties>
<java.version>21</java.version>
<spring-cloud.version>2023.0.1</spring-cloud.version>
</properties>
<dependencies>
<!-- Spring Cloud Gateway (Reactive) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Redis Reactive -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!-- JWT (JJWT 0.12.x) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<!-- Optional: actuator, lombok -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.2 Cấu hình reactive web
Trong application.yml (hoặc application.properties), thêm:
spring:
main:
web-application-type: reactive # Bắt buộc cho Spring Cloud Gateway
cloud:
gateway:
# Cấu hình routes sẽ được thêm sau
Lưu ý: Nếu không đặt web-application-type: reactive, Spring Boot sẽ khởi động Servlet container và xung đột với reactive Netty – dẫn đến lỗi không khởi động được Gateway.
3. Cấu Hình Route Predicates Và Dynamic Routing
Routing là nhiệm vụ cốt lõi của API Gateway: xác định request này sẽ được chuyển đến đâu (URI nào). Spring Cloud Gateway cung cấp hai cách cấu hình route:
- File cấu hình YAML/Properties – đơn giản, dễ đọc.
- Java DSL (RouteLocator Bean) – linh hoạt, cho phép logic động.
3.1 Cấu hình Route qua YAML
spring:
cloud:
gateway:
routes:
- id: user_service_route
uri: lb://USER-SERVICE
predicates:
- Path=/api/users/**
- Method=GET,POST
- Header=X-Request-Version, v1
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@ipKeyResolver}"
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
- id: order_service_route
uri: http://localhost:8081
predicates:
- Path=/api/orders/**
- Method=POST
Giải thích:
lb://USER-SERVICE: Sử dụng Load Balancer (tích hợp với Discovery Client như Eureka/Nacos) để gọi tới service đăng ký với tênUSER-SERVICE.Path: Chỉ route nếu đường dẫn khớp với pattern.Method: Chỉ route với HTTP method cụ thể.Header: Yêu cầu headerX-Request-Versioncó giá trịv1.
3.2 Cấu hình Route qua Java DSL (Dynamic Routing)
Khi bạn cần logic routing phức tạp hơn (ví dụ: đọc từ database, áp dụng điều kiện runtime), hãy dùng RouteLocator Bean:
@Configuration
public class GatewayRoutesConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user_route", r -> r
.path("/api/users/**")
.and()
.method(HttpMethod.GET)
.filters(f -> f
.addRequestHeader("X-Gateway-Proxy", "SpringCloudGateway")
.circuitBreaker(config -> config
.setName("userServiceCB")
.setFallbackUri("forward:/fallback/users")))
.uri("lb://USER-SERVICE"))
.route("order_route", r -> r
.path("/api/orders/**")
.filters(f -> f
.addRequestHeader("X-Source", "gateway"))
.uri("http://localhost:8081"))
.build();
}
}
Giải thích:
- Sử dụng fluent API từ
RouteLocatorBuilderđể định nghĩa route. .and()cho phép kết hợp nhiều predicate (tương đương phép AND).- Hỗ trợ các filter như
circuitBreaker,addRequestHeader,rewritePath… lb://prefix kích hoạt load balancing qua Discovery Client.
Mở rộng: Bạn có thể kết hợp nhiều RouteLocator Bean trong cùng một ứng dụng, Spring Cloud Gateway sẽ tự động gộp chúng lại.
4. Thực Chiến: Viết Custom Global Authentication Filter Xử Lý JWT
Trong kiến trúc Microservices, việc xác thực JWT token ngay tại Gateway giúp giảm tải cho các service downstream và đảm bảo chỉ những request hợp lệ mới được đi tiếp.
4.1 Bắt Header Authorization trong ServerWebExchange
Global Filter trong Spring Cloud Gateway là class implements GlobalFilter và Ordered (hoặc dùng @Order). Filter này sẽ áp dụng cho tất cả route.
@Component
@Order(-1) // Ưu tiên cao nhất
public class JwtAuthenticationGlobalFilter implements GlobalFilter {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String BEARER_PREFIX = "Bearer ";
private static final String X_USER_ID_HEADER = "X-User-Id";
private static final String X_USER_ROLE_HEADER = "X-User-Role";
private final JwtTokenValidator jwtTokenValidator;
public JwtAuthenticationGlobalFilter(JwtTokenValidator jwtTokenValidator) {
this.jwtTokenValidator = jwtTokenValidator;
}
@Override
public Mono
<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 1. Kiểm tra whitelist (public endpoints)
String path = request.getPath().value();
if (isPublicPath(path)) {
return chain.filter(exchange);
}
// 2. Lấy Authorization header
String authHeader = request.getHeaders().getFirst(AUTHORIZATION_HEADER);
if (authHeader == null || !authHeader.startsWith(BEARER_PREFIX)) {
return onError(exchange, "Missing or invalid Authorization header", HttpStatus.UNAUTHORIZED);
}
String token = authHeader.substring(BEARER_PREFIX.length());
// 3. Xác thực JWT (non-blocking)
return jwtTokenValidator.validateToken(token)
.flatMap(claims -> {
// 4. Lấy thông tin user từ claims
String userId = claims.getSubject();
String role = claims.get("role", String.class);
// 5. Mutate request: thêm header chứa userId và role
ServerHttpRequest mutatedRequest = request.mutate()
.header(X_USER_ID_HEADER, userId)
.header(X_USER_ROLE_HEADER, role != null ? role : "USER")
.build();
ServerWebExchange mutatedExchange = exchange.mutate()
.request(mutatedRequest)
.build();
// 6. Tiếp tục filter chain
return chain.filter(mutatedExchange);
})
.onErrorResume(e -> onError(exchange, "JWT validation failed: " + e.getMessage(), HttpStatus.UNAUTHORIZED));
}
private boolean isPublicPath(String path) {
return path.startsWith("/auth/login")
|| path.startsWith("/auth/refresh")
|| path.startsWith("/actuator/health");
}
private Mono
<Void> onError(ServerWebExchange exchange, String message, HttpStatus status) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(status);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
String json = String.format("{\"error\": \"%s\", \"timestamp\": \"%s\"}",
message, java.time.Instant.now().toString());
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(json.getBytes(StandardCharsets.UTF_8))));
}
}

Giải thích:
@Order(-1)đảm bảo filter này chạy trước hầu hết các filter khác.- Sử dụng
jwtTokenValidator.validateToken(token)trả về `Mono ` – hoàn toàn non-blocking. - Dùng
ServerHttpRequest.mutate()để thêm headerX-User-IdvàX-User-Roletrước khi chuyển tiếp xuống downstream. - Các service downstream có thể đọc header này để biết user đang thực hiện request mà không cần giải mã JWT lại.
- Response lỗi trả về JSON với
Content-Type: application/json(đã thêm so với version cũ).
4.2 Service JwtTokenValidator (Non-blocking) – Sử dụng JJWT 0.12.x
@Component
public class JwtTokenValidator {
private final SecretKey secretKey;
public JwtTokenValidator(@Value("${jwt.secret}") String secret) {
// Tạo SecretKey từ chuỗi base64 hoặc chuỗi plain (nên dùng base64)
this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
}
public Mono
<Claims> validateToken(String token) {
return Mono.fromCallable(() -> {
try {
return Jwts.parser()
.verifyWith(secretKey) // API mới 0.12.x
.build()
.parseSignedClaims(token)
.getPayload();
} catch (Exception e) {
throw new JwtValidationException("Invalid token", e);
}
}).subscribeOn(Schedulers.boundedElastic()); // CPU-bound, chạy thread pool riêng
}
}
⚠️ Lưu ý quan trọng:
- Việc giải mã JWT là thao tác CPU-bound. Để không block Event Loop của Netty, hãy dùng
subscribeOn(Schedulers.boundedElastic()) để chuyển tác vụ nặng sang thread pool riêng.
- Sử dụng
Keys.hmacShaKeyFor() với chuỗi secret đủ mạnh (ít nhất 256 bit cho HS256). Nên lưu secret dưới dạng Base64 trong cấu hình.
Cấu hình secret trong application.yml:
jwt:
secret: "c2VjcmV0LWtleS1mb3Itand0LWF1dGhlbnRpY2F0aW9uLW11c3QtYmUtbG9uZy1lbm91Z2g="
4.3 Đính kèm User Context xuống Downstream
Sau khi filter chạy, request được mutate với header X-User-Id. Các service downstream (Spring Boot REST API) có thể đọc header này:
@RestController
public class UserController {
@GetMapping("/api/users/me")
public ResponseEntity
<UserDto> getCurrentUser(@RequestHeader("X-User-Id") String userId) {
// userId đã được gateway inject, không cần giải mã JWT lại
return ResponseEntity.ok(userService.findById(userId));
}
}
5. Chống Spam Request Với Redis RateLimiter Bean
Rate Limiting là cơ chế giới hạn số lượng request trong một khoảng thời gian, bảo vệ hệ thống khỏi bị quá tải. Spring Cloud Gateway tích hợp sẵn RequestRateLimiterGatewayFilterFactory dựa trên Token Bucket Algorithm và lưu trạng thái trong Redis.

5.1 Cấu hình Redis
spring:
data:
redis:
host: localhost
port: 6379
timeout: 5000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
5.2 Định nghĩa KeyResolver (Tuỳ chỉnh)
KeyResolver xác định key để Redis lưu thông tin rate limit. Mặc định là PrincipalNameKeyResolver (lấy username từ authentication). Bạn có thể tuỳ chỉnh:
@Configuration
public class RateLimiterConfig {
// KeyResolver theo IP client (lấy từ X-Forwarded-For hoặc Remote Address)
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> {
ServerHttpRequest request = exchange.getRequest();
String ip = request.getHeaders().getFirst("X-Forwarded-For");
if (ip == null || ip.isEmpty()) {
// Lấy địa chỉ remote, xử lý null an toàn
var remoteAddress = request.getRemoteAddress();
ip = remoteAddress != null ? remoteAddress.getAddress().getHostAddress() : "unknown";
}
return Mono.just(ip);
};
}
// KeyResolver theo userId (đã được filter JWT gán vào header)
@Bean
public KeyResolver userKeyResolver() {
return exchange -> {
ServerHttpRequest request = exchange.getRequest();
String userId = request.getHeaders().getFirst("X-User-Id");
return Mono.just(userId != null ? userId : "anonymous");
};
}
}
Best Practice: Sử dụng KeyResolver theo UserId thay vì IP để công bằng hơn trong môi trường nhiều user dùng chung IP (NAT, công ty).
5.3 Cấu hình RedisRateLimiter Bean
@Configuration
public class RateLimiterConfig {
@Bean
public RedisRateLimiter redisRateLimiter() {
// replenishRate: 10 requests/giây
// burstCapacity: 20 requests/giây (cho phép burst)
// requestedTokens: 1 token/request
return new RedisRateLimiter(10, 20, 1);
}
}
Giải thích tham số:
replenishRate: Số token được thêm vào bucket mỗi giây (tốc độ ổn định).burstCapacity: Số token tối đa bucket có thể chứa (cho phép burst).requestedTokens: Số token tiêu tốn cho mỗi request (mặc định 1). Nên set rõ ràng để dễ hiểu.
📖 Tham khảo tài liệu chính thức của Spring Cloud Gateway về RequestRateLimiter và RedisRateLimiter.
5.4 Áp dụng Rate Limiter cho Route
Cách 1: YAML
spring:
cloud:
gateway:
routes:
- id: api_route
uri: lb://API-SERVICE
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@userKeyResolver}"
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
Cách 2: Java DSL
@Bean
public RouteLocator rateLimitedRouteLocator(RouteLocatorBuilder builder,
RedisRateLimiter redisRateLimiter,
KeyResolver userKeyResolver) {
return builder.routes()
.route("rate_limited_api", r -> r
.path("/api/**")
.filters(f -> f
.requestRateLimiter(config -> config
.setRateLimiter(redisRateLimiter)
.setKeyResolver(userKeyResolver)))
.uri("lb://API-SERVICE"))
.build();
}
Lưu ý: RequestRateLimiter không hỗ trợ shortcut notation (kiểu RequestRateLimiter=10,20), phải dùng cấu trúc đầy đủ với args như trên.
6. Lỗi Thường Gặp Và Cách Khắc Phục
6.1 Sử dụng thư viện Blocking trong Gateway Filter
❌ Sai:
@Component
public class BadFilter implements GlobalFilter {
@Override
public Mono
<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// RestTemplate là blocking, sẽ gây tắc nghẽn Event Loop!
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://some-service/check", String.class);
// ...
return chain.filter(exchange);
}
}
🔴 Hậu quả: Event Loop của Netty bị block, throughput giảm nghiêm trọng, thậm chí gây deadlock.
✅ Đúng: Sử dụng WebClient (Reactive, non-blocking).
@Component
public class GoodFilter implements GlobalFilter {
private final WebClient webClient;
public GoodFilter(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("http://some-service").build();
}
@Override
public Mono
<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return webClient.get()
.uri("/check")
.retrieve()
.bodyToMono(String.class)
.flatMap(result -> {
// Xử lý kết quả
return chain.filter(exchange);
});
}
}
6.2 Không cấu hình Timeout cho Route
Không có timeout có thể dẫn đến cascading failures khi một service downstream chậm.
✅ Giải pháp: Cấu hình timeout toàn cục và theo route.
spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000 # 1 giây
response-timeout: 5s # 5 giây
Hoặc theo route qua Java DSL:
.route("order_route", r -> r
.path("/api/orders/**")
.filters(f -> f.addRequestHeader("X-Source", "gateway"))
.uri("http://localhost:8081")
.metadata(RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR, 3000) // 3 giây
.metadata(RouteMetadataUtils.CONNECT_TIMEOUT_ATTR, 1000) // 1 giây
)
6.3 KeyResolver trả về key rỗng
Mặc định, nếu KeyResolver trả về key rỗng hoặc null, request sẽ bị từ chối (HTTP 429).
✅ Cách xử lý: Cấu hình cho phép key rỗng hoặc trả về key mặc định.
spring:
cloud:
gateway:
filter:
request-rate-limiter:
deny-empty-key: false
empty-key-status-code: 200
Hoặc trong KeyResolver trả về "default" hoặc "anonymous" khi không có userId (như đã làm ở phần 5.2).
6.4 Quên cấu hình spring.main.web-application-type=reactive
Lỗi: Khởi động Gateway bị lỗi ApplicationContext do conflict giữa Servlet và Reactive.
✅ Sửa: Thêm cấu hình trong application.yml:
spring:
main:
web-application-type: reactive
7. Best Practices Cho Spring Cloud Gateway Production
7.1 Luôn cấu hình Timeout
- Connect timeout: 1-3 giây.
- Response timeout: 5-30 giây tuỳ nghiệp vụ.
- Thiết lập theo route để linh hoạt với từng service.
7.2 Tuỳ chỉnh KeyResolver cho Rate Limiter
- Mặc định
PrincipalNameKeyResolvercó thể không phù hợp. - Nên dùng UserId hoặc ClientId để công bằng.
- Trong môi trường cluster, đảm bảo Redis là shared cache.
7.3 Sử dụng WebClient thay vì RestTemplate
- Tất cả các filter trong Gateway phải là non-blocking.
- RestTemplate, JDBC, JPA đồng bộ đều là cấm kỵ trong reactive stack.
7.4 Tối ưu hiệu năng với JWT Cache
- Việc giải mã JWT có thể tốn CPU. Có thể cache kết quả validation trong Redis/Caffeine với TTL ngắn (ví dụ 1-5 phút) để giảm tải.
7.5 Giám sát và Logging
- Log đầy đủ requestId, userId, path, status code.
- Tích hợp Micrometer để monitor throughput, error rate, latency.
- Sử dụng
actuatorendpoints để kiểm tra sức khỏe Gateway.
7.6 Luôn set requestedTokens rõ ràng trong cấu hình Rate Limiter
Dù mặc định là 1, việc set rõ ràng giúp người đọc hiểu ý đồ và dễ dàng điều chỉnh sau.
8. Câu Hỏi Thường Gặp (FAQ)
8.1 Spring Cloud Gateway khác gì với Nginx Reverse Proxy?
Nginx hoạt động ở tầng Infrastructure (Layer 7 Proxy), xử lý TCP/UDP/HTTP với hiệu năng cực cao, phù hợp cho static file, load balancing đơn giản, SSL termination. Spring Cloud Gateway hoạt động ở tầng Application, tích hợp sâu với hệ sinh thái Spring, cho phép viết logic routing phức tạp, tích hợp Service Discovery, Circuit Breaker, và các custom filter dựa trên code Java. Nginx cứng nhắc với config file, còn Spring Cloud Gateway linh hoạt với code.
8.2 Có thể dùng Spring Security chung với Spring Cloud Gateway không?
Có, nhưng cần hiểu rõ: Spring Security 6+ dựa trên Servlet, trong khi Spring Cloud Gateway dựa trên WebFlux (Reactive). Bạn cần dùng spring-security-config và spring-security-webflux thay vì spring-security-web. Hoặc đơn giản hơn, tự viết Global Filter xử lý JWT như đã hướng dẫn ở trên, vì Spring Cloud Gateway không dùng FilterChain của Servlet.
📚 Để hiểu sâu hơn về JWT trong hệ sinh thái Spring Security, tham khảo bài viết: Spring Security 6 & JWT: Xác thực Stateless.
8.3 Làm thế nào để kiểm tra Redis RateLimiter trong môi trường development?
Bạn có thể:
- Dùng Redis chạy trên Docker (
docker run -p 6379:6379 redis). - Dùng Redis mock (ví dụ: dùng
Embedded Redischo test). - Khi chạy ứng dụng, gửi nhiều request nhanh liên tục đến API được bảo vệ, kiểm tra header
X-RateLimit-Remaining(nếu có) hoặc xem response code 429 khi vượt quá giới hạn.
8.4 Tôi có thể dùng Redis Cluster với Spring Cloud Gateway không?
Có, Spring Boot Data Redis Reactive hỗ trợ Redis Cluster. Chỉ cần cấu hình đúng trong application.yml:
spring:
data:
redis:
cluster:
nodes:
- 127.0.0.1:7001
- 127.0.0.1:7002
- 127.0.0.1:7003

9. Kết Luận
Spring Cloud Gateway là một lựa chọn mạnh mẽ và hiện đại cho tầng API Gateway trong kiến trúc Microservices Java. Với nền tảng non-blocking dựa trên Project Reactor, nó xử lý hiệu quả hàng nghìn concurrent connections. Qua bài viết này, bạn đã nắm được:
- Cách cấu hình Route qua YAML và Java DSL để điều hướng request linh hoạt.
- Cách viết Custom Global Filter xác thực JWT (sử dụng JJWT 0.12.x) và inject user context xuống downstream.
- Cách tích hợp Redis RateLimiter để bảo vệ hệ thống khỏi quá tải.
- Các lỗi thường gặp và best practices để vận hành trong production.
Hãy bắt tay vào triển khai Gateway cho hệ thống Microservices của bạn ngay hôm nay.