[Bug] Spring Cloud Gateway 4.3.3 plugin may inject a stale sw8 context from a previous request #14095
Replies: 1 comment 1 reply
|
Thanks for the analysis — it is correct, and the level of detail made this quick to confirm. I verified it against Spring Cloud Gateway 4.3.3 and reactor-netty 1.2.18 sources. The fix is in apache/skywalking-java#830, built on your proposal. Four things are different from your draft, and it is worth saying why. 1. Both go through the same if (doAfterRequest == null && doAfterResponseSuccess == null && doOnRedirect == null &&
doOnRequest == null && doOnRequestError == null && doOnResponse == null && doOnResponseError == null) {
return super.defaultConnectionObserver();
}
else {
return super.defaultConnectionObserver().then(new HttpClientDoOn(...));
}Installing a no-op 2. The 3. If the derived object is not an 4. The regression test asserts the behaviour rather than reactor-netty's contract. Could you verify it locally? The agent is in Two questions, because one part of your evidence does not fit this root cause. The stale trace is about 832 seconds old (
Either way this is a real cross-request context bleed and worth fixing on its own. Thanks again for the report and the patch. |
Uh oh!
There was an error while loading. Please reload this page.
Describe the bug
Under concurrent traffic, the SkyWalking Spring Cloud Gateway 4.x plugin may propagate a stale
sw8context that belongs to a previous request.The downstream service confirms that the
sw8header exists, but the Trace ID activated by the downstream agent is not the Trace ID of the current gateway request. It is an older Trace ID previously created by the same gateway instance.This is different from a missing-header problem: propagation happens, but the propagated context appears stale.
Environment
apm-spring-cloud-gateway-4.x-plugin-9.6.0.jarThe standalone optional
apm-spring-webflux-6.x-pluginandapm-netty-http-4.1.x-pluginare not enabled, so the Gateway plugin is the only plugin responsible for outbound Gateway trace propagation.Evidence
For one request, the gateway reports the current trace as:
The downstream service receives
sw8, but activates another trace:Both IDs have the same gateway process/instance prefix, while the timestamp component of the downstream Trace ID is about 833 seconds older. Repeated requests show the same pattern: the gateway creates unique current Trace IDs, but the downstream service sometimes activates a historical gateway Trace ID.
Steps to reproduce
apm-spring-cloud-gateway-4.x-plugin-9.6.0.jar.sw8exists and the activated Trace ID.Expected behavior
The downstream service should join the trace of the current gateway request.
Actual behavior
The downstream service receives
sw8, but intermittently joins a trace created by an earlier request on the same gateway instance.Suspected cause
In the
v412ximplementation,NettyRoutingGetHttpClientV412Interceptor.afterMethodstores a request-scopedContextSnapshotin the dynamic field of theHttpClientreturned byNettyRoutingFilter#getHttpClient:That Reactor Netty
HttpClientmay be shared/reused across requests. If multiple requests write theirContextSnapshotto the same enhanced object, a later duplicate/connect/send stage may observe a snapshot from another request and inject stalesw8data.The following local experiment prevents the shared-object write by deriving a request-local
HttpClientbefore attaching the snapshot:A regression test also confirms that two invocations using the same shared
HttpClientreturn two distinct derived instances.Could the maintainers please confirm whether storing the request
ContextSnapshoton the sharedHttpClientis expected, and whether the context should instead be attached to a request-local object or captured closer to the actual send operation?Additional context
sw8values are included because they contain encoded service and endpoint metadata. Sanitized diagnostic logs can be provided if needed.All reactions