首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何用Java的HttpClient在慢速流响应体上超时

如何用Java的HttpClient在慢速流响应体上超时
EN

Stack Overflow用户
提问于 2021-05-19 03:15:31
回答 2查看 1.4K关注 0票数 8

当我需要以流的方式处理响应时,我应该如何处理挂起使用Java 11中包含的HTTP客户机发送HTTP响应体的服务器?

阅读了文档之后,我意识到设置连接超时请求超时是可能的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HttpClient httpClient = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(2))
        .build();

HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://example.com"))
        .timeout(Duration.ofSeconds(5))
        .build();

HttpResponse<Stream<String>> httpResponse = httpClient
        .send(httpRequest, HttpResponse.BodyHandlers.ofLines());

Stream<String> responseLineStream = httpResponse.body();
responseLineStream.count();

在上述守则中:

  • 如果无法在2秒内建立连接,则会引发超时异常。
  • 如果在5秒内未收到响应,则将引发超时异常。通过实验,定时器在建立连接之后启动,对于这种类型的BodyHandler,在收到状态行和标头时,会考虑接收响应。

这意味着当代码执行时,在7秒内就会抛出一个异常,或者我们已经到达最后一行。但是,最后一行不受任何超时的限制。如果服务器停止发送响应体,则最后一行将永远阻塞。

在这种情况下,我怎样才能避免最后一句呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-05-19 04:31:34

我猜这将留给流的使用者,因为这是处理逻辑的一部分,所以仍然可以使用CompletableFuture来处理主体处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HttpResponse<Stream<String>> httpResponse = httpClient.send(httpRequest,
                                                            HttpResponse.BodyHandlers.ofLines());

Stream<String> responseLineStream = httpResponse.body();
CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> responseLineStream.count());
long count = future.get(3, TimeUnit.SECONDS);

或者仅仅是一个由Java Executor执行的Future

票数 6
EN

Stack Overflow用户

发布于 2021-06-04 20:05:04

解决这一问题的一种方法是在接收整个身体所需的时间上设置一个超时。这就是M A的解决方案。正如您已经注意到的,如果超时计算,您应该关闭流,这样连接就会正确地释放,而不是挂在后台。一种更普遍的方法是实现一个BodySubscriber,当它在超时时间内不被上游完成时,它会异常地完成它自己。这使得不必只为定时等待或关闭流而生成线程。下面是一个适当的实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class TimeoutBodySubscriber<T> implements BodySubscriber<T> {
  private final BodySubscriber<T> downstream;
  private final Duration timeout;
  private Subscription subscription;

  /** Make sure downstream isn't called after we receive an onComplete or onError. */
  private boolean done;

  TimeoutBodySubscriber(BodySubscriber<T> downstream, Duration timeout) {
    this.downstream = downstream;
    this.timeout = timeout;
  }

  @Override
  public CompletionStage<T> getBody() {
    return downstream.getBody();
  }

  @Override
  public synchronized void onSubscribe(Subscription subscription) {
    this.subscription = requireNonNull(subscription);
    downstream.onSubscribe(subscription);

    // Schedule an error completion to be fired when timeout evaluates
    CompletableFuture.delayedExecutor(timeout.toMillis(), TimeUnit.MILLISECONDS)
        .execute(this::onTimeout);
  }

  private synchronized void onTimeout() {
    if (!done) {
      done = true;
      downstream.onError(new HttpTimeoutException("body completion timed out"));

      // Cancel subscription to release the connection, so it doesn't keep hanging in background
      subscription.cancel();
    }
  }

  @Override
  public synchronized void onNext(List<ByteBuffer> item) {
    if (!done) {
      downstream.onNext(item);
    }
  }

  @Override
  public synchronized void onError(Throwable throwable) {
    if (!done) {
      done = true;
      downstream.onError(throwable);
    }
  }

  @Override
  public synchronized void onComplete() {
    if (!done) {
      done = true;
      downstream.onComplete();
    }
  }

  static <T> BodyHandler<T> withBodyTimeout(BodyHandler<T> handler, Duration timeout) {
    return responseInfo -> new TimeoutBodySubscriber<>(handler.apply(responseInfo), timeout);
  }
}

它可用于以下方面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Duration timeout = Duration.ofSeconds(10);
HttpResponse<Stream<String>> httpResponse = httpClient
        .send(httpRequest, TimeoutBodySubscriber.withTimeout(HttpResponse.BodyHandlers.ofLines(), timeout));

另一种方法是使用读取超时。这更灵活,因为只要服务器保持活动状态(即继续发送内容),响应就不会超时。如果在超时期间没有接收到下一个请求的信号,那么您需要一个BodySubscriber来完成自己的任务。这一点实现起来稍微复杂一些。如果依赖关系良好,可以使用甲醇。如所述,它实现了读取超时。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Duration timeout = Duration.ofSeconds(3);
HttpResponse<Stream<String>> httpResponse = httpClient
    .send(httpRequest, MoreBodyHandlers.withReadTimeout(HttpResponse.BodyHandlers.ofLines(), timeout));

另一种策略是将两者结合使用:当服务器变得不活跃或身体需要太长时间才能完成时,就立即超时。

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

https://stackoverflow.com/questions/67602169

复制
相关文章
[PHP] try catch在日常中的使用
2.finally是不管try或者catch任何一块有return, 最终都会执行的块
唯一Chat
2019/09/10
1.7K0
Try catch如何使用[通俗易懂]
浏览器的兼容性是程序员很头痛的事儿,往往一些出错会让我们查找许久,在使用try catch能更好的解决兼容性出错的问题:由于不同浏览器报错提示也不尽相同,通过使用try catch捕获的浏览器的报错提示,来判断用户使用的浏览器,然后做出对应的解决方法;那么,你如果用if,就只能反馈真或假,而不能直接抛出浏览器的报错内容。
全栈程序员站长
2022/08/31
1.8K0
try和catch的使用。
// 报错,a找不到,程序终止,不往下继续。 console.log(a) // 放在try里 try { // a不打印 console.log(a) }catch(e){ // e是错误信息 console.log(e) // 弹出123 alert("123") } // 如果放在try中 弹出2 // 否则终止 alert("2") // 使用 let 不变量提升 let a = 0 总结:在使用try和catch时,程序报错但依然可以向下进行(node中系统错误,因为不可预知,需要大量代码来cat
biaoblog.cn 个人博客
2022/08/11
1.8K0
try()catch{}写法
当生活像一首歌那样轻快流畅时,笑颜常开乃易事;而在一切事都不妙时仍能微笑的人,是真正的乐观。——威尔科克斯 曾经我们使用java的IO流复制文件时是这么写的 package com.ruben; import java.io.*; import java.util.Optional; /** * @ClassName: FileDemo * @Description: 我还没有写描述 * @Date: 2021/1/10 0010 21:38 * * * @author: <achao1
阿超
2022/08/16
1.3K0
try catch的作用
public static void main(String[] args) { int i; i = 2/0; System.out.println(i); System.out.println(1111111111);
全栈程序员站长
2022/09/07
1.4K0
如何使用 try-with-resources 代替try-catch-finally?
try-with-resources 是 Java 7 引入的一种语法结构,用于自动关闭实现了 AutoCloseable 接口的资源。它可以代替传统的 try-catch-finally 结构来处理资源的释放。
程序员朱永胜
2023/10/10
2.1K0
try-catch-finally
总结: 1、finally语句中没有return时,执行完try或catch语句的return之后还会执行finally。(而return的值会暂存在栈里面,等待finally执行后再返回) 2、finally语句中有return时,依然会执行try或catch语句的return,但是最终返回的是finally语句中的return。
用户9854323
2022/06/25
7890
SAP ABAP TRY CATCH
SAP 开发中会遇到两种系统异常,一种是基于异常类的异常,可以通过系统变量SY-SUBRC来进行判断;另外一种是非类异常,系统的异常,例如0作为除数的情况。
matinal
2023/10/13
2650
简单理解try catch和try finally
错误可能是语法错误,通常是程序员造成的编码错误或错别字。也可能是拼写错误或语言中缺少的功能。
PHP学习网
2022/08/03
1.1K0
try catch finally 用法[通俗易懂]
请问答案是:“return value of getValue():0 还是 return value of getValue():1”呢?
全栈程序员站长
2022/09/07
1.5K0
C# try catch finally
 catch 和 finally 一起使用的常见方式是:在 try 块中获取并使用资源,在 catch 块中处理异常情况,并在 finally 块中释放资源。
aehyok
2018/09/11
1.8K0
try catch 对性能影响
之前一直没有去研究try catch的内部机制,只是一直停留在了感觉上,正好这周五开会交流学习的时候,有人提出了相关的问题。借着周末,正好研究一番。
全栈程序员站长
2022/07/04
1.6K0
try catch 对性能影响
try catch finally 实现机制
try catch finally如何执行异常时跳转?finally 语句为何一定会执行?
Erossssssss
2021/04/09
2.5K0
try catch finally 实现机制
建议大型项目用上Try Catch建议大型项目用上Try Catch
我们在平时项目做功能的时候,经常会遇到崩溃的情况。如果是我们在开发测试阶段,我们可以找到原因修复。但是遇到已经上线,出现这种问题。要么使用JSPatch进行热修复,但是使用热修复修复苦只有写的人知道。
君赏
2018/08/31
8610
try-catch的性能分析
https://blog.csdn.net/lylwo317/article/details/51869893
葆宁
2019/04/18
1.8K0
try-catch的性能分析
捕获异常try…catch…finally
try:该代码块中编写可能产生异常的代码。 catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。 finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
秋白
2019/02/21
1.3K0
捕获异常try…catch…finally
Android 复习笔记(五)—— OutOfMemoryError 可以被 try catch 吗 ?
群里小伙伴碰到的一道比较经典的面试题,但我相信很多第一次碰到这个问题的同学应该无法立刻给出答案,最好的办法肯定还是动手测一测。
路遥TM
2021/08/31
5960
你还在使用 try-catch-finally 关闭资源?
作者:何甜甜在吗 链接:https://juejin.im/post/5b8f9fa05188255c6f1df755
Java技术栈
2020/07/03
8650
JavaScript 错误 - throw、try 和 catch
finally 语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行。
陈不成i
2021/07/19
1.1K0
try catch finally 执行顺序详解
关于try catch finally 执行顺序的笔试面试题目非常的多,我曾经在牛客网刷题的时候不止一次的碰到过,而且不止一次的做错过,这里面需要涉及的细节如果不弄清楚每次做题就会产生似是而非的感觉。这次查阅了很多相关资料,关于try catch finally 执行顺序各方面基本都讲到了。不足之处欢迎指出。
肉眼品世界
2021/08/09
6010

相似问题

避免嵌套的try/catch

31

Android上的Try and Catch问题

30

在FileWriter上使用try catch

26

如何避免使用try...catch块

52

Java --如何避免使用try catch语句

35
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文