聊聊AsyncHttpClient的IOExceptionFilter

本文主要研究一下AsyncHttpClient的IOExceptionFilter

IOExceptionFilter

org/asynchttpclient/filter/IOExceptionFilter.java

/*** This filter is invoked when an {@link java.io.IOException} occurs during an http transaction.*/
public interface IOExceptionFilter {/*** An {@link org.asynchttpclient.AsyncHttpClient} will invoke {@link IOExceptionFilter#filter} and will* use the returned {@link FilterContext} to replay the {@link org.asynchttpclient.Request} or abort the processing.** @param ctx a {@link FilterContext}* @param <T> the handler result type* @return {@link FilterContext}. The {@link FilterContext} instance may not the same as the original one.* @throws FilterException to interrupt the filter processing.*/<T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException;
}

IOExceptionFilter接口定义了filter方法,在捕获到IOException的时候执行

ResumableIOExceptionFilter

org/asynchttpclient/handler/resumable/ResumableIOExceptionFilter.java

/*** Simple {@link org.asynchttpclient.filter.IOExceptionFilter} that replay the current {@link org.asynchttpclient.Request} using a {@link ResumableAsyncHandler}*/
public class ResumableIOExceptionFilter implements IOExceptionFilter {public <T> FilterContext<T> filter(FilterContext<T> ctx) {if (ctx.getIOException() != null && ctx.getAsyncHandler() instanceof ResumableAsyncHandler) {Request request = ResumableAsyncHandler.class.cast(ctx.getAsyncHandler()).adjustRequestRange(ctx.getRequest());return new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build();}return ctx;}
}

ResumableIOExceptionFilter实现了IOExceptionFilter接口,它在asyncHandler是ResumableAsyncHandler类型的时候执行adjustRequestRange方法获取新的request,然后再通过new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build()返回

ResumableAsyncHandler

org/asynchttpclient/handler/resumable/ResumableAsyncHandler.java

  /*** Invoke this API if you want to set the Range header on your {@link Request} based on the last valid bytes* position.** @param request {@link Request}* @return a {@link Request} with the Range header properly set.*/public Request adjustRequestRange(Request request) {Long ri = resumableIndex.get(request.getUrl());if (ri != null) {byteTransferred.set(ri);}// The Resumableif (resumableListener != null && resumableListener.length() > 0 && byteTransferred.get() != resumableListener.length()) {byteTransferred.set(resumableListener.length());}RequestBuilder builder = new RequestBuilder(request);if (request.getHeaders().get(RANGE) == null && byteTransferred.get() != 0) {builder.setHeader(RANGE, "bytes=" + byteTransferred.get() + "-");}return builder.build();}

adjustRequestRange方法在byteTransferred不等于resumableListener.length()的时候会重置byteTransferred,对于有range的header则重置其bytes参数值

ResponseFiltersInterceptor

org/asynchttpclient/netty/handler/intercept/ResponseFiltersInterceptor.java

  public boolean exitAfterProcessingFilters(Channel channel,NettyResponseFuture<?> future,AsyncHandler<?> handler,HttpResponseStatus status,HttpHeaders responseHeaders) {FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(handler).request(future.getCurrentRequest()).responseStatus(status).responseHeaders(responseHeaders).build();for (ResponseFilter asyncFilter : config.getResponseFilters()) {try {fc = asyncFilter.filter(fc);// FIXME Is it worth protecting against this?assertNotNull("fc", "filterContext");} catch (FilterException efe) {requestSender.abort(channel, future, efe);}}// The handler may have been wrapped.future.setAsyncHandler(fc.getAsyncHandler());// The request has changedif (fc.replayRequest()) {requestSender.replayRequest(future, fc, channel);return true;}return false;}

ResponseFiltersInterceptor的exitAfterProcessingFilters方法,对于fc.replayRequest()为true则执行requestSender.replayRequest(future, fc, channel)

replayRequest

org/asynchttpclient/netty/request/NettyRequestSender.java

  public void replayRequest(final NettyResponseFuture<?> future, FilterContext fc, Channel channel) {Request newRequest = fc.getRequest();future.setAsyncHandler(fc.getAsyncHandler());future.setChannelState(ChannelState.NEW);future.touch();LOGGER.debug("\n\nReplaying Request {}\n for Future {}\n", newRequest, future);try {future.getAsyncHandler().onRetry();} catch (Exception e) {LOGGER.error("onRetry crashed", e);abort(channel, future, e);return;}channelManager.drainChannelAndOffer(channel, future);sendNextRequest(newRequest, future);}

NettyRequestSender的replayRequest方法会触发future.getAsyncHandler().onRetry()回调,然后执行channelManager.drainChannelAndOffer(channel, future)及sendNextRequest

applyIoExceptionFiltersAndReplayRequest

org/asynchttpclient/netty/request/NettyRequestSender.java

  public boolean applyIoExceptionFiltersAndReplayRequest(NettyResponseFuture<?> future, IOException e,Channel channel) {boolean replayed = false;@SuppressWarnings({"unchecked", "rawtypes"})FilterContext<?> fc = new FilterContext.FilterContextBuilder().asyncHandler(future.getAsyncHandler()).request(future.getCurrentRequest()).ioException(e).build();for (IOExceptionFilter asyncFilter : config.getIoExceptionFilters()) {try {fc = asyncFilter.filter(fc);assertNotNull(fc, "filterContext");} catch (FilterException efe) {abort(channel, future, efe);}}if (fc.replayRequest() && future.incrementRetryAndCheck() && future.isReplayPossible()) {future.setKeepAlive(false);replayRequest(future, fc, channel);replayed = true;}return replayed;}

NettyRequestSender的applyIoExceptionFiltersAndReplayRequest方法会遍历config.getIoExceptionFilters(),然后挨个执行fc = asyncFilter.filter(fc)

小结

AsyncHttpClient的IOExceptionFilter接口定义了filter方法,在捕获到IOException的时候执行;ResumableIOExceptionFilter实现了IOExceptionFilter接口,它在asyncHandler是ResumableAsyncHandler类型的时候执行adjustRequestRange方法获取新的request,然后再通过new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build()返回;NettyRequestSender的replayRequest方法会触发future.getAsyncHandler().onRetry()回调,然后执行channelManager.drainChannelAndOffer(channel, future)及sendNextRequest。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217836.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

都是星光赶路人

不知不觉已经快工作五年了&#xff0c;工作以后就感觉时间一年比一年快&#xff0c;仿佛昨天才刚毕业&#xff0c;就像陈鸿宇歌中的那样&#xff0c;多少遗憾自负存念想&#xff0c;唯有时间不可挡。五年&#xff0c;思考了很多&#xff0c;也想明白了许多。正好借着年末&#…

STM32 MCU的易坑点收集

IIC配置中的Clock No Stretch Mode Clock Stretch Mode时钟延长模式&#xff1a; 时钟延长是一个术语&#xff0c;某些从设备可以把时钟线拉低&#xff0c;主设备发现自己释放时钟线之后时钟线还没有变成高电平&#xff0c;就会停止发送数据&#xff0c;然后等待从设备释放时钟…

Angular+Nginx区域HIS医院信息管理系统源码

医院管理信息系统&#xff08;HIS&#xff09;是医院基本、重要的管理系统&#xff0c;是医院大数据的基础。“云”指系统采用云计算的技术和建设模式&#xff0c;具有可扩展、易共享、区域化、易协同、低成本、易维护、体验好的优势。“H”是医疗卫生&#xff0c;由原来医院 (…

利用transition-group标签包裹li标签,实现输入数据后按Enter键将数据添加到列表中

1.效果图 2.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><script src"https://cdn.bootcdn.net/ajax/libs/vue/2.3.0/vue.js"></script><div id&quo…

免费实用的API接口集合

IP归属地-IPv4区县级&#xff1a;根据IP地址查询归属地信息&#xff0c;包含43亿全量IPv4&#xff0c;支持到中国地区&#xff08;不含港台地区&#xff09;区县级别&#xff0c;含运营商数据。IP归属地-IPv4城市级&#xff1a;根据IP地址查询归属地信息&#xff0c;支持到城市…

CLEAR MOT评估指标

错误正样本&#xff08;False Positive&#xff0c;FP&#xff09;&#xff1a;整个视频中被预测为正的负样本数。 错误负样本&#xff08;False Negatives&#xff0c;FN&#xff09;&#xff1a;整个视频中被预测为负的正样本数。 IDs&#xff1a;跟踪过程中目标ID切换总数。…

Angular13无法在浏览器debug

前言 本文将介绍如何解决在Angular 13中无法在浏览器中进行调试的问题&#xff0c;并提供了一种解决方法。 发生场景 根据项目需求&#xff0c;升级至Angular 13后&#xff0c;发现无法在浏览器中进行调试。 问题原因 无法进行调试的原因是&#xff0c;当使用Angular 13的…

QT----第三天,Visio stdio自定义封装控件

目录 第三天1 自定义控件封装 源码&#xff1a;CPP学习代码 第三天 1 自定义控件封装 新建一个QT widgetclass&#xff0c;同时生成ui,h,cpp文件 在smallWidget.ui里添加上你想要的控件并调试大小 回到mainwidget.ui&#xff0c;拖入一个widget&#xff08;因为我们封装的也…

二分查找26(Leetcode528按权重随机选择)

代码&#xff1a; 看不懂题 看了题解才懂题是什么意思.. 二分查找完结撒花&#xff01;&#x1f389; class Solution {int[] pre;int total;public Solution(int[] w) {int n w.length;total Arrays.stream(w).sum();pre new int[n];pre[0] w[0];for(int i1;i<n;i){…

Single Thread Execution设计模式

Single Thread Execution模式是指在同一时刻只能有一个线程去访问共享资源&#xff0c;即采用排他方式的操作保证在同一个时刻只能有一个线程访问共享 资源。线程安全类是指多个线程在对某个类的实例同时进行操作时&#xff0c;不会引起数据的不一致问题。反之&#xff0c;就是…

【送书活动】探究AIGC、AGI、GPT和人工智能大模型

文章目录 前言01 《ChatGPT 驱动软件开发》推荐语 02 《ChatGPT原理与实战》推荐语 03 《神经网络与深度学习》推荐语 04 《AIGC重塑教育》推荐语 05 《通用人工智能》推荐语 后记赠书活动 前言 人工智能技术在过去几年中发展迅猛&#xff0c;得益于大数据、云计算、深度学习等…

C++1114新标准——统一初始化(Uniform Initialization)、Initializer_list(初始化列表)、explicit

系列文章目录 C11&14新标准——Variadic templates&#xff08;数量不定的模板参数&#xff09; C11&14新标准——Uniform Initialization&#xff08;统一初始化&#xff09;、Initializer_list&#xff08;初始化列表&#xff09;、explicit 文章目录 系列文章目录1…

TiDB 7.5 LTS 发版丨提升规模化场景下关键应用的稳定性和成本的灵活性

作者&#xff1a; TiDB社区小助手 原文来源&#xff1a; https://tidb.net/blog/1cffec89 互联网时代&#xff0c;数据的迅猛增长给数据库带来了可扩展性的挑战&#xff0c;Gen AI 带来的数据暴增更加剧了这种挑战。传统的数据分片已经不能承载新时代数据暴增的需求&#xf…

UE4 Niagara学习笔记

需要在其他发射器的同一个粒子位置发射其他粒子就用Spawn Particles from other Emitter 把发射器名字填上去即可 这里Move to Nearest Distance Field Subface GPU&#xff0c;可以将生成的Niagara附着到最近的物体上 使用场景就是做的火苗附着到物体上

【每日一题】2697. 字典序最小回文串-2023.12.13

题目&#xff1a; 2697. 字典序最小回文串 给你一个由 小写英文字母 组成的字符串 s &#xff0c;你可以对其执行一些操作。在一步操作中&#xff0c;你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 &#xff0c;使 s 变成一个 回文串 。如果执行…

Python和Beautiful Soup爬虫助力提取文本内容

大家好&#xff0c;网络爬虫是一项非常抢手的技能&#xff0c;收集、分析和清洗数据是数据科学项目中最重要的部分。今天介绍如何从链接中爬取高质量文本内容&#xff0c;我们使用迭代&#xff0c;从大约700个链接中进行网络爬取。如果想直接跳转到代码部分&#xff0c;可以在下…

【图像拼接】论文精读:Natural Image Stitching With Layered Warping Constraint

第一次来请先看这篇文章:【图像拼接(Image Stitching)】关于【图像拼接论文精读】专栏的相关说明,包含专栏使用说明、创新思路分享等(不定期更新) 图像拼接系列相关论文精读 Seam Carving for Content-Aware Image ResizingAs-Rigid-As-Possible Shape ManipulationAdap…

Java面试整理(四)-JVM类加载机制(中)

Java虚拟机(JVM)的类加载机制是Java平台的核心组件之一,它负责加载、链接、初始化类和接口。这个机制涉及几个关键的步骤和组件: 类加载器(Class Loaders):引导类加载器(Bootstrap Class Loader):这是JVM的一部分,用于加载JDK内部类和其他核心库。通常,这个类加载器…

Java版本+鸿鹄企业电子招投标系统源代码+支持二开+Spring cloud +鸿鹄电子招投标系统

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。为了符合国家电子招投标法律法规及相关规范&#xff0c;…

2697. 字典序最小回文串(2023-12-13)

力扣每日一题 题目&#xff1a;2697. 字典序最小回文串 日期&#xff1a;2023-12-13 用时&#xff1a;4 m 53 s 时间&#xff1a;7ms 内存&#xff1a;43.61MB 代码&#xff1a; class Solution {public String makeSmallestPalindrome(String s) {char[] chs s.toCharArray…