引言
响应式编程正在重塑现代应用架构,从传统的同步阻塞模式转向异步非阻塞的响应式系统。Spring
WebFlux和RSocket为构建高性能、高并发的响应式应用提供了强大的工具集。本文将深入探讨响应式编程的核心概念,并通过实战案例展示如何构建真正的响应式系统。
响应式编程基础
1.1 Reactor核心概念
java
// Reactor基础操作示例
@Component
@Slf4j
public class ReactorFundamentals {
/**
* Flux - 多个元素的异步序列
*/
public Flux<String> createFluxExamples() {
// 1. 从集合创建Flux
Flux<String> fromIterable = Flux.fromIterable(Arrays.asList("A", "B", "C"));
// 2. 从数组创建Flux
Flux<String> fromArray = Flux.fromArray(new String[]{"X", "Y", "Z"});
// 3. 使用just创建
Flux<String> justFlux = Flux.just("Hello", "Reactive", "World");
// 4. 使用range创建数值序列
Flux<Integer> numberFlux = Flux.range(1, 10);
// 5. 使用interval创建定时序列
Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(1))
.take(5); // 只取前5个元素
return justFlux;
}
/**
* Mono - 单个元素的异步序列
*/
public Mono<String> createMonoExamples() {
// 1. 创建包含值的Mono
Mono<String> justMono = Mono.just("Single Value");
// 2. 创建空的Mono
Mono<String> emptyMono = Mono.empty();
// 3. 从Optional创建Mono
Mono<String> fromOptional = Mono.justOrEmpty(Optional.of("Optional Value"));
// 4. 从Callable创建Mono
Mono<String> fromCallable = Mono.fromCallable(() -> {
Thread.sleep(100); // 模拟耗时操作
return "From Callable";
});
return justMono;
}
/**
* 转换操作符
*/
public Flux<String> transformationOperators() {
return Flux.range(1, 5)
.map(i -> "Number: " + i) // 同步转换
.filter(s -> !s.contains("3")) // 过滤
.flatMap(s -> Mono.just(s + "!")) // 异步转换
.concatWith(Flux.just("Final Item")) // 连接流
.distinct() // 去重
.take(3) // 取前N个
.skip(1) // 跳过前N个
.doOnNext(item -> log.info("Processing: {}", item)) // 副作用
.doOnComplete(() -> log.info("Stream completed"));
}
/**
* 组合操作符
*/
public Flux<String> combinationOperators() {
Flux<String> first = Flux.just("A", "B", "C");
Flux<String> second = Flux.just("X", "Y", "Z");
// 1. merge - 合并流(交错发射)
Flux<String> merged = Flux.merge(first, second);
// 2. zip - 配对合并
Flux<String> zipped = Flux.zip(first, second,
(f, s) -> f + "-" + s);
// 3. concat - 顺序连接
Flux<String> concatenated = Flux.concat(first, second);
// 4. combineLatest - 组合最新值
Flux<Long> tick1 = Flux.interval(Duration.ofMillis(800));
Flux<Long> tick2 = Flux.interval(Duration.ofMillis(1000));
Flux<String> combined = Flux.combineLatest(tick1, tick2,
(t1, t2) -> t1 + ":" + t2);
return zipped.take(3);
}
/**
* 错误处理操作符
*/
public Flux<String> errorHandlingOperators() {
return Flux.range(1, 5)
.map(i -> {
if (i == 3) {
throw new RuntimeException("Error at " + i);
}
return "Item " + i;
})
.onErrorReturn("Fallback Value") // 返回默认值
.onErrorResume(error -> { // 恢复为另一个流
log.error("Error occurred: {}", error.getMessage());
return Flux.just("Recovery Item 1", "Recovery Item 2");
})
.retry(2) // 重试2次
.doOnError(error -> log.error("Final error: {}", error.getMessage()));
}
/**
* 背压处理
*/
public Flux<Integer> backpressureHandling() {
return Flux.range(1, 1000)
.onBackpressureBuffer(50, // 缓冲区大小
buffer -> log.warn("Buffer overflow: {}", buffer),
BufferOverflowStrategy.DROP_LATEST)
.onBackpressureDrop(dropped ->
log.warn("Dropped due to backpressure: {}", dropped))
.doOnNext(item -> {
// 模拟处理延迟
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
/**
* 调度器使用
*/
public Flux<String> schedulerExamples() {
return Flux.range(1, 10)
.publishOn(Schedulers.parallel()) // 后续操作在并行线程执行
.map(i -> {
log.info("Processing {} on thread: {}", i,
Thread.currentThread().getName());
return "Processed: " + i;
})
.subscribeOn(Schedulers.boundedElastic()) // 订阅在弹性线程池执行
.doOnSubscribe(subscription ->
log.info("Subscribed on thread: {}", Thread.currentThread().getName()));
}
/**
* 热序列 vs 冷序列
*/
public void hotVsColdSequences() {
// 冷序列 - 每个订阅者都会收到完整的数据
Flux<String> coldFlux = Flux.defer(() -> {
log.info("Creating new data stream");
return Flux.just("Cold", "Data", "Stream");
});
// 热序列 - 数据独立于订阅者
ConnectableFlux<String> hotFlux = Flux.interval(Duration.ofSeconds(1))
.map(i -> "Hot Data " + i)
.publish(); // 转换为热序列
hotFlux.connect(); // 开始发射数据
// 第一个订阅者
hotFlux.subscribe(data -> log.info("Subscriber 1: {}", data));
// 2秒后第二个订阅者加入
new Thread(() -> {
try {
Thread.sleep(2000);
hotFlux.subscribe(data -> log.info("Subscriber 2: {}", data));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
1.2 响应式编程模式
java
// 响应式设计模式
@Component
@Slf4j
public class ReactivePatterns {
/**
* 异步流水线模式
*/
public Mono<String> asyncPipeline(String input) {
return Mono.just(input)
.publishOn(Schedulers.parallel())
.map(this::validateInput)
.flatMap(this::processData)
.publishOn(Schedulers.boundedElastic())
.flatMap(this::saveToDatabase)
.publishOn(Schedulers.parallel())
.map(this::formatResponse)
.onErrorResume(this::handleError);
}
private String validateInput(String input) {
if (input == null || input.trim().isEmpty()) {
throw new IllegalArgumentException("Input cannot be empty");
}
return input.trim();
}
private Mono<String> processData(String data) {
return Mono.fromCallable(() -> {
// 模拟耗时处理
Thread.sleep(100);
return data.toUpperCase();
}).subscribeOn(Schedulers.boundedElastic());
}
private Mono<String> saveToDatabase(String data) {
// 模拟数据库操作
return Mono.just("saved:" + data)
.delayElement(Duration.ofMillis(50))
.doOnNext(result -> log.info("Saved to database: {}", result));
}
private String formatResponse(String data) {
return "Response: " + data;
}
private Mono<String> handleError(Throwable error) {
log.error("Pipeline error: {}", error.getMessage());
return Mono.just("Error: " + error.getMessage());
}
/**
* 请求-响应模式
*/
public Mono<UserProfile> requestResponsePattern(Long userId) {
return getUserById(userId)
.flatMap(user -> getProfileByUser(user))
.timeout(Duration.ofSeconds(5))
.retryWhen(Retry.backoff(3, Duration.ofMillis(100)));
}
private Mono<User> getUserById(Long userId) {
return Mono.just(new User(userId, "user" + userId))
.delayElement(Duration.ofMillis(100));
}
private Mono<UserProfile> getProfileByUser(User user) {
return Mono.just(new UserProfile(user, "profile@" + user.getName()))
.delayElement(Duration.ofMillis(150));
}
/**
* 事件总线模式
*/
public static class ReactiveEventBus {
private final Sinks.Many<Event> eventSink = Sinks.many().multicast().onBackpressureBuffer();
private final Flux<Event> eventFlux = eventSink.asFlux().publish().autoConnect();
public void publishEvent(Event event) {
eventSink.tryEmitNext(event);
}
public <T extends Event> Flux<T> subscribe(Class<T> eventType) {
return eventFlux
.filter(eventType::isInstance)
.cast(eventType)
.onBackpressureLatest();
}
}
/**
* 缓存模式
*/
public static class ReactiveCache<K, V> {
private final Map<K, Mono<V>> cache = new ConcurrentHashMap<>();
private final Function<K, Mono<V>> valueLoader;
public ReactiveCache(Function<K, Mono<V>> valueLoader) {
this.valueLoader = valueLoader;
}
public Mono<V> get(K key) {
return cache.computeIfAbsent(key, k ->
valueLoader.apply(k)
.cache(Duration.ofMinutes(10)) // 缓存10分钟
.doOnError(error -> cache.remove(key)) // 错误时移除缓存
);
}
public void evict(K key) {
cache.remove(key);
}
}
/**
* 批量处理模式
*/
public static class BatchProcessor<T> {
private final Sinks.Many<T> sink = Sinks.many().unicast().onBackpressureBuffer();
private final Flux<List<T>> batchedFlux;
public BatchProcessor(int batchSize, Duration windowTimeout) {
this.batchedFlux = sink.asFlux()
.windowTimeout(batchSize, windowTimeout)
.flatMap(window -> window.collectList())
.publish()
.autoConnect();
}
public void addItem(T item) {
sink.tryEmitNext(item);
}
public Flux<List<T>> getBatches() {
return batchedFlux;
}
}
// 领域模型
static class User {
private final Long id;
private final String name;
User(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() { return id; }
public String getName() { return name; }
}
static class UserProfile {
private final User user;
private final String email;
UserProfile(User user, String email) {
this.user = user;
this.email = email;
}
public User getUser() { return user; }
public String getEmail() { return email; }
}
static class Event {
private final String type;
private final Object data;
Event(String type, Object data) {
this.type = type;
this.data = data;
}
public String getType() { return type; }
public Object getData() { return data; }
}
}
Spring WebFlux深度实战
2.1 WebFlux控制器与路由
java
// 响应式REST控制器
@RestController
@RequestMapping("/api/reactive/users")
@Slf4j
public class ReactiveUserController {
private final ReactiveUserService userService;
private final ReactiveEventPublisher eventPublisher;
public ReactiveUserController(ReactiveUserService userService,
ReactiveEventPublisher eventPublisher) {
this.userService = userService;
this.eventPublisher = eventPublisher;
}
/**
* 获取所有用户 - 流式响应
*/
@GetMapping(produces = MediaType.APPLICATION_NDJSON_VALUE)
public Flux<UserDTO> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
return userService.findAllUsers(page, size)
.doOnSubscribe(s -> log.info("开始流式返回用户数据"))
.doOnComplete(() -> log.info("用户数据流完成"))
.doOnError(error -> log.error("用户数据流错误", error));
}
/**
* 根据ID获取用户
*/
@GetMapping("/{id}")
public Mono<ResponseEntity<UserDTO>> getUserById(@PathVariable Long id) {
return userService.findUserById(id)
.map(user -> ResponseEntity.ok(user))
.defaultIfEmpty(ResponseEntity.notFound().build())
.doOnSuccess(response -> {
if (response.getStatusCode().is2xxSuccessful()) {
log.info("成功获取用户: {}", id);
} else {
log.warn("用户不存在: {}", id);
}
});
}
/**
* 创建用户
*/
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono<UserDTO> createUser(@Valid @RequestBody Mono<CreateUserRequest> request) {
return request
.flatMap(userService::createUser)
.doOnSuccess(user -> {
log.info("创建用户成功: {}", user.getId());
eventPublisher.publishUserCreated(user);
})
.doOnError(error -> log.error("创建用户失败", error));
}
/**
* 更新用户
*/
@PutMapping("/{id}")
public Mono<ResponseEntity<UserDTO>> updateUser(
@PathVariable Long id,
@Valid @RequestBody Mono<UpdateUserRequest> request) {
return request
.flatMap(updateRequest -> userService.updateUser(id, updateRequest))
.map(updatedUser -> ResponseEntity.ok(updatedUser))
.defaultIfEmpty(ResponseEntity.notFound().build());
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public Mono<ResponseEntity<Void>> deleteUser(@PathVariable Long id) {
return userService.deleteUser(id)
.then(Mono.just(ResponseEntity.noContent().build()))
.onErrorReturn(ResponseEntity.notFound().build());
}
/**
* 搜索用户 - Server-Sent Events
*/
@GetMapping(value = "/search", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<UserDTO> searchUsers(
@RequestParam String keyword,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
return userService.searchUsers(keyword, page, size)
.delayElements(Duration.ofMillis(100)) // 控制发射速度
.doOnNext(user -> log.debug("发送用户: {}", user.getName()));
}
/**
* 用户统计信息
*/
@GetMapping("/stats")
public Mono<Map<String, Object>> getUserStats() {
return userService.getUserStatistics()
.doOnSubscribe(s -> log.info("获取用户统计信息"));
}
/**
* 批量创建用户
*/
@PostMapping("/batch")
public Flux<UserDTO> createUsersBatch(@Valid @RequestBody Flux<CreateUserRequest> requests) {
return requests
.buffer(10) // 每10个请求批量处理
.delayElements(Duration.ofMillis(500)) // 控制处理速度
.flatMap(batch -> userService.createUsersBatch(Flux.fromIterable(batch)))
.doOnNext(user -> log.info("批量创建用户: {}", user.getId()));
}
}
// 函数式路由配置
@Configuration
@Slf4j
public class FunctionalRoutesConfiguration {
@Bean
public RouterFunction<ServerResponse> userRoutes(ReactiveUserHandler userHandler) {
return RouterFunctions.route()
.GET("/api/v2/users", userHandler::getAllUsers)
.GET("/api/v2/users/{id}", userHandler::getUserById)
.POST("/api/v2/users", userHandler::createUser)
.PUT("/api/v2/users/{id}", userHandler::updateUser)
.DELETE("/api/v2/users/{id}", userHandler::deleteUser)
.GET("/api/v2/users/{id}/events", userHandler::getUserEvents)
.add(otherRoutes())
.filter(authenticationFilter())
.filter(loggingFilter())
.build();
}
@Bean
public RouterFunction<ServerResponse> otherRoutes() {
return RouterFunctions.route()
.GET("/api/v2/health", request ->
ServerResponse.ok().bodyValue(Map.of("status", "UP")))
.GET("/api/v2/metrics", this::getMetrics)
.build();
}
private Mono<ServerResponse> getMetrics(ServerRequest request) {
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(Map.of(
"activeConnections", 150,
"memoryUsage", "65%",
"responseTime", "45ms"
)));
}
// 认证过滤器
private HandlerFilterFunction<ServerResponse, ServerResponse> authenticationFilter() {
return (request, next) -> {
String authHeader = request.headers().firstHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return ServerResponse.status(HttpStatus.UNAUTHORIZED).build();
}
return next.handle(request);
};
}
// 日志过滤器
private HandlerFilterFunction<ServerResponse, ServerResponse> loggingFilter() {
return (request, next) -> {
long startTime = System.currentTimeMillis();
return next.handle(request)
.doOnNext(response -> {
long duration = System.currentTimeMillis() - startTime;
log.info("{} {} - {} - {}ms",
request.method(),
request.path(),
response.statusCode(),
duration);
});
};
}
}
// 函数式处理器
@Component
@Slf4j
public class ReactiveUserHandler {
private final ReactiveUserService userService;
private final ObjectMapper objectMapper;
public ReactiveUserHandler(ReactiveUserService userService, ObjectMapper objectMapper) {
this.userService = userService;
this.objectMapper = objectMapper;
}
public Mono<ServerResponse> getAllUsers(ServerRequest request) {
int page = Integer.parseInt(request.queryParam("page").orElse("0"));
int size = Integer.parseInt(request.queryParam("size").orElse("20"));
return userService.findAllUsers(page, size)
.collectList()
.flatMap(users -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(users));
}
public Mono<ServerResponse> getUserById(ServerRequest request) {
Long id = Long.parseLong(request.pathVariable("id"));
return userService.findUserById(id)
.flatMap(user -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(user))
.switchIfEmpty(ServerResponse.notFound().build());
}
public Mono<ServerResponse> createUser(ServerRequest request) {
return request.bodyToMono(CreateUserRequest.class)
.flatMap(userService::createUser)
.flatMap(user -> ServerResponse.status(HttpStatus.CREATED)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(user))
.onErrorResume(ValidationException.class, e ->
ServerResponse.badRequest()
.bodyValue(Map.of("error", e.getMessage())));
}
public Mono<ServerResponse> updateUser(ServerRequest request) {
Long id = Long.parseLong(request.pathVariable("id"));
return request.bodyToMono(UpdateUserRequest.class)
.flatMap(updateRequest -> userService.updateUser(id, updateRequest))
.flatMap(user -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(user))
.switchIfEmpty(ServerResponse.notFound().build());
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
Long id = Long.parseLong(request.pathVariable("id"));
return userService.deleteUser(id)
.then(ServerResponse.noContent().build())
.switchIfEmpty(ServerResponse.notFound().build());
}
public Mono<ServerResponse> getUserEvents(ServerRequest request) {
Long id = Long.parseLong(request.pathVariable("id"));
return ServerResponse.ok()
.contentType(MediaType.TEXT_EVENT_STREAM)
.body(userService.getUserEvents(id), UserEvent.class);
}
}
2.2 WebFlux高级特性
java
// WebFlux配置与优化
@Configuration
@EnableWebFlux
@Slf4j
public class WebFluxConfiguration implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
// 配置消息编解码器
configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024); // 10MB
}
@Override
public void addCorsMappings(CorsRegistry registry) {
// 配置CORS
registry.addMapping("/api/**")
.allowedOrigins("https://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
@Bean
public WebExceptionHandler webExceptionHandler() {
// 全局异常处理
return (exchange, ex) -> {
ServerHttpResponse response = exchange.getResponse();
if (ex instanceof ValidationException) {
response.setStatusCode(HttpStatus.BAD_REQUEST);
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(createErrorResponse(ex.getMessage()).getBytes())));
}
if (ex instanceof NotFoundException) {
response.setStatusCode(HttpStatus.NOT_FOUND);
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(createErrorResponse("Resource not found").getBytes())));
}
log.error("Unhandled exception", ex);
response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(createErrorResponse("Internal server error").getBytes())));
};
}
private String createErrorResponse(String message) {
return "{\"error\": \"" + message + "\"}";
}
@Bean
public WebFilter contextLoggingFilter() {
// 上下文日志过滤器
return (exchange, chain) -> {
String requestId = UUID.randomUUID().toString();
exchange.getAttributes().put("requestId", requestId);
long startTime = System.currentTimeMillis();
return chain.filter(exchange)
.doOnSuccessOrError((v, e) -> {
long duration = System.currentTimeMillis() - startTime;
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Request completed: {} {} - {} - {}ms - requestId: {}",
request.getMethod(),
request.getPath(),
response.getStatusCode(),
duration,
requestId);
});
};
}
@Bean
public WebFilter rateLimitingFilter() {
// 简单的速率限制过滤器
return (exchange, chain) -> {
String clientIp = getClientIp(exchange.getRequest());
// 这里可以实现更复杂的速率限制逻辑
if (isRateLimited(clientIp)) {
return Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
});
}
return chain.filter(exchange);
};
}
private String getClientIp(ServerHttpRequest request) {
String xForwardedFor = request.getHeaders().getFirst("X-Forwarded-For");
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
return xForwardedFor.split(",")[0].trim();
}
return request.getRemoteAddress() != null ?
request.getRemoteAddress().getAddress().getHostAddress() : "unknown";
}
private boolean isRateLimited(String clientIp) {
// 实现速率限制逻辑
return false;
}
}
// 响应式服务实现
@Service
@Slf4j
public class ReactiveUserService {
private final ReactiveUserRepository userRepository;
private final ReactiveProfileService profileService;
private final ReactiveEventPublisher eventPublisher;
private final Sinks.Many<UserEvent> userEventSink;
public ReactiveUserService(ReactiveUserRepository userRepository,
ReactiveProfileService profileService,
ReactiveEventPublisher eventPublisher) {
this.userRepository = userRepository;
this.profileService = profileService;
this.eventPublisher = eventPublisher;
this.userEventSink = Sinks.many().multicast().onBackpressureBuffer();
}
/**
* 查找所有用户 - 分页支持
*/
public Flux<UserDTO> findAllUsers(int page, int size) {
return userRepository.findAll()
.skip(page * size)
.take(size)
.map(this::convertToDTO)
.doOnRequest(n -> log.debug("Requested {} users", n));
}
/**
* 根据ID查找用户 - 包含Profile信息
*/
public Mono<UserDTO> findUserById(Long id) {
return userRepository.findById(id)
.map(this::convertToDTO)
.flatMap(user -> profileService.findProfileByUserId(id)
.map(profile -> {
user.setProfile(profile);
return user;
})
.defaultIfEmpty(user))
.doOnSuccess(user -> {
if (user != null) {
log.debug("Found user: {}", user.getName());
}
});
}
/**
* 创建用户 - 事务性操作
*/
@Transactional
public Mono<UserDTO> createUser(CreateUserRequest request) {
return Mono.just(request)
.map(this::convertToEntity)
.flatMap(userRepository::save)
.map(this::convertToDTO)
.flatMap(user -> profileService.createProfile(user.getId(), request.getEmail())
.thenReturn(user))
.doOnSuccess(user -> {
log.info("User created successfully: {}", user.getId());
eventPublisher.publishUserCreated(user);
userEventSink.tryEmitNext(new UserEvent("USER_CREATED", user));
})
.doOnError(error -> log.error("Failed to create user", error));
}
/**
* 批量创建用户
*/
public Flux<UserDTO> createUsersBatch(Flux<CreateUserRequest> requests) {
return requests
.map(this::convertToEntity)
.buffer(10) // 批量保存
.flatMap(userRepository::saveAll)
.map(this::convertToDTO)
.doOnNext(user -> log.info("Batch created user: {}", user.getId()));
}
/**
* 搜索用户
*/
public Flux<UserDTO> searchUsers(String keyword, int page, int size) {
return userRepository.findByNameContainingIgnoreCase(keyword)
.skip(page * size)
.take(size)
.map(this::convertToDTO)
.doOnSubscribe(s -> log.info("Searching users with keyword: {}", keyword));
}
/**
* 获取用户事件流
*/
public Flux<UserEvent> getUserEvents(Long userId) {
return userEventSink.asFlux()
.filter(event -> event.getUser().getId().equals(userId))
.doOnSubscribe(s -> log.info("User {} subscribed to events", userId));
}
/**
* 获取用户统计信息
*/
public Mono<Map<String, Object>> getUserStatistics() {
return userRepository.count()
.zipWith(userRepository.countActiveUsers())
.map(tuple -> Map.of(
"totalUsers", tuple.getT1(),
"activeUsers", tuple.getT2(),
"timestamp", Instant.now()
));
}
/**
* 更新用户信息
*/
public Mono<UserDTO> updateUser(Long id, UpdateUserRequest request) {
return userRepository.findById(id)
.flatMap(user -> {
user.setName(request.getName());
user.setEmail(request.getEmail());
user.setUpdatedAt(Instant.now());
return userRepository.save(user);
})
.map(this::convertToDTO)
.doOnSuccess(user -> {
log.info("User updated: {}", id);
userEventSink.tryEmitNext(new UserEvent("USER_UPDATED", user));
})
.switchIfEmpty(Mono.error(new NotFoundException("User not found: " + id)));
}
/**
* 删除用户
*/
public Mono<Void> deleteUser(Long id) {
return userRepository.findById(id)
.flatMap(user -> userRepository.delete(user))
.doOnSuccess(v -> {
log.info("User deleted: {}", id);
userEventSink.tryEmitNext(new UserEvent("USER_DELETED",
new UserDTO(id, "deleted", null)));
})
.switchIfEmpty(Mono.error(new NotFoundException("User not found: " + id)));
}
private User convertToEntity(CreateUserRequest request) {
User user = new User();
user.setName(request.getName());
user.setEmail(request.getEmail());
user.setCreatedAt(Instant.now());
user.setActive(true);
return user;
}
private UserDTO convertToDTO(User user) {
return new UserDTO(user.getId(), user.getName(), user.getEmail());
}
}
RSocket深度实战
3.1 RSocket通信模式
java
// RSocket服务端配置
@Configuration
@Slf4j
@MessageMapping("user.service")
public class RSocketServerConfiguration {
private final ReactiveUserService userService;
public RSocketServerConfiguration(ReactiveUserService userService) {
this.userService = userService;
}
/**
* 请求-响应模式 (Request-Response)
*/
@MessageMapping("user.get")
public Mono<UserDTO> getUser(Message<Long> message) {
Long userId = message.getPayload();
log.info("RSocket request-response: Get user {}", userId);
return userService.findUserById(userId)
.doOnSuccess(user -> log.debug("Found user: {}", user.getName()))
.doOnError(error -> log.error("Error getting user: {}", userId, error));
}
/**
* 请求-流模式 (Request-Stream)
*/
@MessageMapping("users.stream")
public Flux<UserDTO> streamUsers(Message<Map<String, Object>> message) {
Map<String, Object> params = message.getPayload();
int page = (int) params.getOrDefault("page", 0);
int size = (int) params.getOrDefault("size", 10);
log.info("RSocket request-stream: Stream users page={}, size={}", page, size);
return userService.findAllUsers(page, size)
.doOnSubscribe(s -> log.debug("Starting user stream"))
.doOnNext(user -> log.trace("Streaming user: {}", user.getName()))
.doOnComplete(() -> log.debug("User stream completed"))
.doOnError(error -> log.error("User stream error", error));
}
/**
* 即发-忘模式 (Fire-and-Forget)
*/
@MessageMapping("user.update.lastSeen")
public Mono<Void> updateLastSeen(Message<UserActivity> message) {
UserActivity activity = message.getPayload();
log.info("RSocket fire-and-forget: Update last seen for user {}", activity.getUserId());
// 异步处理,不等待响应
return userService.updateLastSeen(activity.getUserId(), activity.getTimestamp())
.doOnSuccess(v -> log.debug("Last seen updated for user {}", activity.getUserId()))
.doOnError(error -> log.error("Failed to update last seen", error))
.onErrorResume(error -> Mono.empty()); // 忽略错误
}
/**
* 通道模式 (Channel)
*/
@MessageMapping("user.events.channel")
public Flux<UserEvent> userEventsChannel(Flux<Map<String, Object>> requests) {
log.info("RSocket channel: User events channel established");
return requests
.switchMap(params -> {
Long userId = (Long) params.get("userId");
String eventType = (String) params.get("eventType");
log.debug("Channel request: userId={}, eventType={}", userId, eventType);
if ("ALL".equals(eventType)) {
return userService.getUserEvents(userId);
} else {
return userService.getUserEvents(userId)
.filter(event -> event.getType().equals(eventType));
}
})
.doOnSubscribe(s -> log.debug("User events channel subscribed"))
.doOnNext(event -> log.trace("Sending event: {}", event.getType()))
.doOnComplete(() -> log.debug("User events channel completed"))
.doOnError(error -> log.error("User events channel error", error));
}
/**
* 元数据推送
*/
@MessageMapping("user.metadata")
public Mono<Map<String, Object>> getUserWithMetadata(Message<Long> message) {
Long userId = message.getPayload();
// 处理元数据
MimeType mimeType = message.getHeaders().getContentType();
log.info("Request with metadata: contentType={}", mimeType);
return userService.findUserById(userId)
.map(user -> {
Map<String, Object> response = new HashMap<>();
response.put("user", user);
response.put("metadata", Map.of(
"processedAt", Instant.now(),
"serverId", "user-service-1"
));
return response;
});
}
}
// RSocket客户端服务
@Service
@Slf4j
public class RSocketClientService {
private final RSocketRequester rSocketRequester;
private final ObjectMapper objectMapper;
public RSocketClientService(RSocketRequester.Builder builder, ObjectMapper objectMapper) {
this.rSocketRequester = builder
.setupRoute("client.connect")
.setupData(Map.of("clientId", "web-client", "version", "1.0"))
.tcp("localhost", 7000);
this.objectMapper = objectMapper;
}
/**
* 请求-响应模式调用
*/
public Mono<UserDTO> getUserById(Long userId) {
log.info("RSocket client request-response: Get user {}", userId);
return rSocketRequester
.route("user.service.user.get")
.data(userId)
.retrieveMono(UserDTO.class)
.timeout(Duration.ofSeconds(5))
.doOnSuccess(user -> log.debug("Received user: {}", user.getName()))
.doOnError(error -> log.error("Failed to get user: {}", userId, error));
}
/**
* 请求-流模式调用
*/
public Flux<UserDTO> streamUsers(int page, int size) {
log.info("RSocket client request-stream: Stream users page={}, size={}", page, size);
Map<String, Object> params = Map.of("page", page, "size", size);
return rSocketRequester
.route("user.service.users.stream")
.data(params)
.retrieveFlux(UserDTO.class)
.doOnSubscribe(s -> log.debug("Starting user stream"))
.doOnNext(user -> log.trace("Received user: {}", user.getName()))
.doOnComplete(() -> log.debug("User stream completed"))
.doOnError(error -> log.error("User stream error", error));
}
/**
* 即发-忘模式调用
*/
public Mono<Void> updateUserLastSeen(Long userId) {
log.info("RSocket client fire-and-forget: Update last seen for user {}", userId);
UserActivity activity = new UserActivity(userId, Instant.now());
return rSocketRequester
.route("user.service.user.update.lastSeen")
.data(activity)
.send()
.doOnSuccess(v -> log.debug("Last seen update sent for user {}", userId))
.doOnError(error -> log.error("Failed to send last seen update", error));
}
/**
* 通道模式调用
*/
public Flux<UserEvent> openUserEventsChannel(Long userId, String eventType) {
log.info("RSocket client channel: Open events channel for user {}, eventType={}",
userId, eventType);
Map<String, Object> initialRequest = Map.of(
"userId", userId,
"eventType", eventType
);
return rSocketRequester
.route("user.service.user.events.channel")
.data(Flux.interval(Duration.ofMinutes(1))
.map(i -> Map.of("userId", userId, "eventType", eventType)))
.retrieveFlux(UserEvent.class)
.doOnSubscribe(s -> log.debug("User events channel opened"))
.doOnNext(event -> log.debug("Received event: {}", event.getType()))
.doOnComplete(() -> log.debug("User events channel closed"))
.doOnError(error -> log.error("User events channel error", error));
}
/**
* 负载均衡调用
*/
public Mono<UserDTO> getUserWithLoadBalancing(Long userId) {
return rSocketRequester
.route("user.service.user.get")
.data(userId)
.retrieveMono(UserDTO.class)
.onErrorResume(error -> {
log.warn("Primary service failed, trying backup: {}", error.getMessage());
// 可以切换到备份服务
return getBackupUser(userId);
});
}
private Mono<UserDTO> getBackupUser(Long userId) {
// 实现备份服务调用
return Mono.just(new UserDTO(userId, "backup-user", "backup@example.com"));
}
/**
* 带元数据的调用
*/
public Mono<Map<String, Object>> getUserWithMetadata(Long userId) {
return rSocketRequester
.route("user.service.user.metadata")
.metadata("client-timestamp", Instant.now().toString())
.data(userId)
.retrieveMono(Map.class)
.doOnSuccess(response -> {
log.debug("Received response with metadata: {}", response.get("metadata"));
});
}
}
// RSocket配置
@Configuration
@Slf4j
public class RSocketConfiguration {
@Bean
public RSocketStrategies rSocketStrategies() {
return RSocketStrategies.builder()
.encoders(encoders -> encoders.add(new Jackson2CborEncoder()))
.decoders(decoders -> decoders.add(new Jackson2CborDecoder()))
.routeMatcher(new PathPatternRouteMatcher())
.metadataExtractor(metadataExtractor())
.build();
}
@Bean
public MetadataExtractor metadataExtractor() {
return new DefaultMetadataExtractor();
}
@Bean
public RSocketMessageHandler rSocketMessageHandler(RSocketStrategies strategies) {
RSocketMessageHandler handler = new RSocketMessageHandler();
handler.setRSocketStrategies(strategies);
return handler;
}
@Bean
@Profile("rsocket-server")
public RSocketServerCustomizer rSocketServerCustomizer() {
return server -> server
.fragment(16384) // 16KB fragments
.payloadDecoder(PayloadDecoder.ZERO_COPY);
}
@Bean
@Profile("rsocket-client")
public RSocketRequester rSocketRequester(RSocketRequester.Builder builder) {
return builder
.rsocketConnector(connector -> connector
.reconnect(Retry.fixedDelay(3, Duration.ofSeconds(2)))
.tcp("localhost", 7000);
}
}
// 领域模型
@Data
@AllArgsConstructor
@NoArgsConstructor
class UserActivity {
private Long userId;
private Instant timestamp;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class UserEvent {
private String type;
private UserDTO user;
private Instant timestamp = Instant.now();
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class CreateUserRequest {
@NotBlank
private String name;
@Email
private String email;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class UpdateUserRequest {
@NotBlank
private String name;
@Email
private String email;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class UserDTO {
private Long id;
private String name;
private String email;
private Object profile;
public UserDTO(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
}
// 自定义异常
class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
性能优化与监控
4.1 响应式应用性能调优
java
// 响应式性能监控
@Component
@Slf4j
public class ReactivePerformanceMonitor {
private final MeterRegistry meterRegistry;
private final Timer webfluxRequestTimer;
private final Counter backpressureEvents;
private final Gauge activeSubscriptions;
private final AtomicInteger subscriptionCount = new AtomicInteger(0);
public ReactivePerformanceMonitor(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.webfluxRequestTimer = Timer.builder("webflux.request.duration")
.description("WebFlux request processing duration")
.register(meterRegistry);
this.backpressureEvents = Counter.builder("reactive.backpressure.events")
.description("Backpressure events count")
.register(meterRegistry);
this.activeSubscriptions = Gauge.builder("reactive.subscriptions.active")
.description("Active reactive subscriptions")
.register(meterRegistry, subscriptionCount, AtomicInteger::get);
}
/**
* 监控Flux性能
*/
public <T> Flux<T> monitorFlux(String name, Flux<T> flux) {
return flux
.doOnSubscribe(s -> {
subscriptionCount.incrementAndGet();
log.debug("Flux subscribed: {}", name);
})
.doOnCancel(() -> {
subscriptionCount.decrementAndGet();
log.debug("Flux cancelled: {}", name);
})
.doOnTerminate(() -> {
subscriptionCount.decrementAndGet();
log.debug("Flux terminated: {}", name);
})
.doOnRequest(n -> log.trace("Flux {} requested {} elements", name, n))
.doOnNext(item -> log.trace("Flux {} emitted item", name))
.onBackpressureBuffer(100,
buffer -> {
backpressureEvents.increment();
log.warn("Backpressure buffer overflow in {}", name);
},
BufferOverflowStrategy.DROP_OLDEST);
}
/**
* 监控Mono性能
*/
public <T> Mono<T> monitorMono(String name, Mono<T> mono) {
return mono
.doOnSubscribe(s -> {
subscriptionCount.incrementAndGet();
log.debug("Mono subscribed: {}", name);
})
.doOnSuccess(item -> {
subscriptionCount.decrementAndGet();
log.debug("Mono completed successfully: {}", name);
})
.doOnError(error -> {
subscriptionCount.decrementAndGet();
log.error("Mono failed: {}", name, error);
})
.doOnCancel(() -> {
subscriptionCount.decrementAndGet();
log.debug("Mono cancelled: {}", name);
});
}
/**
* 记录请求处理时间
*/
public Mono<ServerResponse> timeRequest(ServerRequest request,
Mono<ServerResponse> responseMono) {
long startTime = System.nanoTime();
return responseMono
.doOnSuccess(response -> {
long duration = System.nanoTime() - startTime;
webfluxRequestTimer.record(duration, TimeUnit.NANOSECONDS);
log.debug("Request {} {} processed in {} ns",
request.method(), request.path(), duration);
});
}
/**
* 线程池监控
*/
@EventListener
public void monitorThreadPools(ApplicationReadyEvent event) {
Schedulers.enableMetrics();
// 监控并行调度器
Gauge.builder("schedulers.parallel.active")
.description("Parallel scheduler active threads")
.register(meterRegistry, Schedulers.parallel(),
s -> ((SchedulerMetrics) s).activeTasks());
// 监控弹性调度器
Gauge.builder("schedulers.elastic.active")
.description("Elastic scheduler active threads")
.register(meterRegistry, Schedulers.boundedElastic(),
s -> ((SchedulerMetrics) s).activeTasks());
}
}
// 响应式缓存配置
@Configuration
@Slf4j
public class ReactiveCacheConfiguration {
@Bean
public ReactiveCacheManager reactiveCacheManager() {
return new ReactiveRedisCacheManager(
ReactiveRedisConnectionFactory connectionFactory,
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class)))
);
}
@Bean
public CacheAspectSupport cacheAspect() {
return new ReactiveCachingAspect(reactiveCacheManager());
}
}
// 响应式健康检查
@Component
@Slf4j
public class ReactiveHealthIndicator implements ReactiveHealthIndicator {
private final ReactiveUserRepository userRepository;
private final Sinks.Many<HealthEvent> healthEventSink;
public ReactiveHealthIndicator(ReactiveUserRepository userRepository) {
this.userRepository = userRepository;
this.healthEventSink = Sinks.many().multicast().onBackpressureBuffer();
}
@Override
public Mono<Health> health() {
return checkDatabaseConnection()
.timeout(Duration.ofSeconds(5))
.map(connected -> {
if (connected) {
Health health = Health.up()
.withDetail("database", "connected")
.withDetail("timestamp", Instant.now())
.build();
healthEventSink.tryEmitNext(new HealthEvent("HEALTH_CHECK", health));
return health;
} else {
Health health = Health.down()
.withDetail("database", "disconnected")
.withDetail("timestamp", Instant.now())
.build();
healthEventSink.tryEmitNext(new HealthEvent("HEALTH_CHECK_FAILED", health));
return health;
}
})
.onErrorResume(error -> {
log.error("Health check failed", error);
Health health = Health.down(error).build();
healthEventSink.tryEmitNext(new HealthEvent("HEALTH_CHECK_ERROR", health));
return Mono.just(health);
});
}
private Mono<Boolean> checkDatabaseConnection() {
return userRepository.count()
.map(count -> true)
.onErrorReturn(false);
}
public Flux<HealthEvent> healthEvents() {
return healthEventSink.asFlux();
}
}
@Data
@AllArgsConstructor
class HealthEvent {
private String type;
private Health health;
private Instant timestamp = Instant.now();
}
总结
🎯 响应式编程核心价值
-
性能优势
- 非阻塞I/O提升并发处理能力
- 背压机制防止系统过载
- 资源高效利用
-
编程模型
- 声明式编程提升代码可读性
- 函数式编程增强代码可维护性
- 流式处理简化复杂业务逻辑
-
系统架构
- 更好的弹性设计
- 改进的可伸缩性
- 增强的容错能力
🚀 WebFlux实战要点
-
控制器设计
- 合理使用Flux和Mono
- 正确处理背压
- 优化数据流处理
-
错误处理
- 全局异常处理机制
- 重试和回退策略
- 超时控制
-
性能优化
- 调度器合理配置
- 缓存策略优化
- 连接池管理
🔌 RSocket核心特性
-
交互模式
- 请求-响应:传统RPC模式
- 请求-流:数据流传输
- 即发-忘:日志、指标上报
- 通道:双向数据流
-
协议优势
- 二进制协议高性能
- 应用层流量控制
- 多语言支持
📋 生产环境建议
-
监控告警
- 响应式流监控
- 背压事件告警
- 线程池使用监控
-
调试排查
- 启用详细日志
- 使用调试操作符
- 性能 profiling
-
容量规划
- 合理设置缓冲区
- 线程池大小调优
- 内存使用评估
响应式编程代表了现代应用开发的未来方向,掌握WebFlux和RSocket将帮助您构建更高性能、更弹性的分布式系统。
下一篇预告:《MySQL高级优化与架构设计:从索引优化到分库分表》
如果觉得本文对你有帮助,请点赞、收藏、关注!欢迎在评论区分享你的响应式编程实践经验和问题。