MST

星途 面试题库

面试题:微服务架构下Spring Cloud路由管理之高级难度题

假设你在一个复杂的微服务系统中,使用Spring Cloud Gateway进行路由管理。现在需要对特定服务的请求进行动态限流,并根据请求的来源IP进行访问控制,你将如何实现?请描述具体的实现思路和关键代码片段。
35.3万 热度难度
后端开发微服务架构

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 动态限流
    • 使用Spring Cloud Gateway的限流过滤器,如RequestRateLimiter过滤器。
    • 结合Redis作为限流计数器存储,实现动态限流规则的管理。可以通过操作Redis中的限流数据来动态调整限流参数。
  2. 基于IP的访问控制
    • 在Spring Cloud Gateway的过滤器链中添加自定义过滤器。
    • 在自定义过滤器中获取请求的IP地址,与允许访问的IP列表进行比对,决定是否放行请求。

关键代码片段

  1. 动态限流
    • 引入依赖: 在pom.xml中添加Spring Cloud Gateway和Redis相关依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
  • 配置限流过滤器: 在application.yml中配置限流过滤器:
spring:
  cloud:
    gateway:
      routes:
      - id: specific_service_route
        uri: lb://specific - service
        predicates:
        - Path=/specific - service/**
        filters:
        - name: RequestRateLimiter
          args:
            key - resolver: "#{@ipKeyResolver}"
            redis - rate - limiter.replenishRate: 10 # 每秒补充令牌数
            redis - rate - limiter.burstCapacity: 20 # 令牌桶容量
  • 配置Key Resolver: 在配置类中定义Key Resolver,用于根据请求IP生成限流的Key:
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class RateLimitConfig {

    @Bean
    public KeyResolver ipKeyResolver() {
        return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
            }
        };
    }
}
  1. 基于IP的访问控制
    • 创建自定义过滤器
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

@Component
public class IpAccessFilterFactory extends AbstractGatewayFilterFactory<IpAccessFilterFactory.Config> {

    public IpAccessFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            if (config.getAllowedIps().contains(clientIp)) {
                return chain.filter(exchange);
            } else {
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                return Mono.empty();
            }
        };
    }

    public static class Config {
        private List<String> allowedIps;

        public List<String> getAllowedIps() {
            return allowedIps;
        }

        public void setAllowedIps(List<String> allowedIps) {
            this.allowedIps = allowedIps;
        }
    }
}
  • 配置自定义过滤器: 在application.yml中配置自定义过滤器:
spring:
  cloud:
    gateway:
      routes:
      - id: specific_service_route
        uri: lb://specific - service
        predicates:
        - Path=/specific - service/**
        filters:
        - name: IpAccessFilter
          args:
            allowedIps:
            - 192.168.1.100
            - 10.0.0.1