聊聊AsyncHttpClient的RequestFilter

本文主要研究一下AsyncHttpClient的RequestFilter

RequestFilter

org/asynchttpclient/filter/RequestFilter.java

/*** A Filter interface that gets invoked before making an actual request.*/
public interface RequestFilter {/*** An {@link org.asynchttpclient.AsyncHttpClient} will invoke {@link RequestFilter#filter} and will use the* returned {@link FilterContext#getRequest()} and {@link FilterContext#getAsyncHandler()} to continue the request* 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;
}

RequestFilter定义了filter方法

ThrottleRequestFilter

org/asynchttpclient/filter/ThrottleRequestFilter.java

/*** A {@link org.asynchttpclient.filter.RequestFilter} throttles requests and block when the number of permits is reached,* waiting for the response to arrives before executing the next request.*/
public class ThrottleRequestFilter implements RequestFilter {private static final Logger logger = LoggerFactory.getLogger(ThrottleRequestFilter.class);private final Semaphore available;private final int maxWait;public ThrottleRequestFilter(int maxConnections) {this(maxConnections, Integer.MAX_VALUE);}public ThrottleRequestFilter(int maxConnections, int maxWait) {this(maxConnections, maxWait, false);}public ThrottleRequestFilter(int maxConnections, int maxWait, boolean fair) {this.maxWait = maxWait;available = new Semaphore(maxConnections, fair);}/*** {@inheritDoc}*/@Overridepublic <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException {try {if (logger.isDebugEnabled()) {logger.debug("Current Throttling Status {}", available.availablePermits());}if (!available.tryAcquire(maxWait, TimeUnit.MILLISECONDS)) {throw new FilterException(String.format("No slot available for processing Request %s with AsyncHandler %s",ctx.getRequest(), ctx.getAsyncHandler()));}} catch (InterruptedException e) {throw new FilterException(String.format("Interrupted Request %s with AsyncHandler %s",ctx.getRequest(), ctx.getAsyncHandler()));}return new FilterContext.FilterContextBuilder<>(ctx).asyncHandler(ReleasePermitOnComplete.wrap(ctx.getAsyncHandler(), available)).build();}
}

ThrottleRequestFilter实现了RequestFilter接口,它使用Semaphore来对request进行限流,限流不通过抛出FilterException,若通过则通过ReleasePermitOnComplete.wrap(ctx.getAsyncHandler(), available)包装一下asyncHandler以释放信号量ReleasePermitOnComplete

ReleasePermitOnComplete

org/asynchttpclient/filter/ReleasePermitOnComplete.java

/*** Wrapper for {@link AsyncHandler}s to release a permit on {@link AsyncHandler#onCompleted()}. This is done via a dynamic proxy to preserve all interfaces of the wrapped handler.*/
public class ReleasePermitOnComplete {/*** Wrap handler to release the permit of the semaphore on {@link AsyncHandler#onCompleted()}.** @param handler   the handler to be wrapped* @param available the Semaphore to be released when the wrapped handler is completed* @param <T>       the handler result type* @return the wrapped handler*/@SuppressWarnings("unchecked")public static <T> AsyncHandler<T> wrap(final AsyncHandler<T> handler, final Semaphore available) {Class<?> handlerClass = handler.getClass();ClassLoader classLoader = handlerClass.getClassLoader();Class<?>[] interfaces = allInterfaces(handlerClass);return (AsyncHandler<T>) Proxy.newProxyInstance(classLoader, interfaces, (proxy, method, args) -> {try {return method.invoke(handler, args);} finally {switch (method.getName()) {case "onCompleted":case "onThrowable":available.release();default:}}});}//......
}  

ReleasePermitOnComplete的wrap对原来的handler进行代理,在finally里头执行available.release()

preProcessRequest

org/asynchttpclient/DefaultAsyncHttpClient.java

  /*** Configure and execute the associated {@link RequestFilter}. This class* may decorate the {@link Request} and {@link AsyncHandler}** @param fc {@link FilterContext}* @return {@link FilterContext}*/private <T> FilterContext<T> preProcessRequest(FilterContext<T> fc) throws FilterException {for (RequestFilter asyncFilter : config.getRequestFilters()) {fc = asyncFilter.filter(fc);assertNotNull(fc, "filterContext");}Request request = fc.getRequest();if (fc.getAsyncHandler() instanceof ResumableAsyncHandler) {request = ResumableAsyncHandler.class.cast(fc.getAsyncHandler()).adjustRequestRange(request);}if (request.getRangeOffset() != 0) {RequestBuilder builder = new RequestBuilder(request);builder.setHeader("Range", "bytes=" + request.getRangeOffset() + "-");request = builder.build();}fc = new FilterContext.FilterContextBuilder<>(fc).request(request).build();return fc;}

DefaultAsyncHttpClient的preProcessRequest方法遍历config.getRequestFilters(),挨个执行asyncFilter.filter(fc)

executeRequest

org/asynchttpclient/DefaultAsyncHttpClient.java

  public <T> ListenableFuture<T> executeRequest(Request request, AsyncHandler<T> handler) {if (config.getCookieStore() != null) {try {List<Cookie> cookies = config.getCookieStore().get(request.getUri());if (!cookies.isEmpty()) {RequestBuilder requestBuilder = new RequestBuilder(request);for (Cookie cookie : cookies) {requestBuilder.addOrReplaceCookie(cookie);}request = requestBuilder.build();}} catch (Exception e) {handler.onThrowable(e);return new ListenableFuture.CompletedFailure<>("Failed to set cookies of request", e);}}if (noRequestFilters) {return execute(request, handler);} else {FilterContext<T> fc = new FilterContext.FilterContextBuilder<T>().asyncHandler(handler).request(request).build();try {fc = preProcessRequest(fc);} catch (Exception e) {handler.onThrowable(e);return new ListenableFuture.CompletedFailure<>("preProcessRequest failed", e);}return execute(fc.getRequest(), fc.getAsyncHandler());}}

executeRequest方法对于noRequestFilters为false会执行preProcessRequest

小结

AsyncHttpClient的RequestFilter定义了filter方法,它有一个实现类为ThrottleRequestFilter,使用信号量用于对请求进行限流;DefaultAsyncHttpClient的executeRequest方法对于noRequestFilters为false会执行preProcessRequest,而preProcessRequest方法遍历config.getRequestFilters(),挨个执行asyncFilter.filter(fc)。

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

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

相关文章

HTML 字体样式

目录 使用属性样式使用 CSS 样式表HTML 中常用的字体样式属性总结 HTML 是一种用于创建网页的标记语言&#xff0c;开发者可以通过 HTML 编写网页结构和内容。在 HTML 中&#xff0c;字体样式是非常重要的&#xff0c;可以通过设置字体大小、字体颜色、字体样式等方式来让网页内…

力扣322. 零钱兑换

动态规划 思路&#xff1a; 假设 dp[i] 表示金额 i 的零钱兑换最小数量&#xff1b;它可以由 dp[i - C(j)] 1&#xff0c;即由币值C(j) 与 dp[i - C(j)] 组成&#xff0c;要使得数量最少&#xff0c;则 dp[i - C(j)] 最小&#xff1b;边界条件 dp[0] 0&#xff1b;自下而上分…

Android View闪烁动画AlphaAnimation,Kotlin

Android View闪烁动画AlphaAnimation&#xff0c;Kotlin private fun flickerAnimation(view: View?) {val animation: Animation AlphaAnimation(1f, 0f) //不透明到透明。animation.duration 500 // 1次过程时长。animation.interpolator LinearInterpolator() // 线性速…

Axure电商产品移动端交互原型,移动端高保真Axure原型图(RP源文件手机app界面UI设计模板)

本作品是一套 Axure8 高保真移动端电商APP产品原型模板&#xff0c;包含了用户中心、会员成长、优惠券、积分、互动社区、运营推广、内容推荐、商品展示、订单流程、订单管理、售后及服务等完整的电商体系功能架构和业务流程。 本模板由一百三十多个界面上千个交互元件及事件组…

android项目实战之编辑器图片上传预览

现状分析 项目的需求用到编辑器&#xff0c;编辑器中又可能用到图片上传功能。 实现方案 1. 增加依赖库&#xff0c;可以参考前面的几篇文章&#xff0c;都有描述。 2. 核心代码实现 PictureSelector.create(GoodItemContentFragment.this) .openGallery(SelectMimeType.…

如何在上架App之前设置证书并上传应用

App上架教程 在上架App之前想要进行真机测试的同学&#xff0c;请查看《iOS- 最全的真机测试教程》&#xff0c;里面包含如何让多台电脑同时上架App和真机调试。 P12文件的使用详解 注意&#xff1a; 同样可以在Build Setting 的sign中设置证书&#xff0c;但是有点麻烦&…

Python查找列表中不重复的数字

Python每日一练 文章目录 Python每日一练问题&#xff1a;函数输入函数输出 代码实现示例输入&#xff1a;示例输出&#xff1a; 总结 问题&#xff1a; 编写一个程序来查找列表中不重复的数字。 定义函数find_unique()&#xff0c;它接受一个列表作为参数。 在函数内部&…

Log4j.xml配置说明

介绍 Log4j 2 是一款广泛使用的 Java 日志框架&#xff0c;它支持多种日志级别、异步日志、过滤器等功能&#xff0c;并且具有高性能和可扩展性。以下是 Log4j 2 的详细配置说明&#xff1a; 配置文件名称和存放位置&#xff1a;Log4j 2 的配置文件名可以是任意有效的文件名&a…

微信小程序:上传图片到别的域名文件下

效果 wxml <!-- 上传照片 --> <view class"addbtn"><view classpic name"fault_photo" wx:for"{{imgs}}" wx:for-item"item" wx:key"*this"><image classweui-uploader_img src"{{item}}"…

Kafka-客户端使用

理解Kafka正确使用方式 Kafka提供了两套客户端API&#xff0c;HighLevel API和LowLevel API。 HighLevel API封装了kafka的运行细节&#xff0c;使用起来比较简单&#xff0c;是企业开发过程中最常用的客户端API。 LowLevel API则需要客户端自己管理Kafka的运行细节&#xf…

使用spring-boot-devtools时可能会引起缓存实体转换异常

多次访问API接口时&#xff0c;会报底层实体转换异常排查&#xff0c; 排查自己写的代码&#xff0c;及使用的框架&#xff0c; 最终发现是引用了 热部署插件引起&#xff0c;关闭了插件无影响&#xff1b; 使用spring-boot-devtools时&#xff0c;需要注意这个问题了。 <…

得帆云为玉柴打造CRM售后服务管理系统,实现服务全过程管理|基于得帆云低代码的CRM案例系列

广西玉柴机器股份有限公司 广西玉柴机器股份有限公司始建于1992年&#xff0c;是国内行业首家赴境外上市的中外合资企业&#xff0c;产品远销亚欧美非等180多个国家和地区。公司总部设在广西玉林市&#xff0c;下辖11家子公司&#xff0c;生产基地布局广西、江苏、安徽、山东等…

交友系统:打造独具魅力的社交平台!APP小程序H5三端源码交付,支持二开!

随着社交媒体的兴起&#xff0c;交友系统成为了现代社会不可或缺的一部分。人们希望通过网络结识新朋友&#xff0c;拓展社交圈&#xff0c;寻找志同道合的伙伴&#xff0c;甚至找到自己的爱情。本文将为您介绍交友系统的定义、功能以及如何打造一个独具魅力的社交平台。 一个成…

类加载机制与反射

类加载机制与反射 一.虚拟机类加载机制 1.虚拟机类加载机制概述 虚拟机把描述类的数据从class文件加载到内存 将类的数据进行校验,转换解析和初始化 形成可以被java虚拟机直接使用的java类型 2.类加载过程 当程序要使用某个类时,如果该类还未被加载到内存中,系统会通过加…

Git 常用命令速查

一、 Git 常用命令速查 git branch 查看本地所有分支git status 查看当前状态git commit 提交git branch -a 查看所有的分支git branch -r 查看远程所有分支git commit -am "init" 提交并且加注释git remote add origin git192.168.1.119:ndshowgit push origin mas…

ogre3d 资料

官网 https://www.ogre3d.org/ 主页 https://wiki.ogre3d.org/Home Manual https://ogrecave.github.io/ogre/api/latest/manual.html#SEC_Contents API https://www.ogre3d.org/docs/api/1.9/ https://ogrecave.github.io/ogre/api/latest/ SDK http://www.ogre3d.org/dow…

centos卸载mysql库全流程

&#xff08;1&#xff09;暂停服务 systemctl stop mysqld &#xff08;2&#xff09;查看所有的安装包&#xff0c;将其卸载 rpm -qa |grep mysql rpm -q ( or --query) options -a 查询所有安装的软件包 &#xff08;3&#xff09;使用yum卸载安装的mysql [rootbo /…

c# 利用ContainsKey方法判断Dictionary中是否包含某个键

.NET Framework : 4.7.2IDE : Visual Studio Community 2022OS : Windows 10 x64typesetting : Markdownblog : niaoge.blog.csdn.net ContainsKey的定义 命名空间: System.Collections.Generic 程序集: System.Collections.dll 原型 public bool ContainsKey (TKey key); 确…

科研论文中PPT图片格式选择与转换:EPS、SVG 和 PDF 的比较

当涉及论文中的图片格式时&#xff0c;导师可能要求使用 EPS 格式的图片。EPS&#xff08;Encapsulated PostScript&#xff09;是一种矢量图格式&#xff0c;它以 PostScript 语言描述图像&#xff0c;能够无损地缩放并保持图像清晰度。与像素图像格式&#xff08;如 PNG 和 J…

Qt搭建MQTT编程环境

QT 部署官方MQTT模块 在Qt Creator中&#xff0c;默认是没有部署Mqtt模块的&#xff0c;在使用QT编程之前&#xff0c;先把mqtt 模块部署到开发环境当中。参考博文&#xff1a;Qt开发技术&#xff1a;mqtt介绍、QtMqtt编译和开发环境搭建_长沙红胖子-CSDN博客 下载 Qt官方在g…