java - 在 WebClient 中处理异常抛出 io.netty.handler.timeout.ReadTimeoutException
问题描述
所以我是响应式编程的新手,我写了一些我想测试的代码。这些更多是集成测试,因为我正在实时复制文件并稍后检查它们是否相同。我有一个MockWebServer
嘲笑我的回应4xx
是在代码中处理得很好。不幸的是,我也得到io.netty.handler.timeout.ReadTimeoutException
了掩盖我的习惯WebClientResponseException
,所以在测试中我得到了错误的异常。基本上我有两个问题,为什么我会得到这个io.netty.handler.timeout.ReadTimeoutException
例外?由于某种原因,它只出现在doOnError()
方法之后,我不确定它为什么会发生。
现在代码就在那里,而且它是同步的,我很清楚这一点。
第二个问题是,在给定次数的重试后,我如何处理测试中的自定义异常?现在它是 3,然后我才希望抛出我的另一个异常。
这是代码:
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(targetPath, StandardOpenOption.WRITE);
Flux<DataBuffer> fileDataStream = Mono.just(filePath)
.map(file -> targetPath.toFile().exists() ? targetPath.toFile().length() : 0)
.map(bytes -> webClient
.get()
.uri(uri)
.accept(MediaType.APPLICATION_OCTET_STREAM)
.header("Range", String.format("bytes=%d-", bytes))
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse -> Mono.error(new CustomException("4xx error")))
.onStatus(HttpStatus::is5xxServerError, clientResponse -> Mono.error(new CustomException("5xx error")))
.bodyToFlux(DataBuffer.class)
.doOnError(throwable -> log.info("fileDataStream onError", throwable))
)
.flatMapMany(Function.identity());
return DataBufferUtils
.write(fileDataStream, fileChannel)
.map(DataBufferUtils::release)
.doOnError(throwable -> {
try {
fileChannel.force(true);
} catch (IOException e) {
throw new WritingException("failed force update to file channel", e);
}
})
.retry(3)
.doOnComplete(() -> {
try {
fileChannel.force(true);
} catch (IOException e) {
log.warn("failed force update to file channel", e);
throw new WritingException("failed force update to file channel", e);
}
})
.doOnError(throwable -> targetPath.toFile().delete())
.then(Mono.just(target));
响应是Mono<Path>
因为我只Path
对新创建和复制的文件感兴趣。
欢迎任何关于代码的评论。
复制机制是基于此线程Downlolad 并使用 Project Reactor 中的 ExchangeFunction 从 ClientRequest 保存文件
解决方案
所以基本上问题出在测试中。我只有一次MockResponse
排队,MockWebServer
所以在WebClient
模拟服务器中重试时没有任何响应集(基本上它的行为就像它根本不可用,因为没有模拟响应)。
为了能够在服务器完全关闭的情况下处理异常,我认为值得在通量链中添加类似这样的行:
.doOnError(ChannelException.class, e -> {
throw new YourCustomExceptionForHandlingServerIsDownSituation("Server is unreachable", e);
})
这将帮助您ReadTimeoutException
从 Netty 处理(如果服务器无法访问),因为它扩展了ChannelException
类。始终处理您的异常。
推荐阅读
- python - 如何在没有目标值的数据集上使用决策树进行预测?
- python - 使用 PIL 库从 YCbCr 到 RGB 的色彩空间转换?
- ios - 使用 Swift 5.1 for iOS 中的 SwiftUI 使用 RadialGradient 填充动态大小的 Rectangle
- ruby-on-rails - Rails 5 yield 给出重复的内容
- python - 将python文件导入另一个python文件
- python - 使用 Python 和 Selenium 抓取 Instagram 上喜欢帖子的帐户的名称,但仅返回 11 个名称
- r - expss 包可以处理带有加权数据的多个答案问题吗?
- php - PHP 在 Heroku 上连接到 Postgres 时遇到问题
- jenkins - 在 Bash 脚本中,如何退出整个脚本并返回成功
- matlab - 如何使用 fzero() 在 MATLAB 中求解多项式方程?