Skip to content

Commit

Permalink
*router piugin support springboot3
Browse files Browse the repository at this point in the history
Signed-off-by: provenceee <[email protected]>
  • Loading branch information
provenceee committed Nov 15, 2024
1 parent 8812773 commit 6a4facd
Show file tree
Hide file tree
Showing 24 changed files with 519 additions and 534 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,23 @@

import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.utils.LogUtils;
import io.sermant.core.utils.ReflectUtils;
import io.sermant.flowcontrol.common.config.ConfigConst;
import io.sermant.flowcontrol.common.entity.FlowControlResult;
import io.sermant.flowcontrol.common.entity.HttpRequestEntity;
import io.sermant.flowcontrol.common.entity.RequestEntity.RequestType;
import io.sermant.flowcontrol.service.InterceptorSupporter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -42,6 +48,28 @@
public class DispatcherServletInterceptor extends InterceptorSupporter {
private final String className = DispatcherServletInterceptor.class.getName();

private Function<Object, String> getRequestUri;

private Function<Object, String> getPathInfo;

private Function<Object, String> getMethod;

private Function<Object, Enumeration<String>> getHeaderNames;

private BiFunction<Object, String, String> getHeader;

private Function<Object, PrintWriter> getWriter;

private BiConsumer<Object, Integer> setStatus;

/**
* 构造方法
*/
public DispatcherServletInterceptor() {
super();
initFunction();
}

/**
* http request data conversion adapts to plugin -> service data transfer Note that this method is not
* extractable,Because host dependencies can only be loaded by this interceptor, pulling out results in classes not
Expand All @@ -50,18 +78,18 @@ public class DispatcherServletInterceptor extends InterceptorSupporter {
* @param request request
* @return HttpRequestEntity
*/
private Optional<HttpRequestEntity> convertToHttpEntity(HttpServletRequest request) {
private Optional<HttpRequestEntity> convertToHttpEntity(Object request) {
if (request == null) {
return Optional.empty();
}
String uri = request.getRequestURI();
String uri = getRequestUri.apply(request);
return Optional.of(new HttpRequestEntity.Builder()
.setRequestType(RequestType.SERVER)
.setPathInfo(request.getPathInfo())
.setPathInfo(getPathInfo.apply(request))
.setServletPath(uri)
.setHeaders(getHeaders(request))
.setMethod(request.getMethod())
.setServiceName(request.getHeader(ConfigConst.FLOW_REMOTE_SERVICE_NAME_HEADER_KEY))
.setMethod(getMethod.apply(request))
.setServiceName(getHeader.apply(request, ConfigConst.FLOW_REMOTE_SERVICE_NAME_HEADER_KEY))
.build());
}

Expand All @@ -71,12 +99,12 @@ private Optional<HttpRequestEntity> convertToHttpEntity(HttpServletRequest reque
* @param request request information
* @return headers
*/
private Map<String, String> getHeaders(HttpServletRequest request) {
final Enumeration<String> headerNames = request.getHeaderNames();
private Map<String, String> getHeaders(Object request) {
final Enumeration<String> headerNames = getHeaderNames.apply(request);
final Map<String, String> headers = new HashMap<>();
while (headerNames.hasMoreElements()) {
final String headerName = headerNames.nextElement();
headers.put(headerName, request.getHeader(headerName));
headers.put(headerName, getHeader.apply(request, headerName));
}
return Collections.unmodifiableMap(headers);
}
Expand All @@ -85,19 +113,19 @@ private Map<String, String> getHeaders(HttpServletRequest request) {
protected final ExecuteContext doBefore(ExecuteContext context) throws Exception {
LogUtils.printHttpRequestBeforePoint(context);
final Object[] allArguments = context.getArguments();
final HttpServletRequest argument = (HttpServletRequest) allArguments[0];
final Object request = allArguments[0];
final FlowControlResult result = new FlowControlResult();
final Optional<HttpRequestEntity> httpRequestEntity = convertToHttpEntity(argument);
final Optional<HttpRequestEntity> httpRequestEntity = convertToHttpEntity(request);
if (!httpRequestEntity.isPresent()) {
return context;
}
chooseHttpService().onBefore(className, httpRequestEntity.get(), result);
if (result.isSkip()) {
context.skip(null);
final HttpServletResponse response = (HttpServletResponse) allArguments[1];
final Object response = allArguments[1];
if (response != null) {
response.setStatus(result.getResponse().getCode());
response.getWriter().print(result.buildResponseMsg());
setStatus.accept(response, result.getResponse().getCode());
getWriter.apply(response).print(result.buildResponseMsg());
}
}
return context;
Expand All @@ -116,4 +144,75 @@ protected final ExecuteContext doThrow(ExecuteContext context) {
LogUtils.printHttpRequestOnThrowPoint(context);
return context;
}

private String getRequestUri(Object httpServletRequest) {
return getString(httpServletRequest, "getRequestURI");
}

private String getPathInfo(Object httpServletRequest) {
return getString(httpServletRequest, "getPathInfo");
}

private String getMethod(Object httpServletRequest) {
return getString(httpServletRequest, "getMethod");
}

private Enumeration<String> getHeaderNames(Object httpServletRequest) {
return (Enumeration<String>) ReflectUtils.invokeMethodWithNoneParameter(httpServletRequest, "getHeaderNames")
.orElse(null);
}

private String getHeader(Object httpServletRequest, String key) {
return (String) ReflectUtils.invokeMethod(httpServletRequest, "getHeader", new Class[]{String.class},
new Object[]{key}).orElse(null);
}

private PrintWriter getWriter(Object httpServletRequest) {
return (PrintWriter) ReflectUtils.invokeMethodWithNoneParameter(httpServletRequest, "getWriter")
.orElse(null);
}

private void setStatus(Object httpServletResponse, int code) {
ReflectUtils.invokeMethod(httpServletResponse, "setStatus", new Class[]{int.class}, new Object[]{code});
}

private String getString(Object object, String method) {
return (String) ReflectUtils.invokeMethodWithNoneParameter(object, method).orElse(null);
}

private void initFunction() {
boolean canLoadLowVersion = canLoadLowVersion();
if (canLoadLowVersion) {
getRequestUri = obj -> ((HttpServletRequest) obj).getRequestURI();
getPathInfo = obj -> ((HttpServletRequest) obj).getPathInfo();
getMethod = obj -> ((HttpServletRequest) obj).getMethod();
getHeaderNames = obj -> ((HttpServletRequest) obj).getHeaderNames();
getHeader = (obj, key) -> ((HttpServletRequest) obj).getHeader(key);
getWriter = obj -> {
try {
return ((HttpServletResponse) obj).getWriter();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
};
setStatus = (obj, code) -> ((HttpServletResponse) obj).setStatus(code);
} else {
getRequestUri = this::getRequestUri;
getPathInfo = this::getPathInfo;
getMethod = this::getMethod;
getHeaderNames = this::getHeaderNames;
getHeader = this::getHeader;
getWriter = this::getWriter;
setStatus = this::setStatus;
}
}

private boolean canLoadLowVersion() {
try {
Class.forName(HttpServletRequest.class.getCanonicalName());
} catch (NoClassDefFoundError | ClassNotFoundException error) {
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.plugin.agent.interceptor.AbstractInterceptor;
import io.sermant.core.utils.LogUtils;
import io.sermant.core.utils.ReflectUtils;
import io.sermant.monitor.common.MetricCalEntity;
import io.sermant.monitor.util.MonitorCacheUtil;

import java.util.function.Function;

import javax.servlet.http.HttpServletRequest;

/**
Expand All @@ -34,6 +37,15 @@
public class DispatcherServletInterceptor extends AbstractInterceptor {
private static final String START_TIME = "startTime";

private Function<Object, String> getRequestUri;

/**
* 构造方法
*/
public DispatcherServletInterceptor() {
initFunction();
}

@Override
public ExecuteContext before(ExecuteContext context) {
LogUtils.printHttpRequestBeforePoint(context);
Expand All @@ -50,7 +62,7 @@ public ExecuteContext after(ExecuteContext context) {
LogUtils.printHttpRequestAfterPoint(context);
return context;
}
String uri = ((HttpServletRequest) context.getArguments()[0]).getRequestURI();
String uri = getRequestUri.apply(context.getArguments()[0]);
MetricCalEntity metricCalEntity = MonitorCacheUtil.getMetricCalEntity(uri);
metricCalEntity.getReqNum().incrementAndGet();
long startTime = (Long) context.getExtMemberFieldValue(START_TIME);
Expand All @@ -70,11 +82,33 @@ public ExecuteContext onThrow(ExecuteContext context) {
LogUtils.printHttpRequestOnThrowPoint(context);
return context;
}
String uri = ((HttpServletRequest) context.getArguments()[0]).getRequestURI();
String uri = getRequestUri.apply(context.getArguments()[0]);
MetricCalEntity metricCalEntity = MonitorCacheUtil.getMetricCalEntity(uri);
metricCalEntity.getReqNum().incrementAndGet();
metricCalEntity.getFailedReqNum().incrementAndGet();
LogUtils.printHttpRequestOnThrowPoint(context);
return context;
}

private String getRequestUri(Object httpServletRequest) {
return (String) ReflectUtils.invokeMethodWithNoneParameter(httpServletRequest, "getRequestURI").orElse(null);
}

private void initFunction() {
boolean canLoadLowVersion = canLoadLowVersion();
if (canLoadLowVersion) {
getRequestUri = obj -> ((HttpServletRequest) obj).getRequestURI();
} else {
getRequestUri = this::getRequestUri;
}
}

private boolean canLoadLowVersion() {
try {
Class.forName(HttpServletRequest.class.getCanonicalName());
} catch (NoClassDefFoundError | ClassNotFoundException error) {
return false;
}
return true;
}
}
12 changes: 0 additions & 12 deletions sermant-plugins/sermant-router/spring-router-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@
<version>${jakarta.el.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
Expand All @@ -79,12 +73,6 @@
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,23 +19,23 @@
import io.sermant.core.plugin.agent.matcher.ClassMatcher;

/**
* Add an injection interceptor by intercepting and inject a spring web interceptor
* get http request data
*
* @author provenceee
* @since 2022-07-12
*/
public class HandlerExecutionChainDeclarer extends AbstractDeclarer {
private static final String ENHANCE_CLASS = "org.springframework.web.servlet.HandlerExecutionChain";
public class DispatcherServletDeclarer extends AbstractDeclarer {
private static final String ENHANCE_CLASS = "org.springframework.web.servlet.DispatcherServlet";

private static final String INTERCEPT_CLASS
= "io.sermant.router.spring.interceptor.HandlerExecutionChainInterceptor";
= "io.sermant.router.spring.interceptor.DispatcherServletInterceptor";

private static final String METHOD_NAME = "applyPreHandle";
private static final String METHOD_NAME = "doService";

/**
* Constructor
*/
public HandlerExecutionChainDeclarer() {
public DispatcherServletDeclarer() {
super(ENHANCE_CLASS, INTERCEPT_CLASS, METHOD_NAME);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public ExecuteContext before(ExecuteContext context) {
Object serviceName = ReflectUtils.getFieldValue(obj, "serviceName").orElse(null);
if (serviceName instanceof String) {
AppCache.INSTANCE.setAppName((String) serviceName);
configService.init(RouterConstant.SPRING_CACHE_NAME, AppCache.INSTANCE.getAppName());
} else {
LOGGER.warning("Service name is null or not instanceof string.");
}
Expand All @@ -69,7 +70,6 @@ public ExecuteContext before(ExecuteContext context) {

@Override
public ExecuteContext after(ExecuteContext context) {
configService.init(RouterConstant.SPRING_CACHE_NAME, AppCache.INSTANCE.getAppName());
return context;
}
}
Loading

0 comments on commit 6a4facd

Please sign in to comment.