本文目录导读:

- Spring Boot/WebFlux 异步请求超时
- RestTemplate HTTP 请求超时
- WebClient 响应式超时
- Servlet 容器配置(Tomcat)
- Spring Cloud OpenFeign 超时
- 数据库查询超时
- 全局超时异常处理
- 最佳实践建议
在Java中处理请求超时通常涉及以下几个方面,具体实现取决于你使用的框架和技术栈,以下是几种常见场景及处理方案:
Spring Boot/WebFlux 异步请求超时
使用 @Async 配合 Future
import java.util.concurrent.*;
@Service
public class AsyncService {
@Async
public Future<String> slowOperation() {
// 模拟耗时操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return new AsyncResult<>("完成");
}
}
// 控制器中处理超时
@RestController
public class TimeoutController {
@Autowired
private AsyncService service;
@GetMapping("/timeout-demo")
public String handleTimeout() {
Future<String> future = service.slowOperation();
try {
// 设置2秒超时
return future.get(2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
return "请求超时";
} catch (Exception e) {
return "处理异常:" + e.getMessage();
}
}
}
使用 CompletableFuture
@GetMapping("/completable-timeout")
public String handleCompletableTimeout() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "完成";
});
try {
return future.orTimeout(2, TimeUnit.SECONDS)
.exceptionally(ex -> "请求超时")
.get();
} catch (Exception e) {
return "处理失败";
}
}
RestTemplate HTTP 请求超时
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
// 连接超时
factory.setConnectTimeout(3000);
// 读取超时
factory.setReadTimeout(5000);
return new RestTemplate(factory);
}
}
// 使用
@Service
public class HttpService {
@Autowired
private RestTemplate restTemplate;
public String callExternalApi() {
try {
return restTemplate.getForObject(
"https://example.com/slow-api",
String.class
);
} catch (ResourceAccessException e) {
return "外部服务超时:" + e.getMessage();
}
}
}
WebClient 响应式超时
@Service
public class ReactiveService {
public Mono<String> callWithTimeout() {
return WebClient.create("https://example.com")
.get()
.uri("/slow-api")
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(3)) // 整体超时
.onErrorResume(TimeoutException.class, e ->
Mono.just("请求超时(响应式)"))
.onErrorResume(Exception.class, e ->
Mono.just("其他错误:" + e.getMessage()));
}
}
// 控制器
@RestController
public class WebClientController {
@Autowired
private ReactiveService service;
@GetMapping("/reactive-timeout")
public Mono<String> handleReactiveTimeout() {
return service.callWithTimeout();
}
}
Servlet 容器配置(Tomcat)
application.yml
server:
tomcat:
connection-timeout: 3000 # 连接超时(毫秒)
max-connections: 10000 # 最大连接数
max-threads: 200 # 最大线程数
servlet:
session:
timeout: 30m # Session超时
全局 Filter 处理
@Component
public class TimeoutFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
long timeout = 5000; // 5秒
// 设置请求超时
httpRequest.startAsync();
httpRequest.getAsyncContext().setTimeout(timeout);
chain.doFilter(request, response);
}
}
Spring Cloud OpenFeign 超时
配置类
feign:
client:
config:
default:
connectTimeout: 3000 # 连接超时
readTimeout: 5000 # 读取超时
loggerLevel: basic
specific-service: # 特定服务配置
connectTimeout: 5000
readTimeout: 10000
代码配置
@Configuration
public class FeignConfig {
@Bean
public Request.Options options() {
return new Request.Options(
3000, // 连接超时
TimeUnit.MILLISECONDS,
5000, // 读取超时
TimeUnit.MILLISECONDS,
true // 跟随重定向
);
}
}
@FeignClient(name = "example-service", configuration = FeignConfig.class)
public interface ExampleClient {
@GetMapping("/api/data")
String getData();
}
数据库查询超时
JDBC 超时设置
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setConnectionTimeout(3000); // 连接超时
config.setConnectionTestTimeout(3000); // 连接测试超时
config.setMaxLifetime(1800000); // 连接最大生命周期
return new HikariDataSource(config);
}
}
// JPA 查询超时设置
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager entityManager;
public List<User> findUsersWithTimeout() {
Query query = entityManager.createQuery("SELECT u FROM User u");
query.setHint("javax.persistence.query.timeout", 5000); // 5秒
return query.getResultList();
}
}
全局超时异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(TimeoutException.class)
@ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
@ResponseBody
public Map<String, Object> handleTimeout(TimeoutException e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 408);
result.put("message", "请求超时");
result.put("timestamp", System.currentTimeMillis());
return result;
}
@ExceptionHandler(ResourceAccessException.class)
@ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
@ResponseBody
public Map<String, Object> handleResourceTimeout(ResourceAccessException e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 408);
result.put("message", "外部服务超时:" + e.getMessage());
return result;
}
}
最佳实践建议
- 分层设置超时:对不同层级设置不同的超时时间(网络层>服务层>数据库层)
- 合理设置超时值:
- 连接超时:3000-5000ms
- 读取超时:5000-10000ms
- 业务处理超时:根据业务复杂度设定
- 使用断路器:结合 Hystrix/Resilience4j 防止雪崩效应
- 超时后处理:
- 返回默认值或缓存数据
- 异步补偿处理
- 记录日志用于监控
// Resilience4j 断路器示例
@CircuitBreaker(name = "externalService", fallbackMethod = "fallback")
@TimeLimiter(name = "externalService", fallbackMethod = "fallback")
public CompletableFuture<String> callExternalService() {
return CompletableFuture.supplyAsync(() -> {
// 调用外部服务
return restTemplate.getForObject("...", String.class);
});
}
public CompletableFuture<String> fallback(TimeoutException e) {
return CompletableFuture.completedFuture("服务超时,使用降级数据");
}
选择哪种方案取决于你的应用架构、性能要求和业务场景,建议在生产环境中结合监控系统(如Prometheus)来动态调整超时参数。