【问题标题】:PUT on void http-inbound-gatewayPUT 无效 http-inbound-gateway
【发布时间】:2016-02-19 11:04:54
【问题描述】:

我不知道我是否正确地关注了这个问题 - 我通过 RestTemplate 发送了一个 PUT 请求,如下所示:

restTemplate.exchange(getBaseUrl() + "/api/getVoid", HttpMethod.PUT, new HttpEntity<String>("someMessage"), Void.class);

或:

restTemplate.put(getBaseUrl() + "/api/getVoid", "someMessage");

PUT 所以这意味着我不期待回复内容。我的 HTTP PUT 服务由 Spring Integration 组件公开:

<int-http:inbound-gateway supported-methods="PUT" reply-timeout="5000"
                      path="/api/getVoid"
                      request-channel="some-request-channel1" reply-channel="some-reply-channel1">

<int:channel id="some-request-channel1"/>
<int:channel id="some-reply-channel1"/>

<int:service-activator input-channel="some-request-channel1" output-channel="some-reply-channel1" ref="someService"
                   method="restMethodVoid"/>

我的入站网关集上有一个回复通道,但处理请求的服务“返回”无效(某些 PUT 操作)。

@ServiceActivator
public void restMethodVoid(Message<String> request) {
   log.info("DONE! But you will get 500");
}

现在的问题 - 我可以看到将 PUT 请求发送到入站网关以使用 void 返回方法进行处理会在回复超时时引发 500 内部服务器错误。

这是否意味着不可能向“由”无效服务方法操作的 SI http 入站网关发送 PUT 或任何其他请求?

这是 1.3.2 版本中的行为,但它在 1.2.3 中的行为有所不同 - 网关行为似乎相同 - 它超时但没有抛出 500 - 只是回到仍在等待请求线程并释放它“很好”(仍然只是超时)。

我认为这两种行为都不是完美的,但 1.3.2 更糟糕,因为假设我将 PUT(或以 Void.class 作为返回类型的 POST...)发送为进程并且处理得很好 - 一些关键的事务操作被提交等等 - 方法返回非常好,但调用者得到 500。所以这个 500 被传播给它的调用者......可能以 UI 上的错误结束(这真的会吓到用户;))。但一切都很顺利。

在 1.2.3 行为中 - 即使超时但线程可以返回到其调用者并返回 200 状态,因此接下来传播正确的响应代码。

Gary,Artem - 你能在这里给点建议吗?

【问题讨论】:

  • 这是来自 1.2.3.RELEASE 版本的响应:11:16:01.882 [Thread-3] DEBUG o.s.web.client.RestTemplate - PUT request for "http://localhost:64526/api/getVoid" resulted in 200 (OK)(仍然是超时)。从 1.3.2.RELEASE 开始:org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error。嗯
  • 我不确定你指的是凋零版本 1.2.3 和 1.3.2;这些版本不存在;该行为在 4.2 版中已更改(已修复) - 请参阅下面的答案。
  • 对不起,我指的是 Spring Boot 版本。

标签: spring-integration


【解决方案1】:

请参阅discussion on this pull request

当下游流返回 void 时,您应该使用入站通道适配器,而不是网关;该修复是在发生超时时更正网关的问题 - 它错误地返回 200,现在返回 500(默认情况下)。

以这种方式使用网关时,您会错误地将 Web 容器线程绑定到默认超时 (1s) 等待永远不会收到的回复。

从那里重复我的完整答案...

网关用于双向交互(请求/回复);此修复纠正了如果发生超时,则返回 200 OK 的问题;这是不正确的。

如果您从不期待回复(例如您的情况),您应该使用&lt;http:inbound-channel-adapter/&gt;。通道适配器用于与消息流的单向交互(尽管在这种情况下,会向调用者发送 200 OK)。在这种情况下,单向意味着流程不返回回复。

事实上,这个修复只是暴露了您的配置中的一个错误;在此更改之前,线程将在流程完成(等待回复)后暂停 1 秒(默认回复超时)。这意味着您的所有请求都比需要的时间长 1 秒。

适配器不等待回复。

【讨论】:

  • 感谢您的解释。但是为什么在超时的情况下返回 500 而不是 408 - REQUEST_TIMEOUT?
  • 408 是 client 错误(客户端没有及时完成请求)。 5xx 是服务器错误。我们默认选择了 500 服务器错误,504(网关超时)具有我们无法假设的语义——我们不知道应用程序是否是代理。 reference manual 解释了如何使用 reply-timeout-status-code-expression 更改默认 500。
  • D'oh.. 是的,我看到一切,一如既往,仔细考虑;)再次感谢! 504 似乎都不适合(不是这个网关;))
  • 加里,只是最后一个问题 - 当这个 200 作为超时返回时(假设它设置为 10 秒) - 需要超过 10 秒的长时间运行的作业发生了什么 - 是停止了或者只是调用线程以 200 被释放并且请求的作业仍在服务器上运行?
  • 这取决于您是否切换到另一个线程 - 网关超时仅在线程返回网关时开始 - 如果您在 Web 容器线程上运行长时间运行的作业,则计时器在工作完成;如果您移交给另一个线程,则计时器会在移交后启动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
相关资源
最近更新 更多