You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2022/05/14 12:45:41 UTC
[skywalking-java] branch main updated: Fix Span not finished in gateway plugin when the gateway request timeout. (#175)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git
The following commit(s) were added to refs/heads/main by this push:
new 42377bb27 Fix Span not finished in gateway plugin when the gateway request timeout. (#175)
42377bb27 is described below
commit 42377bb2746393f537b22cd37e4b7b0aefdfecf2
Author: wuwen <wu...@aliyun.com>
AuthorDate: Sat May 14 20:45:36 2022 +0800
Fix Span not finished in gateway plugin when the gateway request timeout. (#175)
---
CHANGES.md | 1 +
...ientFinalizerResponseConnectionInterceptor.java | 66 ++++++++++++-----
...ientFinalizerResponseConnectionInterceptor.java | 48 ++++++++++---
.../v3x/HttpClientFinalizerInterceptorTest.java | 7 +-
.../config/expectedData.yaml | 83 +++++++++++++++++++---
.../src/main/resources/application.yml | 6 ++
.../projectB/controller/TestController.java | 5 ++
.../gateway-3.x-scenario/config/expectedData.yaml | 81 ++++++++++++++++++---
.../src/main/resources/application.yml | 6 ++
.../projectB/controller/TestController.java | 5 ++
10 files changed, 262 insertions(+), 46 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index e45e028d2..cdc8681f7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -16,6 +16,7 @@ Release Notes.
* Grpc plugin support trace client async generic call(without grpc stubs), support Method type: `UNARY`、`SERVER_STREAMING`.
* Enhance Apache ShenYu (incubating) plugin: support trace `grpc`,`sofarpc`,`motan`,`tars` rpc proxy.
* Add primary endpoint name to log events.
+* Fix Span not finished in gateway plugin when the gateway request timeout.
#### Documentation
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientFinalizerResponseConnectionInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientFinalizerResponseConnectionInterceptor.java
index 1d67b7c0f..9d26794b1 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientFinalizerResponseConnectionInterceptor.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientFinalizerResponseConnectionInterceptor.java
@@ -19,46 +19,74 @@ package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x;
import java.lang.reflect.Method;
import java.util.function.BiFunction;
+
+import io.netty.handler.codec.http.HttpResponseStatus;
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.define.EnhanceObjectCache;
import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.SignalType;
import reactor.netty.Connection;
import reactor.netty.http.client.HttpClientResponse;
public class HttpClientFinalizerResponseConnectionInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) {
BiFunction<? super HttpClientResponse, ? super Connection, ? extends Publisher> finalReceiver = (BiFunction<? super HttpClientResponse, ? super Connection, ? extends Publisher>) allArguments[0];
EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField();
- allArguments[0] = new BiFunction<HttpClientResponse, Connection, Publisher>() {
- @Override
- public Publisher apply(final HttpClientResponse response, final Connection connection) {
- Publisher publisher = finalReceiver.apply(response, connection);
- // receive the response. Stop the span.
- if (cache.getSpan() != null) {
- if (response.status().code() >= 400) {
- cache.getSpan().errorOccurred();
- }
- Tags.HTTP_RESPONSE_STATUS_CODE.set(cache.getSpan(), response.status().code());
- cache.getSpan().asyncFinish();
- }
-
- if (cache.getSpan1() != null) {
- cache.getSpan1().asyncFinish();
+ allArguments[0] = (BiFunction<HttpClientResponse, Connection, Publisher>) (response, connection) -> {
+ Publisher publisher = finalReceiver.apply(response, connection);
+ // receive the response.
+ if (cache.getSpan() != null) {
+ if (response.status().code() >= HttpResponseStatus.BAD_REQUEST.code()) {
+ cache.getSpan().errorOccurred();
}
- return publisher;
+ Tags.HTTP_RESPONSE_STATUS_CODE.set(cache.getSpan(), response.status().code());
}
+ return publisher;
};
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
- return ret;
+ Object ret) {
+ Flux<?> responseFlux = (Flux<?>) ret;
+
+ responseFlux = responseFlux
+ .doOnError(e -> {
+ EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField();
+ if (cache == null) {
+ return;
+ }
+
+ if (cache.getSpan() != null) {
+ cache.getSpan().errorOccurred();
+ cache.getSpan().log(e);
+ }
+ })
+ .doFinally(signalType -> {
+ EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField();
+ if (cache == null) {
+ return;
+ }
+ // do finally. Finish the span.
+ if (cache.getSpan() != null) {
+ if (signalType == SignalType.CANCEL) {
+ cache.getSpan().errorOccurred();
+ }
+ cache.getSpan().asyncFinish();
+ }
+
+ if (cache.getSpan1() != null) {
+ cache.getSpan1().asyncFinish();
+ }
+ });
+
+ return responseFlux;
}
@Override
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.java
index 0ef159d44..de484c86d 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.java
@@ -24,6 +24,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceM
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.EnhanceObjectCache;
import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.SignalType;
import reactor.netty.Connection;
import reactor.netty.http.client.HttpClientResponse;
@@ -39,7 +41,7 @@ public class HttpClientFinalizerResponseConnectionInterceptor implements Instanc
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) {
BiFunction<? super HttpClientResponse, ? super Connection, ? extends Publisher> finalReceiver = (BiFunction<? super HttpClientResponse, ? super Connection, ? extends Publisher>) allArguments[0];
EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField();
allArguments[0] = (BiFunction<HttpClientResponse, Connection, Publisher>) (response, connection) -> {
@@ -47,26 +49,54 @@ public class HttpClientFinalizerResponseConnectionInterceptor implements Instanc
if (cache == null) {
return publisher;
}
- // receive the response. Stop the span.
+ // receive the response.
if (cache.getSpan() != null) {
if (response.status().code() >= HttpResponseStatus.BAD_REQUEST.code()) {
cache.getSpan().errorOccurred();
}
Tags.HTTP_RESPONSE_STATUS_CODE.set(cache.getSpan(), response.status().code());
- cache.getSpan().asyncFinish();
- }
-
- if (cache.getSpan1() != null) {
- cache.getSpan1().asyncFinish();
}
+
return publisher;
};
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
- return ret;
+ Object ret) {
+ Flux<?> responseFlux = (Flux<?>) ret;
+
+ responseFlux = responseFlux
+ .doOnError(e -> {
+ EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField();
+ if (cache == null) {
+ return;
+ }
+
+ if (cache.getSpan() != null) {
+ cache.getSpan().errorOccurred();
+ cache.getSpan().log(e);
+ }
+ })
+ .doFinally(signalType -> {
+ EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField();
+ if (cache == null) {
+ return;
+ }
+ // do finally. Finish the span.
+ if (cache.getSpan() != null) {
+ if (signalType == SignalType.CANCEL) {
+ cache.getSpan().errorOccurred();
+ }
+ cache.getSpan().asyncFinish();
+ }
+
+ if (cache.getSpan1() != null) {
+ cache.getSpan1().asyncFinish();
+ }
+ });
+
+ return responseFlux;
}
@Override
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java
index 7723f02d5..b3bfbde11 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java
@@ -40,6 +40,7 @@ import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
import reactor.netty.Connection;
import reactor.netty.NettyOutbound;
import reactor.netty.http.client.HttpClientRequest;
@@ -151,9 +152,13 @@ public class HttpClientFinalizerInterceptorTest {
Object[] responseConnectionArguments = new Object[]{originalResponseConnectionBiFunction};
responseConnectionInterceptor
.beforeMethod(enhancedInstance, null, responseConnectionArguments, null, null);
- responseConnectionInterceptor.afterMethod(enhancedInstance, null, new Object[0], null, enhancedInstance);
+ Flux flux = Flux.just(0);
+
+ flux = (Flux) responseConnectionInterceptor.afterMethod(enhancedInstance, null, new Object[0], null, flux);
+
((BiFunction<? super HttpClientResponse, ? super Connection, ? extends Publisher<Void>>) responseConnectionArguments[0])
.apply(mockResponse, null);
+ flux.blockFirst();
}
private void assertUpstreamSpan(AbstractSpan span) {
diff --git a/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml
index f317ca684..bcd400521 100644
--- a/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml
@@ -19,6 +19,26 @@ segmentItems:
segments:
- segmentId: not null
spans:
+ - operationName: /provider/timeout/error
+ parentSpanId: 0
+ spanId: 1
+ isError: true
+ spanType: Exit
+ tags:
+ - { key: url, value: not null }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: '500' }
+ logs:
+ - logEvent:
+ - { key: event, value: error }
+ - { key: error.kind, value: not null }
+ - { key: message, value: not null }
+ - { key: stack, value: not null }
+ - logEvent:
+ - { key: event, value: error }
+ - { key: error.kind, value: not null }
+ - { key: message, value: not null }
+ - { key: stack, value: not null }
- operationName: GET:/provider/b/testcase
parentSpanId: -1
spanId: 0
@@ -42,21 +62,49 @@ segmentItems:
segments:
- segmentId: not null
spans:
- - operationName: /provider/b/testcase
+ - operationName: /provider/timeout/error
parentSpanId: -1
spanId: 0
spanLayer: Http
- startTime: nq 0
- endTime: nq 0
- componentId: 67
- isError: false
+ isError: true
spanType: Entry
- peer: not null
tags:
- - {key: url, value: 'http://localhost:8080/provider/b/testcase'}
+ - {key: url, value: 'http://localhost:8080/provider/timeout/error' }
- {key: http.method, value: GET}
- - {key: http.status_code, value: '200'}
- skipAnalysis: 'false'
+ - {key: http.status_code, value: '500'}
+ - segmentId: not null
+ spans:
+ - operationName: SpringCloudGateway/sendRequest
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 61
+ isError: true
+ spanType: Exit
+ peer: 1.2.3.4:18070
+ skipAnalysis: false
+ tags:
+ - { key: url, value: not null }
+ logs:
+ - logEvent:
+ - { key: event, value: error }
+ - { key: error.kind, value: not null }
+ - { key: message, value: not null }
+ - { key: stack, value: not null }
+ - operationName: SpringCloudGateway/RoutingFilter
+ parentSpanId: -1
+ spanId: 0
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 61
+ spanType: Local
+ refs:
+ - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ skipAnalysis: 'false'
- segmentId: not null
spans:
- operationName: SpringCloudGateway/sendRequest
@@ -87,3 +135,20 @@ segmentItems:
parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not
null, parentService: not null, traceId: not null}
skipAnalysis: 'false'
+ - segmentId: not null
+ spans:
+ - operationName: /provider/b/testcase
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 67
+ isError: false
+ spanType: Entry
+ peer: not null
+ tags:
+ - { key: url, value: 'http://localhost:8080/provider/b/testcase' }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: '200' }
+ skipAnalysis: 'false'
\ No newline at end of file
diff --git a/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml
index da55c58a4..7639e7ce8 100644
--- a/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml
+++ b/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml
@@ -20,8 +20,14 @@ server:
spring:
cloud:
gateway:
+ httpclient:
+ connect-timeout: 2000
routes:
- id: provider_route
uri: http://localhost:18070
predicates:
- Path=/provider/b/*
+ - id: provider_timeout
+ uri: http://1.2.3.4:18070
+ predicates:
+ - Path=/provider/timeout/*
diff --git a/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java b/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java
index cb8b88eba..923d7fd7f 100644
--- a/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java
+++ b/test/plugin/scenarios/gateway-2.1.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java
@@ -19,12 +19,17 @@ package test.apache.skywalking.apm.testcase.sc.gateway.projectB.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@RequestMapping("/provider/b/testcase")
public String testcase() {
+ try {
+ new RestTemplate().getForEntity("http://localhost:8080/provider/timeout/error", String.class);
+ } catch (Exception e) {
+ }
return "1";
}
diff --git a/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml
index f317ca684..2eaea2414 100644
--- a/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml
@@ -19,6 +19,26 @@ segmentItems:
segments:
- segmentId: not null
spans:
+ - operationName: /provider/timeout/error
+ parentSpanId: 0
+ spanId: 1
+ isError: true
+ spanType: Exit
+ tags:
+ - { key: url, value: not null }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: '500' }
+ logs:
+ - logEvent:
+ - { key: event, value: error }
+ - { key: error.kind, value: not null }
+ - { key: message, value: not null }
+ - {key: stack, value: not null}
+ - logEvent:
+ - { key: event, value: error }
+ - { key: error.kind, value: not null }
+ - { key: message, value: not null }
+ - { key: stack, value: not null }
- operationName: GET:/provider/b/testcase
parentSpanId: -1
spanId: 0
@@ -42,20 +62,48 @@ segmentItems:
segments:
- segmentId: not null
spans:
- - operationName: /provider/b/testcase
+ - operationName: /provider/timeout/error
parentSpanId: -1
spanId: 0
spanLayer: Http
- startTime: nq 0
- endTime: nq 0
- componentId: 67
- isError: false
+ isError: true
spanType: Entry
- peer: not null
tags:
- - {key: url, value: 'http://localhost:8080/provider/b/testcase'}
+ - {key: url, value: 'http://localhost:8080/provider/timeout/error' }
- {key: http.method, value: GET}
- - {key: http.status_code, value: '200'}
+ - {key: http.status_code, value: '500'}
+ - segmentId: not null
+ spans:
+ - operationName: SpringCloudGateway/sendRequest
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 61
+ isError: true
+ spanType: Exit
+ peer: 1.2.3.4:18070
+ skipAnalysis: false
+ tags:
+ - { key: url, value: not null }
+ logs:
+ - logEvent:
+ - { key: event, value: error }
+ - { key: error.kind, value: not null }
+ - { key: message, value: not null }
+ - { key: stack, value: not null}
+ - operationName: SpringCloudGateway/RoutingFilter
+ parentSpanId: -1
+ spanId: 0
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 61
+ spanType: Local
+ refs:
+ - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
skipAnalysis: 'false'
- segmentId: not null
spans:
@@ -87,3 +135,20 @@ segmentItems:
parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not
null, parentService: not null, traceId: not null}
skipAnalysis: 'false'
+ - segmentId: not null
+ spans:
+ - operationName: /provider/b/testcase
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 67
+ isError: false
+ spanType: Entry
+ peer: not null
+ tags:
+ - { key: url, value: 'http://localhost:8080/provider/b/testcase' }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: '200' }
+ skipAnalysis: 'false'
diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml
index da55c58a4..7639e7ce8 100644
--- a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml
+++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml
@@ -20,8 +20,14 @@ server:
spring:
cloud:
gateway:
+ httpclient:
+ connect-timeout: 2000
routes:
- id: provider_route
uri: http://localhost:18070
predicates:
- Path=/provider/b/*
+ - id: provider_timeout
+ uri: http://1.2.3.4:18070
+ predicates:
+ - Path=/provider/timeout/*
diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java
index cb8b88eba..923d7fd7f 100644
--- a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java
+++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java
@@ -19,12 +19,17 @@ package test.apache.skywalking.apm.testcase.sc.gateway.projectB.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@RequestMapping("/provider/b/testcase")
public String testcase() {
+ try {
+ new RestTemplate().getForEntity("http://localhost:8080/provider/timeout/error", String.class);
+ } catch (Exception e) {
+ }
return "1";
}