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的時(shí)候執(zhí)行
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實(shí)現(xiàn)了IOExceptionFilter接口,它在asyncHandler是ResumableAsyncHandler類型的時(shí)候執(zhí)行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 Resumable if (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()的時(shí)候會重置byteTransferred,對于有range的header則重置其bytes參數(shù)值
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 changed if (fc.replayRequest()) { requestSender.replayRequest(future, fc, channel); return true; } return false; }
ResponseFiltersInterceptor的exitAfterProcessingFilters方法,對于fc.replayRequest()為true則執(zhí)行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方法會觸發(fā)future.getAsyncHandler().onRetry()回調(diào),然后執(zhí)行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(),然后挨個(gè)執(zhí)行fc = asyncFilter.filter(fc)
小結(jié)
AsyncHttpClient的IOExceptionFilter接口定義了filter方法,在捕獲到IOException的時(shí)候執(zhí)行;
ResumableIOExceptionFilter實(shí)現(xiàn)了IOExceptionFilter接口,它在asyncHandler是ResumableAsyncHandler類型的時(shí)候執(zhí)行adjustRequestRange方法獲取新的request,然后再通過new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build()返回;
NettyRequestSender的replayRequest方法會觸發(fā)future.getAsyncHandler().onRetry()回調(diào),然后執(zhí)行channelManager.drainChannelAndOffer(channel, future)及sendNextRequest。
以上就是AsyncHttpClient IOExceptionFilter異常過濾器的詳細(xì)內(nèi)容,更多關(guān)于AsyncHttpClient IOExceptionFilter的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring Security整合KeyCloak保護(hù)Rest API實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Spring Security整合KeyCloak保護(hù)Rest API實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Java?多線程并發(fā)?ReentrantReadWriteLock詳情
這篇文章主要介紹了Java多線程并發(fā)ReentrantReadWriteLock詳情,ReentrantReadWriteLock可重入讀寫鎖。實(shí)際使用場景中,我們需要處理的操作本質(zhì)上是讀與寫,更多相關(guān)資料,感興趣的小伙伴可以參考一下下面文章內(nèi)容2022-06-06使用jmx?exporter采集kafka指標(biāo)示例詳解
這篇文章主要為大家介紹了使用jmx?exporter采集kafka指標(biāo)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Java框架Struts2實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了Java框架Struts2實(shí)現(xiàn)圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08Java獲取時(shí)間差(天數(shù)差,小時(shí)差,分鐘差)代碼示例
這篇文章主要介紹了Java獲取時(shí)間差(天數(shù)差,小時(shí)差,分鐘差)代碼示例,使用SimpleDateFormat來實(shí)現(xiàn)的相關(guān)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11java 較大數(shù)據(jù)量取差集,list.removeAll性能優(yōu)化詳解
這篇文章主要介紹了java 較大數(shù)據(jù)量取差集,list.removeAll性能優(yōu)化詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09springBoot整合rabbitmq測試常用模型小結(jié)
這篇文章主要介紹了springBoot整合rabbitmq并測試五種常用模型,本文主要針對前五種常用模型,在spirngboot框架的基礎(chǔ)上整合rabbitmq并進(jìn)行測試使用,需要的朋友可以參考下2022-01-01