2.Spring MVC与WebFlux响应式编程
目录
一、Spring MVC核心机制与工作原理
• 请求处理流程:DispatcherServlet分发机制、HandlerMapping与HandlerAdapter • 核心组件:ViewResolver、ModelAndView、拦截器(Interceptor) • 注解驱动开发:@Controller、@RequestMapping、@RequestBody/@ResponseBody • RESTful支持:@RestController、@PathVariable、@RequestParam • 异常处理:@ControllerAdvice、@ExceptionHandler、全局异常响应
二、WebFlux响应式编程模型
• 响应式核心概念:Reactive Streams规范、背压(Backpressure)机制 • WebFlux vs MVC:非阻塞IO、事件驱动模型、适用场景对比 • 核心组件:RouterFunction、HandlerFunction、WebFilter • 响应式类型:Mono与Flux操作符(map、flatMap、zip) • 响应式数据访问:R2DBC(关系型数据库)、Reactive MongoDB
三、同步与异步处理对比
• 阻塞式处理(MVC):Servlet线程模型、Tomcat线程池配置 • 非阻塞式处理(WebFlux):EventLoop线程模型、Netty性能优势 • 性能压测对比:1000并发下MVC(Tomcat) vs WebFlux(Netty)吞吐量 • 混合应用场景:MVC同步接口与WebFlux异步接口共存策略
四、实战:构建混合应用(MVC+WebFlux)
• 项目架构设计:Spring Boot多模块配置(MVC模块 + WebFlux模块) • 接口兼容性:统一返回格式(JSON)、全局跨域配置 • 异步接口开发:基于WebFlux的文件上传/下载、SSE(Server-Sent Events)实时推送 • 灰度发布策略:通过网关(Spring Cloud Gateway)动态路由流量
五、性能优化与生产调优
• MVC优化:Tomcat线程池参数(maxThreads、acceptCount)、静态资源缓存 • WebFlux优化:Netty事件循环组配置、响应式超时控制 • 内存泄漏排查:堆内存分析(MAT工具)、阻塞操作检测(BlockHound) • 监控告警:Micrometer集成Prometheus、WebFlux链路追踪(Sleuth + Zipkin)
六、常见问题与面试题精选
• 高频面试题: • Spring MVC如何处理HTTP请求?DispatcherServlet的作用是什么? • WebFlux的背压机制如何解决数据消费速度不匹配问题? • 为什么WebFlux默认使用Netty而不是Tomcat? • 实战场景题: • 设计一个支持10万并发的实时股票报价接口(WebFlux + SSE)。 • 优化一个Spring MVC接口从200ms延迟降低到50ms以下。 • 陷阱题: • 在WebFlux中调用阻塞代码(如JDBC)会导致什么问题?如何解决? • 为什么WebFlux的Mono返回类型不能直接序列化为XML?
一、Spring MVC核心机制与工作原理
1. 请求处理全流程剖析
Spring MVC的请求处理流程围绕DispatcherServlet展开,其核心流程如下:
-  HTTP请求接收: DispatcherServlet作为前端控制器,接收所有HTTP请求。
-  处理器映射(HandlerMapping): • 根据请求URL匹配对应的控制器方法(如 @RequestMapping定义的路径)。 • 支持多种匹配策略(路径通配符、正则表达式)。@GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { ... }
-  处理器适配(HandlerAdapter): • 调用目标控制器方法,处理参数绑定(如 @RequestBody解析JSON)。 • 支持多种参数类型(HttpServletRequest、Model、自定义POJO)。
-  视图解析(ViewResolver): • 根据逻辑视图名(如 return "userList";)解析为物理视图(如userList.jsp)。 • 支持模板引擎(Thymeleaf、FreeMarker)。
2. 核心组件详解
2.1 ViewResolver与模板渲染
• 视图解析流程:
// 配置Thymeleaf视图解析器  
@Bean  
public ThymeleafViewResolver viewResolver() {  ThymeleafViewResolver resolver = new ThymeleafViewResolver();  resolver.setTemplateEngine(templateEngine());  return resolver;  
}   
• 动态数据传递:通过Model对象传递数据到视图。
@GetMapping("/profile")  
public String profile(Model model) {  model.addAttribute("user", userService.getCurrentUser());  return "profile";  
}   
2.2 拦截器(Interceptor)实战
• 自定义拦截器:实现HandlerInterceptor接口,完成日志、权限等操作。
public class AuthInterceptor implements HandlerInterceptor {  @Override  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {  if (!checkToken(request.getHeader("token"))) {  response.sendError(401, "Unauthorized");  return false;  }  return true;  }  
}   
• 配置拦截路径:
@Configuration  
public class WebConfig implements WebMvcConfigurer {  @Override  public void addInterceptors(InterceptorRegistry registry) {  registry.addInterceptor(new AuthInterceptor())  .addPathPatterns("/api/**");  }  
}   
3. 注解驱动开发
3.1 控制器层注解
• @Controller vs @RestController: • @Controller:用于传统MVC模式,配合视图解析器返回HTML页面。 • @RestController:用于RESTful API,所有方法默认添加@ResponseBody,返回JSON/XML数据。
3.2 请求映射注解
• 多条件匹配:
@RequestMapping(  value = "/search",  method = RequestMethod.GET,  params = "keyword",  headers = "Content-Type=application/json"  
)  
public List<Product> searchProducts() { ... }   
3.3 参数绑定注解
• @RequestBody与HttpMessageConverter: • JSON反序列化流程: 1. 请求头Content-Type: application/json触发MappingJackson2HttpMessageConverter。 2. 将请求体JSON转换为Java对象。
@PostMapping("/users")  
public ResponseEntity<User> createUser(@RequestBody User user) {  User savedUser = userService.save(user);  return ResponseEntity.created(URI.create("/users/" + savedUser.getId())).body(savedUser);  
}   
4. RESTful接口设计规范
4.1 资源操作语义化
• HTTP方法对应CRUD:
| HTTP方法 | 操作 | 示例 | 
|---|---|---|
| GET | 查询资源 | GET /users/123 | 
| POST | 创建资源 | POST /users | 
| PUT | 全量更新 | PUT /users/123 | 
| PATCH | 部分更新 | PATCH /users/123 | 
| DELETE | 删除资源 | DELETE /users/123 | 
4.2 HATEOAS实现
• Spring HATEOAS集成:
@GetMapping("/users/{id}")  
public EntityModel<User> getUser(@PathVariable Long id) {  User user = userService.findById(id);  return EntityModel.of(user,  linkTo(methodOn(UserController.class).getUser(id)).withSelfRel(),  linkTo(methodOn(UserController.class).getUserOrders(id)).withRel("orders")  );  
}   
• 响应示例:
{  "id": 123,  "name": "John",  "_links": {  "self": { "href": "http://localhost:8080/users/123" },  "orders": { "href": "http://localhost:8080/users/123/orders" }  }  
}   
5. 全局异常处理
5.1 统一异常响应
• 自定义异常类:
public class ResourceNotFoundException extends RuntimeException {  public ResourceNotFoundException(String message) {  super(message);  }  
}   
• 全局异常处理器:
@ControllerAdvice  
public class GlobalExceptionHandler {  @ExceptionHandler(ResourceNotFoundException.class)  public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {  ErrorResponse error = new ErrorResponse(404, ex.getMessage());  return ResponseEntity.status(404).body(error);  }  
}   
• 错误响应体:
{  "code": 404,  "message": "User not found with id 123"  
}   
总结 本章深入解析了Spring MVC的核心机制,从请求处理流程到RESTful接口设计,覆盖了控制器开发、参数绑定、异常处理等关键内容。后续章节将对比WebFlux响应式编程模型,帮助开发者根据业务场景选择最佳技术方案。
二、WebFlux响应式编程模型
1. 响应式核心概念
1.1 Reactive Streams规范
Reactive Streams是响应式编程的标准化规范,定义了以下核心接口: • Publisher<T>:数据生产者,发布数据流。 • Subscriber<T>:数据消费者,订阅并处理数据。 • Subscription:订阅关系,控制数据请求(如request(n))。 • Processor<T, R>:同时充当生产者和消费者的中间处理节点。
代码示例(简单Publisher):
Flux<Integer> flux = Flux.range(1, 10)  .delayElements(Duration.ofMillis(100));  
flux.subscribe(  value -> System.out.println("Received: " + value),  error -> System.err.println("Error: " + error),  () -> System.out.println("Completed")  
);   
1.2 背压(Backpressure)机制
• 问题场景:生产者速度 > 消费者速度,导致内存溢出。 • 解决方案:通过Subscription动态控制数据流速。
Flux.range(1, 1000)  .onBackpressureBuffer(10)  // 缓冲区大小为10,超出后丢弃旧数据  .subscribe(new BaseSubscriber<Integer>() {  @Override  protected void hookOnSubscribe(Subscription subscription) {  request(5);  // 初始请求5个元素  }  @Override  protected void hookOnNext(Integer value) {  process(value);  request(1);  // 每处理完1个元素,再请求1个  }  });   
2. WebFlux vs MVC:模型对比与适用场景
2.1 非阻塞IO与事件驱动
• MVC(阻塞式): • 每个请求占用一个线程(Tomcat线程池默认200线程)。 • 高并发时线程资源耗尽,导致性能瓶颈。 • WebFlux(非阻塞): • 基于事件循环(EventLoop),单线程处理数千连接。 • 适用I/O密集型场景(如微服务网关、实时推送)。
2.2 性能对比
| 指标 | Spring MVC(Tomcat) | WebFlux(Netty) | 
|---|---|---|
| 吞吐量(req/s) | 5k | 15k | 
| 内存占用 | 高(每个线程1MB) | 低(共享线程池) | 
| 适用场景 | CRUD、同步逻辑 | 高并发、实时流 | 
2.3 混合应用场景
• 用例:电商系统同时提供管理后台(MVC)和实时订单推送(WebFlux)。 • 配置示例:
# application.yml server: port: 8080 servlet: context-path: /mvc spring: webflux: base-path: /reactive
3. 核心组件详解
3.1 函数式端点(RouterFunction & HandlerFunction)
• 路由定义:使用RouterFunctions.route()组合请求谓词和处理器。
@Bean  
public RouterFunction<ServerResponse> userRoutes() {  return route()  .GET("/users/{id}", this::getUser)  .POST("/users", this::createUser)  .build();  
}  
private Mono<ServerResponse> getUser(ServerRequest request) {  Long id = Long.parseLong(request.pathVariable("id"));  return ServerResponse.ok().body(userService.findById(id), User.class);  
}   
3.2 响应式过滤器(WebFilter)
• 日志记录示例:
@Component  
public class LoggingWebFilter implements WebFilter {  @Override  public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {  long startTime = System.currentTimeMillis();  return chain.filter(exchange)  .doOnTerminate(() -> {  long duration = System.currentTimeMillis() - startTime;  System.out.println(  exchange.getRequest().getURI() + " - " + duration + "ms"  );  });  }  
}   
4. 响应式类型与操作符
4.1 Mono与Flux核心操作
| 操作符 | 用途 | 示例 | 
|---|---|---|
| map | 同步转换元素 | Flux.just(1,2).map(i -> i*2) | 
| flatMap | 异步转换(返回Publisher) | Flux.just(1,2).flatMap(i -> Mono.just(i*2)) | 
| zip | 合并多个流(按元素顺序配对) | Mono.zip(monoA, monoB, (a,b) -> a + b) | 
| merge | 合并多个流(按元素到达顺序) | Flux.merge(fluxA, fluxB) | 
代码示例(实时数据流处理):
Flux<StockPrice> prices = WebClient.create()  .get()  .uri("http://stock-service/prices")  .retrieve()  .bodyToFlux(StockPrice.class)  .filter(price -> price.getValue() > 100)  .bufferTimeout(10, Duration.ofSeconds(1))  .flatMap(batch -> saveBatchToDB(batch));   
5. 响应式数据访问
5.1 R2DBC(关系型数据库)
• 核心依赖:
<dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-postgresql</artifactId> </dependency>
• CRUD示例:
public Flux<User> findAll() {  return databaseClient.sql("SELECT * FROM users")  .map(row -> new User(row.get("id", Long.class), row.get("name", String.class)))  .all();  
}   
5.2 Reactive MongoDB
• 查询与订阅:
public Flux<User> streamUsers() {  return mongoTemplate.changeStream(User.class)  .watchCollection("users")  .listen()  .map(ChangeStreamEvent::getBody);  
}   
总结 WebFlux通过非阻塞IO和响应式编程模型,为高并发场景提供了高效的解决方案。结合R2DBC和Reactive MongoDB,开发者可以构建端到端的响应式应用。下一章将深入探讨同步与异步处理的性能差异及混合应用架构设计。
三、同步与异步处理对比
1. 阻塞式处理(Spring MVC)
1.1 Servlet线程模型与Tomcat配置
• 线程模型: • 每个HTTP请求占用一个独立线程(Tomcat默认线程池大小为200)。 • 线程从接收请求到返回响应的全流程中,若遇到阻塞操作(如数据库查询、远程调用),线程会被挂起,直到操作完成。 • 配置优化:
# application.yml server: tomcat: max-threads: 200 # 最大工作线程数 accept-count: 100 # 等待队列容量 min-spare-threads: 10 # 最小空闲线程数
• 性能瓶颈: • 当并发请求超过max-threads + accept-count时(如300并发),Tomcat直接拒绝请求(返回503)。 • 长耗时操作(如文件导出)可能导致线程池耗尽,影响其他请求。
1.2 典型同步接口示例
@RestController  
public class BlockingController {  @GetMapping("/blocking/users/{id}")  public User getUser(@PathVariable Long id) {  // 模拟耗时1秒的数据库查询(阻塞线程)  try { Thread.sleep(1000); } catch (InterruptedException e) {}  return new User(id, "User" + id);  }  
}   
2. 非阻塞式处理(WebFlux)
2.1 EventLoop线程模型与Netty优势
• EventLoop机制: • 单线程(EventLoop)通过事件驱动处理多个连接(如1000并发)。 • 所有I/O操作(如网络请求、数据库调用)均为非阻塞,通过回调通知结果。 • Netty核心参数:
# application.yml spring: webflux: server: max-in-memory-size: 10MB # 请求体内存缓冲大小 thread-pool: max-threads: 4 # 事件循环线程数(通常设为CPU核数)
• 性能优势: • 高并发下内存占用稳定(无线程上下文切换开销)。 • 适用于实时流处理(如股票行情推送、物联网设备数据采集)。
2.2 典型异步接口示例
@RestController  
public class ReactiveController {  @GetMapping("/reactive/users/{id}")  public Mono<User> getUser(@PathVariable Long id) {  // 模拟异步数据库查询(不阻塞线程)  return Mono.delay(Duration.ofSeconds(1))  .map(delay -> new User(id, "User" + id));  }  
}   
3. 性能压测对比(MVC vs WebFlux)
3.1 压测环境与参数
• 工具:Apache JMeter(1000并发,持续10秒)。 • 接口逻辑:模拟1秒延迟的查询操作。 • 服务器配置:4核CPU,8GB内存,Spring Boot 3.0。
3.2 压测结果
| 指标 | Spring MVC(Tomcat) | WebFlux(Netty) | 
|---|---|---|
| 吞吐量(req/s) | 200 | 950 | 
| 平均响应时间 | 1000ms | 1050ms | 
| 最大内存占用 | 1.2GB | 300MB | 
| 线程占用数 | 200 | 4 | 
结论: • WebFlux在高并发场景下吞吐量提升近5倍,内存占用降低75%。 • MVC的响应时间更稳定,但受限于线程池容量。
4. 混合应用场景与共存策略
4.1 技术选型原则
• 使用MVC的场景: • 依赖阻塞式组件(如JDBC、JPA)。 • 简单CRUD接口,无需高并发(如管理后台)。 • 使用WebFlux的场景: • 高并发、低延迟需求(如API网关、实时推送)。 • 依赖非阻塞数据源(如R2DBC、Reactive MongoDB)。
4.2 混合架构实现
• 项目配置:
// build.gradle  
dependencies {  implementation 'org.springframework.boot:spring-boot-starter-web'      // MVC  implementation 'org.springframework.boot:spring-boot-starter-webflux'  // WebFlux  
}   
• 路由策略:通过@Order控制处理器优先级。
@Configuration  
public class WebConfig implements WebFluxConfigurer {  @Bean  @Order(-1)  // WebFlux优先处理  public RouterFunction<ServerResponse> reactiveRoutes() {  return route()  .GET("/reactive/**", request -> ServerResponse.ok().build())  .build();  }  
}   
4.3 线程池隔离
• MVC线程池:Tomcat默认线程池处理同步请求。 • WebFlux线程池:Netty EventLoop处理异步请求。 • 关键配置:
spring: task: execution: pool: core-size: 10 # 异步任务线程池(避免阻塞EventLoop)
总结
• 同步模型(MVC):适合简单业务、阻塞式数据源,开发门槛低。 • 异步模型(WebFlux):适合高并发、实时流,但需重构为全响应式链路。 • 混合架构:通过路由和线程池隔离,平衡开发效率与性能需求。
生产建议: • 核心服务(如支付回调)使用WebFlux保证高可用。 • 复杂事务操作(如库存扣减)优先选择MVC+JDBC。 • 使用BlockHound检测阻塞调用,确保响应式代码纯净性。
// BlockHound配置(检测阻塞操作)  
public class BlockHoundConfig {  @PostConstruct  public void init() {  BlockHound.builder()  .allowBlockingCallsInside("com.example.MyService", "safeBlockingMethod")  .install();  }  
}   
四、实战:构建混合应用(MVC+WebFlux)
1. 项目架构设计
1.1 多模块工程配置
• 模块划分: • mvc-module:处理同步请求(依赖spring-boot-starter-web)。 • webflux-module:处理异步请求(依赖spring-boot-starter-webflux)。 • common-module:共享DTO、工具类、异常处理。
• Maven/Gradle配置:
// build.gradle(根项目)  
subprojects {  apply plugin: 'org.springframework.boot'  dependencies {  implementation project(':common-module')  }  
}  
// mvc-module/build.gradle  
dependencies {  implementation 'org.springframework.boot:spring-boot-starter-web'  
}  
// webflux-module/build.gradle  
dependencies {  implementation 'org.springframework.boot:spring-boot-starter-webflux'  
}   
• 启动类隔离:
// MVC模块启动类  
@SpringBootApplication  
@EnableAutoConfiguration(exclude = {ReactiveWebServerFactoryAutoConfiguration.class})  
public class MvcApplication { ... }  // WebFlux模块启动类  
@SpringBootApplication  
@EnableAutoConfiguration(exclude = {ServletWebServerFactoryAutoConfiguration.class})  
public class WebfluxApplication { ... }   
2. 接口兼容性与统一规范
2.1 统一JSON响应格式
• 全局响应封装(common-module中定义):
public class ApiResponse<T> {  private int code;  private String message;  private T data;  // Getter/Setter  
}   
• MVC统一返回(@ControllerAdvice):
@ControllerAdvice  
public class MvcResponseWrapper implements ResponseBodyAdvice<Object> {  @Override  public boolean supports(MethodParameter returnType, Class converterType) {  return !returnType.getGenericParameterType().equals(ApiResponse.class);  }  @Override  public Object beforeBodyWrite(Object body, MethodParameter returnType,  MediaType selectedContentType, Class selectedConverterType,  ServerHttpRequest request, ServerHttpResponse response) {  return new ApiResponse<>(200, "Success", body);  }  
}   
• WebFlux统一返回(全局过滤器):
@Component  
public class WebfluxResponseFilter implements WebFilter {  @Override  public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {  return chain.filter(exchange)  .then(Mono.defer(() -> {  ServerHttpResponse response = exchange.getResponse();  if (response.getStatusCode() == HttpStatus.OK) {  Object body = response.getBody();  return response.writeWith(Mono.just(  response.bufferFactory().wrap(  new ApiResponse<>(200, "Success", body).toString().getBytes()  )  ));  }  return Mono.empty();  }));  }  
}   
2.2 全局跨域配置
• MVC跨域配置:
@Configuration  
public class MvcCorsConfig implements WebMvcConfigurer {  @Override  public void addCorsMappings(CorsRegistry registry) {  registry.addMapping("/**")  .allowedOrigins("*")  .allowedMethods("GET", "POST");  }  
}   
• WebFlux跨域配置:
@Configuration  
public class WebfluxCorsConfig {  @Bean  public CorsWebFilter corsFilter() {  CorsConfiguration config = new CorsConfiguration();  config.addAllowedOrigin("*");  config.addAllowedMethod("*");  UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  source.registerCorsConfiguration("/**", config);  return new CorsWebFilter(source);  }  
}   
3. 异步接口开发实战
3.1 文件上传与下载
• WebFlux文件上传:
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)  
public Mono<String> uploadFile(@RequestPart("file") FilePart filePart) {  Path path = Paths.get("/tmp/" + filePart.filename());  return filePart.transferTo(path).thenReturn("Upload success");  
}   
• WebFlux文件下载:
@GetMapping("/download/{filename}")  
public Mono<Resource> downloadFile(@PathVariable String filename) {  return Mono.fromSupplier(() -> new FileSystemResource("/tmp/" + filename));  
}   
3.2 SSE实时推送
• 服务端实现:
@GetMapping(value = "/stream/prices", produces = MediaType.TEXT_EVENT_STREAM_VALUE)  
public Flux<StockPrice> streamPrices() {  return Flux.interval(Duration.ofSeconds(1))  .map(sequence -> new StockPrice("AAPL", 150 + sequence * 0.5));  
}   
• 客户端订阅:
const eventSource = new EventSource('/stream/prices');  
eventSource.onmessage = (e) => console.log(JSON.parse(e.data));   
4. 灰度发布与动态路由
4.1 Spring Cloud Gateway配置
• 路由规则(按Header分流):
spring: cloud: gateway: routes: - id: mvc-route uri: http://localhost:8081 predicates: - Header=X-Gray, v1 - id: webflux-route uri: http://localhost:8082 predicates: - Header=X-Gray, v2
4.2 金丝雀发布策略
• 按权重分流:
spring: cloud: gateway: routes: - id: canary-route uri: lb://my-service predicates: - Path=/api/** filters: - name: Weight args: group: canary weight: v1, 90 weight: v2, 10
5. 混合应用监控与调优
• 线程池隔离配置:
# WebFlux线程池(避免阻塞EventLoop) spring: task: execution: pool: core-size: 10 max-size: 20
• 监控集成:
management:  endpoints:  web:  exposure:  include: health,metrics,threaddump  metrics:  tags:  application: ${spring.application.name}   
总结
通过混合架构设计,开发者既能保留MVC的简单易用性,又能利用WebFlux处理高并发场景。关键点包括:
-  模块隔离:通过多模块工程避免依赖冲突。 
-  统一规范:全局处理响应格式与跨域配置。 
-  动态路由:结合Spring Cloud Gateway实现灰度发布。 
-  监控保障:线程池隔离与全链路监控确保稳定性。 
适用场景: • 核心交易系统(MVC保证事务一致性)。 • 实时通知服务(WebFlux支持高并发推送)。 • 逐步迁移旧系统(通过灰度策略平滑过渡)。
五、性能优化与生产调优
1. Spring MVC性能优化
1.1 Tomcat线程池参数调优
• 核心参数:
server: tomcat: max-threads: 200 # 最大工作线程数(建议值:CPU核数 * 200) accept-count: 100 # 等待队列容量(超出后拒绝请求) min-spare-threads: 20 # 最小空闲线程数(快速响应突发流量)
• 调优原则: • CPU密集型场景:max-threads设为CPU核数 * 1.5。 • I/O密集型场景:max-threads可适当增大(如200~400)。
1.2 静态资源缓存
• HTTP缓存头配置:
@Configuration  
public class MvcCacheConfig implements WebMvcConfigurer {  @Override  public void addResourceHandlers(ResourceHandlerRegistry registry) {  registry.addResourceHandler("/static/**")  .addResourceLocations("classpath:/static/")  .setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS));  }  
}   
• Nginx缓存加速:
location /static/ {  expires 30d;  add_header Cache-Control "public";  
}   
2. WebFlux性能优化
2.1 Netty事件循环组配置
• 线程模型优化:
# application.yml spring: webflux: server: # EventLoop线程数(默认:CPU核数 * 2) thread-pool: max-threads: 8
• 参数调优: • Linux系统:启用Epoll传输(减少线程切换开销)。 java @Bean public NettyReactiveWebServerFactory nettyFactory() { return new NettyReactiveWebServerFactory( builder -> builder.option(ChannelOption.SO_BACKLOG, 1024) .childOption(ChannelOption.TCP_NODELAY, true) ); }
2.2 响应式超时控制
• 全局超时配置:
@Bean  
public WebClient webClient() {  return WebClient.builder()  .clientConnector(new ReactorClientHttpConnector(  HttpClient.create()  .responseTimeout(Duration.ofSeconds(5))  ))  .build();  
}   
• 接口级超时:
@GetMapping("/reactive/data")  
public Mono<Data> getData() {  return externalService.fetchData()  .timeout(Duration.ofSeconds(3))  .onErrorResume(e -> Mono.just(new Data("fallback")));  
}   
3. 内存泄漏排查与阻塞检测
3.1 堆内存分析(MAT工具)
• 生成堆转储文件:
# 通过jmap生成 jmap -dump:format=b,file=heapdump.hprof <pid> # 或JVM参数触发OOM时自动生成 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof
• MAT分析步骤:
-  打开 heapdump.hprof,查看“Dominator Tree”找到占用内存最大的对象。
-  检查可疑对象的GC Root路径(如未关闭的数据库连接、静态集合缓存)。 
3.2 阻塞操作检测(BlockHound)
• 集成BlockHound:
public class BlockHoundConfig {  @PostConstruct  public void init() {  BlockHound.builder()  .allowBlockingCallsInside("com.example.Class", "methodName")  .install();  }  
}   
• 检测结果示例:
Blocking call! java.lang.Thread.sleep at com.example.Service.blockingMethod(Service.java:20)
4. 监控告警与链路追踪
4.1 Micrometer集成Prometheus
• 配置依赖:
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>
• 暴露指标端点:
management:  endpoints:  web:  exposure:  include: health, prometheus  metrics:  tags:  application: ${spring.application.name}   
• 自定义指标:
@Bean  
public MeterRegistryCustomizer<PrometheusMeterRegistry> metrics() {  return registry -> registry.config().commonTags("region", "us-east");  
}   
4.2 WebFlux链路追踪(Sleuth + Zipkin)
• 配置依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </dependency>
• Zipkin服务端配置:
spring: zipkin: base-url: http://zipkin-server:9411 sleuth: sampler: probability: 1.0 # 采样率(生产环境设为0.1)
• 追踪效果:
{  "traceId": "3e6f3b7e6d6d6d6d",  "spanId": "6d6d6d6d6d6d6d6d",  "parentSpanId": null,  "name": "GET /reactive/data",  "tags": {  "http.method": "GET",  "http.status_code": "200"  }  
}   
总结
• MVC调优重点:线程池容量、静态资源缓存、避免内存泄漏。 • WebFlux调优重点:非阻塞线程模型、响应式超时、全链路监控。 • 生产保障:通过BlockHound确保响应式代码纯净性,结合Prometheus+Zipkin实现可观测性。
推荐工具链: • 监控:Prometheus(指标) + Grafana(看板) + ELK(日志)。 • 压测:JMeter(全链路压测) + Gatling(高并发模拟)。 • 调优:Arthas(动态诊断) + VisualVM(JVM分析)。
# Arthas快速诊断命令示例 $ ./arthas-boot.jar arthas> dashboard # 实时监控线程/内存 arthas> thread -n 5 # 查看最忙线程
六、常见问题与面试题精选
高频面试题
1. Spring MVC如何处理HTTP请求?DispatcherServlet的作用是什么?
答案:
-  请求处理流程: • DispatcherServlet作为前端控制器,接收所有HTTP请求。 • 通过 HandlerMapping解析请求URL,找到对应的控制器方法(如@GetMapping)。 •HandlerAdapter调用控制器方法,处理参数绑定(如@RequestBody)。 • 结果通过ViewResolver解析视图(如返回JSON或HTML页面)。
-  DispatcherServlet的核心作用: • 统一入口:集中管理请求分发,解耦请求处理与业务逻辑。 • 组件协调:集成 HandlerMapping、ViewResolver等组件,实现松耦合架构。 • 扩展支持:支持拦截器(Interceptor)、异常处理(@ControllerAdvice)。
代码示例:
@RestController  
public class UserController {  @GetMapping("/users/{id}")  public User getUser(@PathVariable Long id) {  return userService.findById(id);  }  
}   
2. WebFlux的背压机制如何解决数据消费速度不匹配问题?
答案:
-  背压核心原理: • 消费者通过 Subscription动态控制数据流速(如request(n)请求n个元素)。 • 生产者根据消费者的处理能力调整数据发送速率。
-  WebFlux实现方式: • Flux缓冲策略:使用onBackpressureBuffer缓存溢出数据。 • 流量控制:limitRate()限制生产者速率。
代码示例:
Flux.range(1, 1000)  .onBackpressureBuffer(10)  // 缓冲区容量为10  .subscribe(  value -> process(value),  error -> log.error("Error", error),  () -> log.info("Completed"),  subscription -> subscription.request(5)  // 初始请求5个元素  );   
3. 为什么WebFlux默认使用Netty而不是Tomcat?
答案:
-  架构差异: • Tomcat:基于Servlet API,每个请求占用一个线程(阻塞式)。 • Netty:基于事件循环(EventLoop),单线程处理多个连接(非阻塞)。 
-  性能优势: • 高并发:Netty的EventLoop模型支持数万并发连接。 • 低延迟:非阻塞I/O减少线程切换开销。 
适用场景: • Tomcat:传统同步逻辑(如JDBC事务)。 • Netty:实时推送、高并发接口(如API网关)。
实战场景题
1. 设计一个支持10万并发的实时股票报价接口(WebFlux + SSE)
实现方案:
-  技术选型: • WebFlux:非阻塞处理高并发连接。 • SSE(Server-Sent Events):通过长连接推送实时数据。 
-  核心代码: @GetMapping(value = "/stocks", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<StockPrice> streamStockPrices() { return Flux.interval(Duration.ofMillis(100)) .map(seq -> new StockPrice("AAPL", 150 + seq * 0.1)); }
-  优化策略: • 背压控制: onBackpressureDrop()丢弃无法处理的实时数据。 • 集群部署:通过Kafka分发数据到多个实例。
2. 优化一个Spring MVC接口从200ms延迟降低到50ms以下
优化步骤:
-  性能分析: • 使用 jstack或Arthas定位线程阻塞点(如慢SQL、外部API调用)。
-  优化手段: • 缓存:Redis缓存查询结果(减少数据库压力)。 • 异步化:将非关键逻辑(如日志记录)改为异步处理。 @Async public void logAccess(Long userId) { // 异步记录访问日志 }• SQL优化:添加索引、避免全表扫描。 
-  效果验证: • 通过JMeter压测确认延迟降低至50ms以下。 
陷阱题
1. 在WebFlux中调用阻塞代码(如JDBC)会导致什么问题?如何解决?
答案: • 问题:阻塞操作(如JDBC)会占用EventLoop线程,导致整个应用吞吐量骤降。 • 解决方案:
-  异步驱动:使用R2DBC(响应式关系数据库驱动)。 
-  线程池隔离:将阻塞操作调度到独立线程池。 
Mono.fromCallable(() -> blockingJdbcCall()) .subscribeOn(Schedulers.boundedElastic()) // 切换到弹性线程池 .subscribe(result -> ...);
2. 为什么WebFlux的Mono返回类型不能直接序列化为XML?
 
答案: • 原因:默认的HttpMessageConverter可能未注册XML的响应式序列化器。 • 解决方案:
-  添加Jackson XML依赖: 
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
-  配置内容协商: 
spring: mvc: contentnegotiation: media-types: xml: application/xml
总结:
• Spring MVC:适合传统同步场景,注重开发效率。 • WebFlux:适合高并发、实时流处理,需严格避免阻塞操作。 • 核心考点:背压机制、线程模型、性能优化、生产问题排查。
