Spring Boot多并发请求时出现EOFException及Tomcat请求解析错误的问题求助
Spring Boot多并发请求时出现EOFException及Tomcat请求解析错误的问题求助
我最近碰到了一个棘手的问题:我的Spring Boot Web服务在同时发送多个请求时,部分请求会失败,但如果是单步调试或者逐个发送请求的话,所有请求都能正常通过。
技术栈
- Spring Boot版本: 2.7.4
- 嵌入式服务器: Tomcat 9.0.65
- 开发工具: IntelliJ IDEA
- 测试客户端: Postman
错误日志
当发送批量请求时,日志里会出现以下错误:
2025-03-31 16:22:29.271 DEBUG 16768 --- [nio-8082-exec-1] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header 2025-03-31 16:22:29.272 DEBUG 16768 --- [nio-8082-exec-1] o.apache.coyote.http11.Http11Processor : Error state [CLOSE_CONNECTION_NOW] reported while processing request
对应的堆栈跟踪:
java.io.EOFException: null at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1340) ~[tomcat-embed-core-9.0.65.jar:9.0.65] at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1227) ~[tomcat-embed-core-9.0.65.jar:9.0.65] at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:805) ~[tomcat-embed-core-9.0.65.jar:9.0.65] at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:360) ~[tomcat-embed-core-9.0.65.jar:9.0.65] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:271) ~[tomcat-embed-core-9.0.65.jar:9.0.65] ...
相关代码
Controller端点
@PostMapping("api/synchro/process") public ResponseEntity<String> processEntries(@RequestBody List<Synchro> entries) { try { for (Synchro entry : entries) { System.out.println(entry.getId()); synchroService.processSynchroEntry(entry); } return ResponseEntity.ok("PROCESSED"); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Error processing entries: " + e.getMessage()); } }
Service方法
@Transactional public void processSynchroEntry(Synchro entry) { String eventType = entry.getEventType().toUpperCase(); String data = entry.getData(); String tableName = entry.getTableName(); switch (eventType) { case "INSERT" -> this.handleInsert(tableName, data); case "UPDATE" -> this.handleUpdate(tableName, data); case "DELETE" -> this.handleDelete(tableName, data); default -> throw new IllegalArgumentException("Unsupported event type: " + eventType); } }
动态插入查询执行逻辑
protected void handleInsert(String tableName, String data) { try { JsonNode dataNode = this.objectMapper.readTree(data); StringBuilder query = new StringBuilder("INSERT INTO "); query.append(tableName).append(" ("); MapSqlParameterSource params = new MapSqlParameterSource(); StringBuilder columns = new StringBuilder(); StringBuilder values = new StringBuilder(); Iterator<Map.Entry<String, JsonNode>> it = dataNode.fields(); while(it.hasNext()) { Map.Entry<String, JsonNode> field = it.next(); if (columns.length() > 0) { columns.append(", "); values.append(", "); } columns.append(field.getKey()); values.append(":" + field.getKey()); params.addValue(field.getKey(), field.getValue().asText()); } query.append(columns).append(") VALUES (").append(values).append(")"); this.namedParameterJdbcTemplate.update(query.toString(), params); } catch (Exception e) { throw new RuntimeException("Error processing insert", e); } }
已尝试的排查步骤
- 检查请求格式:通过Postman发送的请求格式完全正确
- 开启Spring Boot调试日志:确认部分请求确实因EOFException失败
- 测试不同并发级别:逐个发送请求全部成功,批量发送则部分失败
- 验证JSON payload:所有发送的JSON数据格式都没问题
- 调整Tomcat连接配置:尝试修改了以下参数,但问题依旧
server.tomcat.max-threads=200 server.tomcat.accept-count=100 server.connection-timeout=60000
我的疑问
- 到底是什么原因导致批量发送请求时出现这些EOFException?
- 这会不会和事务处理或者Tomcat的连接管理方式有关?
- Spring Boot/Tomcat有没有已知的类似问题会导致这种行为?
- 任何相关的见解或建议我都非常感激!
Synchro实体类代码
public class Synchro { @Id @GeneratedValue( strategy = GenerationType.IDENTITY ) @Column( name = "id", unique = true, nullable = false ) private @NotNull( message = "Id ne peut pas être null" ) Integer id; @Column( name = "eventType", length = 100, nullable = false ) private @NotNull( message = "EventType ne peut pas être null" ) String eventType; @Column( name = "data", nullable = false ) private @NotNull( message = "Data ne peut pas être null" ) String data; @Temporal(TemporalType.TIMESTAMP) @Column( name = "createdAt" ) private @NotNull( message = "CreatedAt ne peut pas être null" ) Date createdAt; @Temporal(TemporalType.TIMESTAMP) @Column( name = "updatedAt" ) private Date updatedAt; @Column( name = "status", length = 20, nullable = false ) private @NotNull( message = "Status ne peut pas être null" ) String status; @Column( name = "tableName", length = 100, nullable = false ) private @NotNull( message = "TableName ne peut pas être null" ) String tableName; @Transient private String source; }
备注:内容来源于stack exchange,提问作者Wassupppp




