首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RestTemplate postForEntity遇到java.io.IOException:过早的EOF错误

RestTemplate postForEntity遇到java.io.IOException:过早的EOF错误
EN

Stack Overflow用户
提问于 2017-09-11 11:35:02
回答 4查看 2.6K关注 0票数 3

对于我的一个maven项目中的问题,我将非常感谢您的帮助。

代码语言:javascript
运行
复制
Exception in thread "main" org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://test-services.domain.ph/campaign/": Premature EOF; nested exception is java.io.IOException: Premature EOF
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:407)
at homecredit.ph.CampaignConnector.call(CampaignConnector.java:46)
Caused by: java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:609)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:696)
at java.io.FilterInputStream.read(FilterInputStream.java:133)

原点:

代码语言:javascript
运行
复制
ResponseEntity<ApiResponse> response = restTemplate.postForEntity(url, entity, ApiResponse.class);

目的地:

代码语言:javascript
运行
复制
@RequestMapping(value="/campaign", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ApiResponse> insertCampaignRecord(
        @Valid @RequestBody CampaignRecordInsertRequest campaignRecordInsertRequest){
    logInfo("Incoming insert request. " + DescriptorUtility.convertToString(campaignRecordInsertRequest));
    campaignDataService.insertNewRecord(CampaignRecordConverter.convertToCampaignRecord(campaignRecordInsertRequest));
    return ResponseUtility.defaultResponse();
}

ResponseUtility

代码语言:javascript
运行
复制
public static ResponseEntity<ApiResponse> defaultResponse(){
    ApiResponse apiResponse = new ApiResponse();
    apiResponse.setTimestamp(DateUtility.currentDateString());
    apiResponse.setMessage(ResponseMessages.SUCCESS);
    return new ResponseEntity<>(apiResponse, HttpStatus.OK);
}

CampaignData服务

代码语言:javascript
运行
复制
@Async("AsyncExecutor")
public void insertNewRecord(CampaignRecord campaignRecord) {
    try {
        campaignRecordRepository.save(campaignRecord);
    } catch (Exception e) {
        logError(e);
    }
}

服务器日志

代码语言:javascript
运行
复制
2017-09-11 11:11:11  INFO 18383 [http-nio-8773-exec-10] [CampaignRecordController] - Incoming insert request. {"dateCampaign":1504656000000,"cuid":...
2017-09-11 11:11:11  WARN 18383 [http-nio-8773-exec-10] [SqlExceptionHelper] - SQL Error: 1062, SQLState: 23000
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [SqlExceptionHelper] - Duplicate entry 'CMP_CLX##1208637#20170906' for key 'UNIQUE_KEY'
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [CampaignDataService] - could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [CampaignDataService] - could not execute statement

PS。服务器日志正常(无论记录保存成功与否,均返回成功响应)

问题是间歇性的。在发送批量请求时随机发生。

提前感谢!:)

EN

回答 4

Stack Overflow用户

发布于 2019-04-17 02:44:07

我在Spring Boot2.1中也遇到了同样的问题。在我的例子中,我有3个应用程序(称为A、B和C),其中B实际上只是A和C之间的代理:

代码语言:javascript
运行
复制
A --> B --> C

Premature EOF发生在从B到A的响应中。所有指示都是一个成功的HTTP响应(200),但是使用调试器检查响应的正文时发现,在序列化的DTO数据的中间有一个新的行字符,而不是在我预期的结尾:

(注意id字段后面的返回字符,没有任何内容长度;忽略末尾不可读的框,它们是未初始化/使用的字节数组的一部分)

在我的例子中,服务B既是服务器又是客户端。代码看起来像这样:

代码语言:javascript
运行
复制
public ResponseEntity<String> handle(String request, HttpHeaders headers) {

    // Do some validation and then call Service C, and pass the response
    // back to Service A

    return restTemplate.postForEntity(
        urlForServiceC,
        new HttpEntity<>(request, headers),
        String.class);
}

我并没有深入研究RestTemplate或它的消息转换器的内部结构,但告诉我响应缓冲可能存在问题的是,我使用Spring filter来记录每个服务的响应。此筛选器必须复制响应流,以避免来自与已被使用的正文相关的其他筛选器的异常。

我注意到,当我在启用此过滤器的情况下运行时,Premature EOF异常消失了。当我禁用它时,异常又回来了。关于复制响应流的一些事情已经解决了Premature EOF错误。

这导致我在服务B中尝试了以下内容:

代码语言:javascript
运行
复制
public ResponseEntity<String> handle(String request, HttpHeaders headers) {

    // Do some validation and then call Service C, and pass the response
    // back to Service A

    String response = restTemplate.postForEntity(
        urlForServiceC,
        new HttpEntity<>(request, headers),
        String.class).getBody();

    return ResponseEntity.ok(response);
}

细微的变化是,我首先将响应保存到一个局部变量,这需要我调用ResponseEntity.getBody()。这迫使服务C的整个响应主体在返回到服务A之前被使用。在进行此更改之后,我的Premature EOF错误没有返回。

票数 1
EN

Stack Overflow用户

发布于 2017-09-11 13:06:42

根据服务器日志,服务器正在尝试保存一些记录,但失败了(由于唯一键冲突)。

代码语言:javascript
运行
复制
2017-09-11 11:11:11  WARN 18383 [http-nio-8773-exec-10] [SqlExceptionHelper] - SQL Error: 1062, SQLState: 23000
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [SqlExceptionHelper] - Duplicate entry 'CMP_CLX##1208637#20170906' for key 'UNIQUE_KEY'
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [CampaignDataService] - could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [CampaignDataService] - could not execute statement

看起来服务器不能很好地处理异常,整个流程中断,导致HTTP-500响应代码(可能)响应为空。

您可以执行以下两个操作:

唯一键被违反的原因gracefully.

  • Verify
  1. 处理异常,并在可能的情况下修复该问题。
票数 0
EN

Stack Overflow用户

发布于 2017-09-11 17:01:28

对于任何可能正在经历这种情况的人来说。问题是由spring boot eureka引起的。当涉及到在大规模(批量处理)中传递ResponseEntity响应时,似乎存在一个错误,导致响应状态为畸形。

当前的解决方法是从ResponseEntity切换到object body。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46147813

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档