From 70c045e39d597dd093c82a42cd2cde05bd399f1b Mon Sep 17 00:00:00 2001 From: justforstudy <2167005981@qq.com> Date: Fri, 21 Oct 2022 19:45:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=93=8D=E5=BA=94=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=8B=A6=E6=88=AA=E7=82=B9=E4=BB=A5=E8=A7=84=E9=81=BF?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=8B=A6=E6=88=AA=E5=8E=9F=E7=94=9F=E7=B1=BB?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...pUrlConnectionResponseStreamDeclarer.java} | 10 ++--- ...lConnectionResponseStreamInterceptor.java} | 45 +++++++++++-------- ....core.plugin.agent.declarer.PluginDeclarer | 2 +- 3 files changed, 33 insertions(+), 24 deletions(-) rename sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/{HttpUrlConnectionResponseCodeDeclarer.java => HttpUrlConnectionResponseStreamDeclarer.java} (83%) rename sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/{HttpUrlConnectionResponseCodeInterceptor.java => HttpUrlConnectionResponseStreamInterceptor.java} (83%) diff --git a/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/HttpUrlConnectionResponseCodeDeclarer.java b/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/HttpUrlConnectionResponseStreamDeclarer.java similarity index 83% rename from sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/HttpUrlConnectionResponseCodeDeclarer.java rename to sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/HttpUrlConnectionResponseStreamDeclarer.java index 6861970050..d79c05f678 100644 --- a/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/HttpUrlConnectionResponseCodeDeclarer.java +++ b/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/declarers/httpconnection/HttpUrlConnectionResponseStreamDeclarer.java @@ -16,7 +16,7 @@ package com.huawei.discovery.declarers.httpconnection; -import com.huawei.discovery.interceptors.httpconnection.HttpUrlConnectionResponseCodeInterceptor; +import com.huawei.discovery.interceptors.httpconnection.HttpUrlConnectionResponseStreamInterceptor; import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; @@ -29,14 +29,14 @@ * @author zhouss * @since 2022-10-20 */ -public class HttpUrlConnectionResponseCodeDeclarer extends AbstractPluginDeclarer { - private static final String INTERCEPT_CLASS = HttpUrlConnectionResponseCodeInterceptor.class.getCanonicalName(); +public class HttpUrlConnectionResponseStreamDeclarer extends AbstractPluginDeclarer { + private static final String INTERCEPT_CLASS = HttpUrlConnectionResponseStreamInterceptor.class.getCanonicalName(); - private static final String METHOD_NAME = "getResponseCode"; + private static final String METHOD_NAME = "getInputStream"; @Override public ClassMatcher getClassMatcher() { - return ClassMatcher.nameEquals("java.net.HttpURLConnection"); + return ClassMatcher.isExtendedFrom("java.net.HttpURLConnection"); } @Override diff --git a/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/HttpUrlConnectionResponseCodeInterceptor.java b/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/HttpUrlConnectionResponseStreamInterceptor.java similarity index 83% rename from sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/HttpUrlConnectionResponseCodeInterceptor.java rename to sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/HttpUrlConnectionResponseStreamInterceptor.java index 0699c730d6..400b0201f8 100644 --- a/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/HttpUrlConnectionResponseCodeInterceptor.java +++ b/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/java/com/huawei/discovery/interceptors/httpconnection/HttpUrlConnectionResponseStreamInterceptor.java @@ -34,24 +34,27 @@ import sun.net.www.http.HttpClient; import sun.net.www.protocol.http.HttpURLConnection; +import java.io.Closeable; import java.io.IOException; import java.net.Proxy; import java.net.SocketTimeoutException; import java.net.URL; +import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; /** - * 拦截HttpUrlConnection#getResponseCode方法, 该拦截主要使之可检测到readTimeOut异常, connect timed out 见connect方法拦截点 + * 拦截HttpUrlConnection#getInputSteam方法, 该拦截主要使之可检测到readTimeOut异常, connect timed out 见connect方法拦截点 * * @author zhouss * @since 2022-10-20 */ -public class HttpUrlConnectionResponseCodeInterceptor implements Interceptor { +public class HttpUrlConnectionResponseStreamInterceptor implements Interceptor { private static final Logger LOGGER = LoggerFactory.getLogger(); private final LbConfig lbConfig; @@ -59,7 +62,7 @@ public class HttpUrlConnectionResponseCodeInterceptor implements Interceptor { /** * 构造器, 初始化配置 */ - public HttpUrlConnectionResponseCodeInterceptor() { + public HttpUrlConnectionResponseStreamInterceptor() { this.lbConfig = PluginConfigManager.getPluginConfig(LbConfig.class); } @@ -75,11 +78,13 @@ public ExecuteContext before(ExecuteContext context) throws Exception { final InvokerService invokerService = PluginServiceManager.getPluginService(InvokerService.class); final Function invokerContextObjectFunction = buildInvokerFunc(context, url, urlInfo); final InvokerContext invokerContext = new InvokerContext(); - final Object firstInvokeResult = invokerContextObjectFunction.apply(invokerContext); + final Object rawInputStream = invokerContextObjectFunction.apply(invokerContext); if (!isNeedRetry(invokerContext.getEx())) { - setResult(context, firstInvokeResult); return context; } + tryCloseOldInputStream(rawInputStream); + LOGGER.log(Level.FINE, String.format(Locale.ENGLISH, "invoke method [%s] failed", + context.getMethod().getName()), invokerContext.getEx()); Optional result = invokerService.invoke( invokerContextObjectFunction, ex -> ex, @@ -91,13 +96,21 @@ public ExecuteContext before(ExecuteContext context) throws Exception { context.setThrowableOut((Exception) obj); return context; } - - // 此处无需调用, 仅直接替换结果即可 - setResult(context, obj); } return context; } + private void tryCloseOldInputStream(Object rawInputStream) { + if (rawInputStream instanceof Closeable) { + // 针对旧的输入流进行关闭处理 + try { + ((Closeable) rawInputStream).close(); + } catch (IOException e) { + LOGGER.warning("Close old input stream failed when invoke"); + } + } + } + private boolean isNeedRetry(Throwable ex) { if (ex instanceof SocketTimeoutException) { // 此处仅SocketTimeoutException: Read timed out进行重试 @@ -107,24 +120,18 @@ private boolean isNeedRetry(Throwable ex) { return false; } - private void setResult(ExecuteContext context, Object result) { - ReflectUtils.setFieldValue(context.getObject(), "responseCode", result); - } - - private void resetResponseCode(ExecuteContext context) { - setResult(context, -1); - } - private void resetStats(ExecuteContext context) { - resetResponseCode(context); ReflectUtils.setFieldValue(context.getObject(), "rememberedException", null); ReflectUtils.setFieldValue(context.getObject(), "failedOnce", false); + ReflectUtils.setFieldValue(context.getObject(), "responseCode", -1); } private Function buildInvokerFunc(ExecuteContext context, URL url, Map urlInfo) { final AtomicBoolean isFirstInvoke = new AtomicBoolean(); + final AtomicReference lastResult = new AtomicReference<>(); return invokerContext -> { + tryCloseOldInputStream(lastResult.get()); if (!isFirstInvoke.get()) { isFirstInvoke.set(true); } else { @@ -135,7 +142,9 @@ private Function buildInvokerFunc(ExecuteContext context newUrl.ifPresent(value -> ReflectUtils.setFieldValue(context.getObject(), "url", value)); newUrl.ifPresent(value -> resetHttpClient(context.getObject(), value)); } - return RequestInterceptorUtils.buildFunc(context, invokerContext).get(); + final Object result = RequestInterceptorUtils.buildFunc(context, invokerContext).get(); + lastResult.set(result); + return result; }; } diff --git a/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer index 7d501dc130..90b177a4d9 100644 --- a/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer +++ b/sermant-plugins/sermant-springboot-registry/springboot-registry-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -24,5 +24,5 @@ com.huawei.discovery.declarers.OkHttp3ClientDeclarer com.huawei.discovery.declarers.SpringEnvironmentInfoDeclarer com.huawei.discovery.declarers.SpringBootDeclarer com.huawei.discovery.declarers.httpconnection.HttpUrlConnectionConnectDeclarer -com.huawei.discovery.declarers.httpconnection.HttpUrlConnectionResponseCodeDeclarer +com.huawei.discovery.declarers.httpconnection.HttpUrlConnectionResponseStreamDeclarer