wy471x opened a new pull request, #7507:
URL: https://github.com/apache/shenyu/pull/7507

   [X] I have read the [Contributor 
Guide](https://shenyu.apache.org/community/contributor-guide)
   [X] I have added test cases for my changes
   [X] I have run `./mvnw clean install -Dmaven.javadoc.skip=true` locally
   
   ## Summary
   
   Fixes #6584 — when every upstream behind a divide selector is down, each 
request still walked the full retry path (every attempt waiting for its full 
timeout) before failing. This PR adds a lightweight, built-in circuit breaker 
to the divide/HTTP proxy and its failover retry path so that requests fail fast 
once an upstream's consecutive failures reach the threshold, with a half-open 
probe to recover.
   
   ### Changes:
   
   1. `UpstreamCircuitBreaker.java` (new, 
`shenyu-plugin/shenyu-plugin-base/.../base/circuitbreaker/UpstreamCircuitBreaker.java`)
 — lightweight per-selector-upstream breaker stored in a `ConcurrentHashMap` 
(thread-safe). State machine: CLOSED → (3 consecutive failures by default) → 
OPEN (requests fail fast, no real traffic) → after a 10s wait window a single 
half-open probe is granted atomically (`tryAcquireHalfOpenProbe`) → probe 
success closes the breaker, probe failure re-opens it. With no failures the 
happy path only performs map lookups, so the overhead is negligible, and it is 
fully independent of the optional resilience4j plugin.
   2. `DividePlugin.java` 
(`shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide`) — after fetching the 
cached upstream list, upstreams still blocked by the breaker are filtered out 
before load balancing (`filterByCircuitBreaker`); if every upstream is blocked, 
exactly one half-open probe request is granted, otherwise the request fails 
fast with `CANNOT_FIND_HEALTHY_UPSTREAM_URL` instead of being forwarded. The 
forwarding tail was extracted to `forwardWithCircuitBreaker`, which records the 
request outcome (`ON_COMPLETE` → success, `ON_ERROR` → failure) via 
`UpstreamCircuitBreaker.recordOutcome`.
   3. `DefaultRetryStrategy.java` (`shenyu-plugin/shenyu-plugin-httpclient`) — 
the failover `resend` path now skips upstreams blocked by the breaker (fast 
fail instead of paying a full timeout per retry) and records each resend 
attempt's outcome against the retried upstream.
   
   ### Test Cases:
   
   - `UpstreamCircuitBreakerTest.java` (new, 
`shenyu-plugin/shenyu-plugin-base`) — opens after the consecutive-failure 
threshold, success resets/closes, blocking within the wait window, half-open 
probe granted exactly once (including a 16-thread concurrent acquisition race 
where only one caller wins), failed probe re-opens, successful probe closes, 
32-thread concurrent failure recording, `recordOutcome` signal handling, key 
building, reset and per-key independence.
   - `DividePluginCircuitBreakerTest.java` (new, `shenyu-plugin-divide`) — 
end-to-end through `DividePlugin.doExecute`: fail fast without invoking the 
chain when all upstreams are blocked; 3 consecutive failed requests open the 
breaker and the 4th request fails fast; after the wait window a half-open probe 
is forwarded and its success closes the breaker; healthy upstreams still 
receive traffic when only one upstream is blocked.
   - `RetryStrategyTest.java` (extended, `shenyu-plugin-httpclient`) — failover 
skips a blocked standby upstream and exhausts with 
`CANNOT_FIND_HEALTHY_UPSTREAM_URL_AFTER_FAILOVER` without calling the client; a 
failed resend records a failure for that upstream; a successful resend resets 
its failure counter.
   
   ## Verification
   
   - `./mvnw -pl 
shenyu-plugin/shenyu-plugin-base,shenyu-plugin/shenyu-plugin-httpclient,shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide
 -am validate` — checkstyle and Apache RAT pass.
   - `./mvnw -pl 
shenyu-plugin/shenyu-plugin-base,shenyu-plugin/shenyu-plugin-httpclient,shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide
 -am test` (no skips, JDK 21) — all tests pass, including the 28 new/extended 
breaker test cases above.
   
   Fixes #6584
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to