Refactor/decouple load balance metrics collection from divide plugin - #6429
Conversation
|
@hengyuss pls fix ci |
…lection_from_DividePlugin
|
I found two issues that should be addressed before merging:
In Suggested fix: use the same defaulted load-balance value consistently, and avoid building callback state unless callbacks are actually needed. Please add a regression test for a
Suggested fix: return a per-selection result/handle that owns outcome reporting, or keep this behavior fenced to divide-specific code until all call sites can honor the lifecycle. Also avoid the untyped Validation I ran locally on PR head ./mvnw -pl shenyu-loadbalancer,shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide -am -Dtest=LoadBalancerFactoryTest,P2cLoadBalancerTest,ShortestResponseLoadBalancerTest,DividePluginTest -DfailIfNoTests=false -DskipITs -DskipRat -Dcheckstyle.skip -Drat.skip=true testThe focused tests passed, but they do not cover the |
…etrics_collection_from_DividePlugin' into refactor/decouple_load_balance_metrics_collection_from_DividePlugin
…lection_from_DividePlugin
|
Thanks for the detailed review! I've addressed both issues: Issue 1 (SPECIFY_DOMAIN): After re-examining the code, I found that the SPECIFY_DOMAIN path on master already works correctly — the newly built Upstream has inflight initialized to 1, so responseTrigger won't cause negative counts. The real problem was that my PR unnecessarily forced the SPECIFY_DOMAIN path through LoadBalancerFactory.getInstance() and buildLoadBalanceData(), which could throw SPI lookup errors or NPE. By reverting to the master pattern, these risks are eliminated. Issue 2 (Two-phase callback protocol): I agree this was the core problem. I've reverted all changes to the LoadBalancer SPI interface — removed onSuccess/onError default methods, removed LoadBalancerFactory.getInstance(), and kept the callback logic as divide-specific private methods in DividePlugin. This way the SPI contract remains stable and other callers (TCP, gRPC, SDK) are unaffected. Additional fix: beginTime was an instance variable (private Long beginTime) on master, which is not thread-safe under concurrent requests. I changed it to a local variable and updated successResponseTrigger to accept it as a parameter.
|
…lection_from_DividePlugin
Aias00
left a comment
There was a problem hiding this comment.
Reviewed #6429. The mechanical change is correct and behavior-preserving, but the PR title/Fixes #6426 oversell the scope, and the changed path has no regression test.
1. should_fix — Scope vs. linked issue. Body says Fixes #6426 and the title is "decouple load balance metrics collection from DividePlugin", but only sub-issue #3 (thread-safety of beginTime) is addressed. The actual decoupling proposed in #6426 — adding onSuccess/onError defaults to LoadBalancer and moving the strategy callbacks out of DividePlugin — is not done: LoadBalancer.java is unchanged and DividePlugin still hard-codes the P2C/SHORTEST_RESPONSE branches with strategy-specific callbacks (DividePlugin.java:133-140). Merging will auto-close #6426 while the SRP/OCP problems (#1, #2) remain. Either rename this to a focused "fix: make shortestResponse beginTime per-request" and switch to Relates to #6426, or land the full decoupling.
2. nit — No test for the changed path. doExecuteTest never sets loadBalance=shortestResponse, so the only line that changed (DividePlugin.java:136-139) is uncovered. successResponseTriggerTest invokes the private helper via reflection and only asserts succeeded == 1 — it would pass even if the caller never wired the local beginTime into the doOnSuccess lambda. Suggest a doExecute test with loadBalance=shortestResponse, a Mono.empty() chain, asserting upstream.getSucceeded().get() == 1 and upstream.getSucceededElapsed().get() > 0 after the StepVerifier completes.
Behavior-preservation verified against master: metrics still recorded on the same paths (shortestResponse: doOnSuccess only; P2C: doOnSuccess+doOnError), same Upstream counters (succeeded/succeededElapsed, consumed by ShortestResponseLoadBalancer), same capture timing, no double-counting/drop. Promoting Long beginTime from a singleton instance field to an effectively-final local long is the correct fix for the race and also removes a latent auto-unbox NPE. Only a private method signature changed — no SPI/compat impact (rg confirms no external consumers/reflection). CI is green.
|
Good fix — and a real concurrency bug, not just style. |
…lection_from_DividePlugin
Fixes #6426
Make sure that:
./mvnw clean install -Dmaven.javadoc.skip=true.