如何优化Spring Boot应用以处理每秒百万请求.md 26 KB

title: 如何优化Spring Boot应用以处理每秒百万请求 author: Gamehu tags:

  • Spring Boot categories:
  • 工作 date: 2025-05-13 22:31:00 ---

如何优化Spring Boot应用以处理每秒百万请求

在当今高流量的互联网环境中,应用程序需要处理的请求量正在迅速增长。作为Java开发者,我们经常面临如何扩展Spring Boot应用以处理大量并发请求的挑战。本文将探讨如何将Spring Boot应用从处理每秒5万请求优化到每秒100万请求的实用策略,并提供详细的代码示例和实施步骤。

面临的挑战

想象一下这样的场景:你的团队被告知应用需要在三个月内实现20倍的流量增长,从每秒5万请求提升到每秒100万请求,而且硬件预算有限。这听起来几乎是不可能完成的任务。然而,通过深入分析性能瓶颈和应用一系列优化技术,我们可以达成这一目标。

在开始优化之前,我们需要了解系统的现状:

  • 基于Spring Boot 2.x的传统MVC架构
  • 使用内嵌的Tomcat服务器
  • 采用JPA进行数据库访问
  • 典型的N层架构(Controller > Service > Repository)
  • 高峰期出现频繁的GC暂停和超时错误

关键性能指标

在开始优化过程之前,了解我们的目标至关重要。成功优化后的应用应该达到以下性能指标:

  • 最大吞吐量:每秒120万请求
  • 平均响应时间:85毫秒(优化前为350毫秒)
  • 95%响应时间:120毫秒(优化前为850毫秒)
  • 峰值CPU使用率:60-70%(优化前为85-95%)
  • 内存使用:可用堆的50%(优化前为75%)
  • 数据库查询:通过缓存减少70%

优化策略

1. 采用响应式编程模型(Spring WebFlux)

最有影响力的变化是采用Spring WebFlux进行响应式编程。这不仅仅是简单的替换,而是需要重新思考应用程序的结构。首先,更新项目依赖:

<!-- 将spring-boot-starter-web替换为spring-boot-starter-webflux -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>2.7.5</version>
</dependency>

<!-- 使用Netty作为服务器 -->
<dependency>
    <groupId>io.projectreactor.netty</groupId>
    <artifactId>reactor-netty</artifactId>
    <version>1.0.24</version>
</dependency>

<!-- 引入Reactor测试支持 -->
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
</dependency>

然后,改变控制器实现方式:

// 传统Spring MVC控制器
@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    @Autowired
    private ProductService productService;
    
    @GetMapping("/{id}")
    public ResponseEntity<Product> getProduct(@PathVariable Long id) {
        Product product = productService.getProductById(id);
        return ResponseEntity.ok(product);
    }
    
    @GetMapping
    public ResponseEntity<List<Product>> getAllProducts() {
        List<Product> products = productService.getAllProducts();
        return ResponseEntity.ok(products);
    }
}

// 响应式WebFlux控制器
@RestController
@RequestMapping("/api/products")
public class ReactiveProductController {
    
    @Autowired
    private ReactiveProductService productService;
    
    @GetMapping("/{id}")
    public Mono<ResponseEntity<Product>> getProduct(@PathVariable Long id) {
        return productService.getProductById(id)
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());
    }
    
    @GetMapping
    public Mono<ResponseEntity<List<Product>>> getAllProducts() {
        return productService.getAllProducts()
            .collectList()
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());
    }
}

服务层也需要相应改变:

// 传统的服务实现
@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;
    
    public Product getProductById(Long id) {
        return repository.findById(id)
            .orElseThrow(() -> new ProductNotFoundException(id));
    }
    
    public List<Product> getAllProducts() {
        return repository.findAll();
    }
}

// 响应式服务实现
@Service
public class ReactiveProductService {
    @Autowired
    private ReactiveProductRepository repository;
    
    public Mono<Product> getProductById(Long id) {
        return repository.findById(id)
            .switchIfEmpty(Mono.error(new ProductNotFoundException(id)));
    }
    
    public Flux<Product> getAllProducts() {
        return repository.findAll();
    }
}

2. 优化数据库访问

数据库通常是系统的主要瓶颈。以下是一些优化数据库访问的详细策略:

2.1 采用响应式数据库驱动

将传统的JDBC驱动替换为响应式数据库驱动:

<!-- 添加R2DBC依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>

<!-- MySQL的R2DBC驱动 -->
<dependency>
    <groupId>dev.miku</groupId>
    <artifactId>r2dbc-mysql</artifactId>
    <version>0.8.2.RELEASE</version>
</dependency>

配置R2DBC连接:

@Configuration
public class R2dbcConfig {
    
    @Bean
    public ConnectionFactory connectionFactory() {
        return MySqlConnectionFactory.from(
            MySqlConnectionConfiguration.builder()
                .host("localhost")
                .port(3306)
                .username("root")
                .password("password")
                .database("reactive_demo")
                .build()
        );
    }
    
    @Bean
    public R2dbcEntityTemplate r2dbcEntityTemplate(ConnectionFactory connectionFactory) {
        return new R2dbcEntityTemplate(connectionFactory);
    }
}

创建响应式Repository:

public interface ReactiveProductRepository extends ReactiveCrudRepository<Product, Long> {
    
    Flux<Product> findByCategory(String category);
    
    Mono<Product> findByName(String name);
    
    @Query("SELECT * FROM products WHERE price > :minPrice")
    Flux<Product> findExpensiveProducts(BigDecimal minPrice);
}

2.2 实施多级缓存策略

引入Redis缓存:

<!-- Redis响应式支持 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

配置Redis缓存:

@Configuration
@EnableRedisRepositories
public class RedisConfig {
    
    @Bean
    public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
        return new LettuceConnectionFactory("localhost", 6379);
    }
    
    @Bean
    public ReactiveRedisTemplate<String, Product> reactiveRedisTemplate(
            ReactiveRedisConnectionFactory factory) {
        
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Product> valueSerializer = 
            new Jackson2JsonRedisSerializer<>(Product.class);
        
        RedisSerializationContext.RedisSerializationContextBuilder<String, Product> builder =
            RedisSerializationContext.newSerializationContext(keySerializer);
        
        RedisSerializationContext<String, Product> context = 
            builder.value(valueSerializer).build();
        
        return new ReactiveRedisTemplate<>(factory, context);
    }
}

在服务层实现缓存:

@Service
public class CachedProductService {
    
    private static final String CACHE_KEY_PREFIX = "product:";
    private static final Duration CACHE_TTL = Duration.ofMinutes(10);
    
    @Autowired
    private ReactiveProductRepository repository;
    
    @Autowired
    private ReactiveRedisTemplate<String, Product> redisTemplate;
    
    public Mono<Product> getProductById(Long id) {
        String cacheKey = CACHE_KEY_PREFIX + id;
        
        // 先尝试从缓存获取
        return redisTemplate.opsForValue().get(cacheKey)
            .switchIfEmpty(
                // 缓存未命中,从数据库加载
                repository.findById(id)
                    .flatMap(product -> {
                        // 将结果存入缓存
                        return redisTemplate.opsForValue()
                            .set(cacheKey, product, CACHE_TTL)
                            .thenReturn(product);
                    })
            );
    }
    
    public Flux<Product> getAllProducts() {
        // 对于列表类型的数据,可以使用不同的缓存策略
        return repository.findAll();
    }
    
    // 清除缓存的方法,在更新产品时调用
    public Mono<Void> invalidateCache(Long id) {
        String cacheKey = CACHE_KEY_PREFIX + id;
        return redisTemplate.delete(cacheKey);
    }
}

2.3 优化SQL查询

使用索引优化:

-- 为常用查询字段添加索引
CREATE INDEX idx_product_category ON products(category);
CREATE INDEX idx_product_price ON products(price);
CREATE INDEX idx_product_name ON products(name);

优化查询方法:

// 避免使用count(*)
public Mono<Boolean> existsByCategory(String category) {
    return repository.findFirstByCategory(category)
        .map(product -> true)
        .defaultIfEmpty(false);
}

// 使用分页减少数据传输量
public Flux<Product> getProductsByCategory(String category, int page, int size) {
    return repository.findByCategory(category, 
        PageRequest.of(page, size, Sort.by("name").ascending()));
}

// 使用投影只返回需要的字段
@Query("SELECT id, name, price FROM products WHERE category = :category")
Flux<ProductSummary> findProductSummariesByCategory(String category);

2.4 实现读写分离

配置主从数据源:

@Configuration
public class DatabaseConfig {
    
    @Bean
    @Primary
    @Qualifier("masterConnectionFactory")
    public ConnectionFactory masterConnectionFactory() {
        return MySqlConnectionFactory.from(
            MySqlConnectionConfiguration.builder()
                .host("master-db.example.com")
                .port(3306)
                .username("master_user")
                .password("master_pass")
                .database("products")
                .build()
        );
    }
    
    @Bean
    @Qualifier("slaveConnectionFactory")
    public ConnectionFactory slaveConnectionFactory() {
        return MySqlConnectionFactory.from(
            MySqlConnectionConfiguration.builder()
                .host("slave-db.example.com")
                .port(3306)
                .username("read_user")
                .password("read_pass")
                .database("products")
                .build()
        );
    }
    
    @Bean
    public TransactionManager transactionManager(
            @Qualifier("masterConnectionFactory") ConnectionFactory connectionFactory) {
        return new R2dbcTransactionManager(connectionFactory);
    }
}

创建读写分离的Repository:

@Repository
public class ReadWriteProductRepository {
    
    private final R2dbcEntityTemplate masterTemplate;
    private final R2dbcEntityTemplate slaveTemplate;
    
    public ReadWriteProductRepository(
            @Qualifier("masterConnectionFactory") ConnectionFactory masterFactory,
            @Qualifier("slaveConnectionFactory") ConnectionFactory slaveFactory) {
        this.masterTemplate = new R2dbcEntityTemplate(masterFactory);
        this.slaveTemplate = new R2dbcEntityTemplate(slaveFactory);
    }
    
    // 写操作使用主库
    @Transactional
    public Mono<Product> save(Product product) {
        return masterTemplate.insert(Product.class)
            .into("products")
            .using(product);
    }
    
    // 读操作使用从库
    public Mono<Product> findById(Long id) {
        return slaveTemplate.select(Product.class)
            .from("products")
            .matching(Query.query(Criteria.where("id").is(id)))
            .one();
    }
    
    public Flux<Product> findAll() {
        return slaveTemplate.select(Product.class)
            .from("products")
            .all();
    }
}

3. 配置调优

性能提升往往来自于正确的配置调整。以下是详细的配置优化步骤:

3.1 调整Netty服务器参数

application.yml中配置Netty参数:

spring:
  webflux:
    base-path: /api

  netty:
    connection:
      timeout: 5000  # 连接超时时间(毫秒)
    worker:
      count: 16      # worker线程数量, 建议设置为CPU核心数的2倍
    boss:
      count: 2       # boss线程数量
    buffer:
      size: 32768    # 缓冲区大小(字节)

在Java代码中自定义Netty配置:

@Configuration
public class NettyConfig {
    
    @Bean
    public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
        NettyReactiveWebServerFactory factory = new NettyReactiveWebServerFactory();
        
        factory.addServerCustomizers(server -> {
            HttpServer httpServer = (HttpServer) server;
            
            // 设置更大的接收缓冲区大小
            httpServer.tcpConfiguration(tcpServer -> 
                tcpServer.option(ChannelOption.SO_RCVBUF, 128 * 1024)
                         .option(ChannelOption.SO_SNDBUF, 128 * 1024)
                         .option(ChannelOption.SO_KEEPALIVE, true)
                         .option(ChannelOption.SO_REUSEADDR, true)
                         .option(ChannelOption.TCP_NODELAY, true));
            
            return httpServer;
        });
        
        return factory;
    }
}

3.2 优化JVM堆和垃圾收集器

application.properties中添加JVM参数,或者直接在启动脚本中配置:

# 堆内存设置
-Xms4g
-Xmx4g

# 年轻代大小,建议为堆的1/3到1/2
-Xmn2g

# GC相关设置,使用G1收集器
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:ParallelGCThreads=8
-XX:ConcGCThreads=2
-XX:InitiatingHeapOccupancyPercent=70

# 禁用类元数据的GC,防止Full GC
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m

# 优化内存分配
-XX:+AlwaysPreTouch
-XX:+DisableExplicitGC

# 开启GC日志记录
-Xlog:gc*:file=logs/gc-%t.log:time,uptime,level,tags:filecount=5,filesize=100m

3.3 连接池优化

配置R2DBC连接池:

@Configuration
public class ConnectionPoolConfig {
    
    @Bean
    public ConnectionFactory connectionFactory() {
        ConnectionPoolConfiguration configuration = ConnectionPoolConfiguration.builder()
            .connectionFactory(createConnectionFactory())
            .maxIdleTime(Duration.ofMinutes(30))
            .maxLifeTime(Duration.ofHours(2))
            .maxAcquireTime(Duration.ofSeconds(3))
            .initialSize(10)
            .maxSize(50)  // 根据负载调整
            .minIdle(10)
            .build();
        
        return new ConnectionPool(configuration);
    }
    
    private ConnectionFactory createConnectionFactory() {
        return MySqlConnectionFactory.from(
            MySqlConnectionConfiguration.builder()
                .host("localhost")
                .port(3306)
                .username("root")
                .password("password")
                .database("reactive_demo")
                .connectTimeout(Duration.ofSeconds(3))
                .build()
        );
    }
}

配置Redis连接池:

@Configuration
public class RedisConnectionConfig {
    
    @Bean
    public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(100))  // 命令超时
            .shutdownTimeout(Duration.ZERO)          // 关闭超时
            .clientOptions(ClientOptions.builder()
                .socketOptions(SocketOptions.builder()
                    .connectTimeout(Duration.ofMillis(100))  // 连接超时
                    .keepAlive(true)
                    .build())
                .build())
            .clientResources(DefaultClientResources.builder()
                .ioThreadPoolSize(4)     // IO线程池大小
                .computationThreadPoolSize(4)  // 计算线程池大小
                .build())
            .build();
        
        RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration();
        serverConfig.setHostName("localhost");
        serverConfig.setPort(6379);
        
        return new LettuceConnectionFactory(serverConfig, clientConfig);
    }
}

3.4 HTTP客户端调优

配置WebClient高性能连接池:

@Configuration
public class WebClientConfig {
    
    @Bean
    public WebClient webClient() {
        HttpClient httpClient = HttpClient.create()
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
            .option(ChannelOption.SO_KEEPALIVE, true)
            .option(ChannelOption.TCP_NODELAY, true)
            .doOnConnected(conn -> 
                conn.addHandlerLast(new ReadTimeoutHandler(10))
                    .addHandlerLast(new WriteTimeoutHandler(10)))
            .responseTimeout(Duration.ofSeconds(5))
            .compress(true)
            .wiretap(true)  // 开发环境调试使用,生产环境应关闭
            .keepAlive(true)
            .poolResources(ConnectionProvider.builder("custom")
                .maxConnections(500)
                .pendingAcquireTimeout(Duration.ofMillis(5000))
                .pendingAcquireMaxCount(1000)
                .maxIdleTime(Duration.ofMillis(8000))
                .build());
        
        return WebClient.builder()
            .clientConnector(new ReactorClientHttpConnector(httpClient))
            .codecs(configurer -> 
                configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
            .build();
    }
}

4. 混合架构方法

不是所有的端点都需要改为响应式的。下面是混合架构的详细实现:

4.1 定义混合架构路由

使用Spring的路由器函数:

@Configuration
public class RouterConfig {
    
    // 高流量端点使用响应式处理
    @Bean
    public RouterFunction<ServerResponse> highTrafficRoutes(
            ReactiveProductHandler productHandler) {
        
        return RouterFunctions
            .route(GET("/api/products").and(accept(APPLICATION_JSON)), 
                productHandler::getAllProducts)
            .andRoute(GET("/api/products/{id}").and(accept(APPLICATION_JSON)), 
                productHandler::getProduct)
            .andRoute(GET("/api/products/category/{category}").and(accept(APPLICATION_JSON)), 
                productHandler::getProductsByCategory);
    }
    
    // 低流量的管理端点保留传统MVC
    @Bean
    public WebMvcConfigurer mvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/admin").setViewName("admin");
                registry.addViewController("/dashboard").setViewName("dashboard");
            }
        };
    }
}

4.2 响应式处理器实现

@Component
public class ReactiveProductHandler {
    
    private final ReactiveProductService productService;
    
    public ReactiveProductHandler(ReactiveProductService productService) {
        this.productService = productService;
    }
    
    public Mono<ServerResponse> getProduct(ServerRequest request) {
        Long productId = Long.valueOf(request.pathVariable("id"));
        
        return productService.getProductById(productId)
            .flatMap(product -> 
                ServerResponse.ok()
                    .contentType(APPLICATION_JSON)
                    .bodyValue(product))
            .switchIfEmpty(ServerResponse.notFound().build());
    }
    
    public Mono<ServerResponse> getAllProducts(ServerRequest request) {
        return productService.getAllProducts()
            .collectList()
            .flatMap(products -> 
                ServerResponse.ok()
                    .contentType(APPLICATION_JSON)
                    .bodyValue(products))
            .switchIfEmpty(ServerResponse.notFound().build());
    }
    
    public Mono<ServerResponse> getProductsByCategory(ServerRequest request) {
        String category = request.pathVariable("category");
        
        return productService.getProductsByCategory(category)
            .collectList()
            .flatMap(products -> 
                ServerResponse.ok()
                    .contentType(APPLICATION_JSON)
                    .bodyValue(products))
            .switchIfEmpty(ServerResponse.notFound().build());
    }
}

4.3 实现逐步迁移策略

创建适配器以支持新旧代码互操作:

@Component
public class ProductServiceAdapter {
    
    private final ReactiveProductService reactiveService;
    private final LegacyProductService legacyService;
    
    @Autowired
    public ProductServiceAdapter(
            ReactiveProductService reactiveService, 
            LegacyProductService legacyService) {
        this.reactiveService = reactiveService;
        this.legacyService = legacyService;
    }
    
    // 将响应式服务适配到传统服务
    public Product getProductSync(Long id) {
        return reactiveService.getProductById(id).block();
    }
    
    // 将传统服务适配到响应式服务
    public Mono<Product> getProductReactive(Long id) {
        return Mono.fromCallable(() -> legacyService.getProductById(id))
            .subscribeOn(Schedulers.boundedElastic());
    }
    
    // 批量操作适配
    public List<Product> getAllProductsSync() {
        return reactiveService.getAllProducts().collectList().block();
    }
    
    public Flux<Product> getAllProductsReactive() {
        return Flux.defer(() -> Flux.fromIterable(legacyService.getAllProducts()))
            .subscribeOn(Schedulers.boundedElastic());
    }
}

5. 水平扩展与Kubernetes

在优化应用程序之后,可以通过Kubernetes进行智能水平扩展。以下是详细的配置和实现:

5.1 创建Dockerfile

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY target/reactive-product-service-0.0.1-SNAPSHOT.jar app.jar

# 设置JVM参数
ENV JAVA_OPTS="-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UseStringDeduplication -Xms1g -Xmx1g -XX:+AlwaysPreTouch"

EXPOSE 8080

# 健康检查
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl -f http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

5.2 创建Kubernetes部署配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-service
  namespace: ecommerce
spec:
  replicas: 3
  selector:
    matchLabels:
      app: product-service
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: product-service
    spec:
      containers:
      - name: product-service
        image: my-registry/product-service:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: "500m"
            memory: "1Gi"
          limits:
            cpu: "1000m"
            memory: "2Gi"
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 20
          periodSeconds: 10
          timeoutSeconds: 2
          failureThreshold: 3
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 20
          timeoutSeconds: 5
          failureThreshold: 3
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: SERVER_PORT
          value: "8080"
        - name: JAVA_OPTS
          value: "-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UseStringDeduplication -Xms1g -Xmx1g -XX:+AlwaysPreTouch"

5.3 创建服务和入口配置

apiVersion: v1
kind: Service
metadata:
  name: product-service
  namespace: ecommerce
spec:
  selector:
    app: product-service
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: product-service-ingress
  namespace: ecommerce
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /api/products
        pathType: Prefix
        backend:
          service:
            name: product-service
            port:
              number: 80

5.4 配置自动扩缩容

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: product-service-hpa
  namespace: ecommerce
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: product-service
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 20
        periodSeconds: 60

5.5 实现优雅降级机制

在应用程序中添加断路器模式:

<!-- 添加Resilience4j依赖 -->
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot2</artifactId>
    <version>1.7.1</version>
</dependency>
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-reactor</artifactId>
    <version>1.7.1</version>
</dependency>

配置断路器:

@Configuration
public class ResilienceConfig {
    
    @Bean
    public CircuitBreakerRegistry circuitBreakerRegistry() {
        CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
            .failureRateThreshold(50)
            .slowCallRateThreshold(50)
            .slowCallDurationThreshold(Duration.ofSeconds(1))
            .permittedNumberOfCallsInHalfOpenState(10)
            .minimumNumberOfCalls(20)
            .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.

参考

https://medium.com/javarevisited/how-i-optimized-a-spring-boot-application-to-handle-1m-requests-second-0cbb2f2823ed