Skip to content

Commit

Permalink
修改响应超时拦截点以规避无法拦截原生类的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
justforstudy-A committed Oct 21, 2022
1 parent 6257dc4 commit 70c045e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,35 @@
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;

/**
* 构造器, 初始化配置
*/
public HttpUrlConnectionResponseCodeInterceptor() {
public HttpUrlConnectionResponseStreamInterceptor() {
this.lbConfig = PluginConfigManager.getPluginConfig(LbConfig.class);
}

Expand All @@ -75,11 +78,13 @@ public ExecuteContext before(ExecuteContext context) throws Exception {
final InvokerService invokerService = PluginServiceManager.getPluginService(InvokerService.class);
final Function<InvokerContext, Object> 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<Object> result = invokerService.invoke(
invokerContextObjectFunction,
ex -> ex,
Expand All @@ -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进行重试
Expand All @@ -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<InvokerContext, Object> buildInvokerFunc(ExecuteContext context, URL url,
Map<String, String> urlInfo) {
final AtomicBoolean isFirstInvoke = new AtomicBoolean();
final AtomicReference<Object> lastResult = new AtomicReference<>();
return invokerContext -> {
tryCloseOldInputStream(lastResult.get());
if (!isFirstInvoke.get()) {
isFirstInvoke.set(true);
} else {
Expand All @@ -135,7 +142,9 @@ private Function<InvokerContext, Object> 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;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 70c045e

Please sign in to comment.