提交 19b37cab 编写于 作者: 于玉桔 提交者: wu-sheng

Optimize spring cloud gateway in concurrent scenes with asyncSpan api (#3265)

* update gateway
上级 ffe1df57
......@@ -15,17 +15,20 @@
* limitations under the License.
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context.Constants;
public class DefaultHttpHeadersInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
if (ContextManager.isActive()) {
objInst.setSkyWalkingDynamicField(ContextManager.capture());
Object transmitter = ContextManager.getRuntimeContext().get(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER);
if (transmitter != null) {
objInst.setSkyWalkingDynamicField(transmitter);
ContextManager.getRuntimeContext().remove(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER);
}
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
......@@ -42,7 +42,11 @@ public class HttpClientOperationsHeadersInterceptor implements InstanceMethodsAr
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Object ret) throws Throwable {
((EnhancedInstance) ret).setSkyWalkingDynamicField(((EnhancedInstance) allArguments[0]).getSkyWalkingDynamicField());
Object transmitter = ((EnhancedInstance) allArguments[0]).getSkyWalkingDynamicField();
if (transmitter != null) {
objInst.setSkyWalkingDynamicField(transmitter);
((EnhancedInstance) allArguments[0]).setSkyWalkingDynamicField(null);
}
return ret;
}
......
......@@ -16,13 +16,12 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
import io.netty.handler.codec.http.HttpHeaders;
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
......@@ -30,6 +29,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedI
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context.SWTransmitter;
import reactor.netty.channel.ChannelOperations;
import reactor.netty.http.client.HttpClientRequest;
......@@ -45,30 +45,32 @@ public class HttpClientOperationsSendInterceptor implements InstanceMethodsAroun
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
HttpClientRequest request = (HttpClientRequest) objInst;
EnhancedInstance instance = (EnhancedInstance) request;
SWTransmitter transmitter = (SWTransmitter) objInst.getSkyWalkingDynamicField();
if (transmitter != null) {
HttpClientRequest request = (HttpClientRequest) objInst;
HttpHeaders header = request.requestHeaders();
ChannelOperations channelOpt = (ChannelOperations) objInst;
InetSocketAddress remote = (InetSocketAddress) (channelOpt.channel().remoteAddress());
String peer = remote.getHostName() + ":" + remote.getPort();
HttpHeaders header = request.requestHeaders();
ChannelOperations channelOpt = (ChannelOperations) objInst;
InetSocketAddress remote = (InetSocketAddress) (channelOpt.channel().remoteAddress());
String peer = remote.getHostName() + ":" + remote.getPort();
AbstractSpan span = ContextManager.createExitSpan(toPath(request.uri()), peer);
ContextSnapshot snapshot = (ContextSnapshot) instance.getSkyWalkingDynamicField();
AbstractSpan span = ContextManager.createExitSpan(transmitter.getOperationName(), peer);
ContextManager.continued(transmitter.getSnapshot());
ContextCarrier contextCarrier = new ContextCarrier();
ContextManager.inject(contextCarrier);
ContextManager.continued(snapshot);
ContextCarrier contextCarrier = new ContextCarrier();
ContextManager.inject(contextCarrier);
span.setComponent(ComponentsDefine.SPRING_CLOUD_GATEWAY);
Tags.URL.set(span, peer + request.uri());
Tags.HTTP.METHOD.set(span, request.method().name());
SpanLayer.asHttp(span);
span.setComponent(ComponentsDefine.SPRING_CLOUD_GATEWAY);
Tags.URL.set(span, peer + request.uri());
Tags.HTTP.METHOD.set(span, request.method().name());
SpanLayer.asHttp(span);
CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
next = next.next();
header.set(next.getHeadKey(), next.getHeadValue());
CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
next = next.next();
header.set(next.getHeadKey(), next.getHeadValue());
}
transmitter.setSpanGateway(span.prepareForAsync());
ContextManager.stopSpan(span);
}
}
......@@ -84,13 +86,4 @@ public class HttpClientOperationsSendInterceptor implements InstanceMethodsAroun
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
private static String toPath(String uri) {
int index = uri.indexOf("?");
if (index > -1) {
return uri.substring(0, index);
} else {
return uri;
}
}
}
......@@ -16,7 +16,7 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
......@@ -24,6 +24,7 @@ import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context.SWTransmitter;
import java.lang.reflect.Method;
......@@ -41,12 +42,18 @@ public class HttpClientOperationsStatusInterceptor implements InstanceMethodsAro
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
HttpResponseStatus response = (HttpResponseStatus) ret;
if (response.code() >= 400) {
ContextManager.activeSpan().errorOccurred();
Tags.STATUS_CODE.set(ContextManager.activeSpan(), String.valueOf(response.code()));
SWTransmitter transmitter = (SWTransmitter) objInst.getSkyWalkingDynamicField();
if (transmitter != null) {
HttpResponseStatus response = (HttpResponseStatus) ret;
if (response.code() >= 400) {
Tags.STATUS_CODE.set(transmitter.getSpanGateway().errorOccurred(), String.valueOf(response.code()));
Tags.STATUS_CODE.set(transmitter.getSpanWebflux().errorOccurred(), String.valueOf(response.code()));
}
transmitter.getSpanGateway().asyncFinish();
transmitter.getSpanWebflux().asyncFinish();
objInst.setSkyWalkingDynamicField(null);
}
ContextManager.stopSpan();
return ret;
}
......
......@@ -16,13 +16,15 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context.Constants;
import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context.SWTransmitter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.web.server.ServerWebExchange;
......@@ -34,22 +36,32 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G
/**
* @author zhaoyuguang
*/
public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInterceptor {
public class NettyRoutingFilterInterceptor implements InstanceMethodsAroundInterceptor {
private static final String SPRING_CLOUD_GATEWAY_ROUTE_PREFIX = "GATEWAY/";
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
if (ContextManager.isActive()) {
ContextManager.activeSpan().tag("route", route.getId());
AbstractSpan span = (AbstractSpan) ((EnhancedInstance) allArguments[0]).getSkyWalkingDynamicField();
String operationName = SPRING_CLOUD_GATEWAY_ROUTE_PREFIX;
if (span != null) {
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
operationName = operationName + route.getId();
span.setOperationName(operationName);
SWTransmitter transmitter = new SWTransmitter(span.prepareForAsync(), ContextManager.capture(), operationName);
ContextManager.stopSpan(span);
ContextManager.getRuntimeContext().put(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER, transmitter);
}
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Object ret) throws Throwable {
if (ContextManager.getRuntimeContext().get(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER) != null) {
ContextManager.getRuntimeContext().remove(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER);
}
return ret;
}
......@@ -57,10 +69,5 @@ public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInte
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
AbstractSpan span = ContextManager.activeSpan();
if (span != null) {
span.errorOccurred();
span.log(t);
}
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context;
/**
* @author zhaoyuguang
*/
public interface Constants {
String SPRING_CLOUD_GATEWAY_TRANSMITTER = "spring.cloud.gateway.transmitter";
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.context;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
/**
* @author zhaoyuguang
*/
public class SWTransmitter {
private AbstractSpan spanWebflux;
private AbstractSpan spanGateway;
private ContextSnapshot snapshot;
private String operationName;
public SWTransmitter(AbstractSpan spanWebflux, ContextSnapshot snapshot, String operationName) {
this.spanWebflux = spanWebflux;
this.snapshot = snapshot;
this.operationName = operationName;
}
public AbstractSpan getSpanWebflux() {
return spanWebflux;
}
public void setSpanWebflux(AbstractSpan spanWebflux) {
this.spanWebflux = spanWebflux;
}
public AbstractSpan getSpanGateway() {
return spanGateway;
}
public void setSpanGateway(AbstractSpan spanGateway) {
this.spanGateway = spanGateway;
}
public ContextSnapshot getSnapshot() {
return snapshot;
}
public void setSnapshot(ContextSnapshot snapshot) {
this.snapshot = snapshot;
}
public String getOperationName() {
return operationName;
}
public void setOperationName(String operationName) {
this.operationName = operationName;
}
}
......@@ -16,7 +16,7 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
......@@ -42,7 +42,7 @@ public class DefaultHttpHeadersInstrumentation extends ClassInstanceMethodsEnhan
}
@Override public String getConstructorInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.DefaultHttpHeadersInterceptor";
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.DefaultHttpHeadersInterceptor";
}
}
};
......
......@@ -16,7 +16,7 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
......@@ -50,7 +50,7 @@ public class HttpClientOperationsInstrumentation extends ClassInstanceMethodsEnh
@Override
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.HttpClientOperationsHeadersInterceptor";
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.HttpClientOperationsHeadersInterceptor";
}
@Override
......@@ -65,7 +65,7 @@ public class HttpClientOperationsInstrumentation extends ClassInstanceMethodsEnh
@Override
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.HttpClientOperationsSendInterceptor";
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.HttpClientOperationsSendInterceptor";
}
@Override
......@@ -81,7 +81,7 @@ public class HttpClientOperationsInstrumentation extends ClassInstanceMethodsEnh
@Override
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.HttpClientOperationsStatusInterceptor";
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.HttpClientOperationsStatusInterceptor";
}
@Override
......
......@@ -16,7 +16,7 @@
*
*/
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define;
package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
......@@ -33,7 +33,7 @@ import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName
* @author zhaoyuguang
*/
public class FilteringWebHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
public class NettyRoutingFilterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
......@@ -46,12 +46,14 @@ public class FilteringWebHandlerInstrumentation extends ClassInstanceMethodsEnha
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("handle").and(takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange"));
return named("filter").and(takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange"));
}
@Override
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.FilteringWebHandlerInterceptor";
return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.NettyRoutingFilterInterceptor";
}
@Override
public boolean isOverrideArgs() {
return false;
......@@ -62,7 +64,7 @@ public class FilteringWebHandlerInstrumentation extends ClassInstanceMethodsEnha
@Override
public ClassMatch enhanceClass() {
return byName("org.springframework.cloud.gateway.handler.FilteringWebHandler");
return byName("org.springframework.cloud.gateway.filter.NettyRoutingFilter");
}
@Override
......
......@@ -14,6 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
spring-cloud-gateway-2.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define.DefaultHttpHeadersInstrumentation
spring-cloud-gateway-2.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define.FilteringWebHandlerInstrumentation
spring-cloud-gateway-2.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define.HttpClientOperationsInstrumentation
\ No newline at end of file
spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.DefaultHttpHeadersInstrumentation
spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.HttpClientOperationsInstrumentation
spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.NettyRoutingFilterInstrumentation
\ No newline at end of file
......@@ -28,7 +28,7 @@
<artifactId>optional-spring-cloud</artifactId>
<modules>
<module>gateway-2.x-plugin</module>
<module>gateway-2.1.x-plugin</module>
</modules>
<packaging>pom</packaging>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册