Aias00 opened a new issue, #3513:
URL: https://github.com/apache/dubbo-go/issues/3513

   ### Problem
   
   `base.BaseClusterInvoker.doSelectInvoker` calls 
`selectedInvoker.IsAvailable()` immediately after `lb.Select(invokers, 
invocation)` without a nil check. Several load-balance implementations can 
return `nil` for a non-empty invoker list, so the cluster layer panics on a 
nil-pointer dereference.
   
   Affected `lb.Select` implementations that return `nil`:
   
   - **P2C** (`cluster/loadbalance/p2c/loadbalance.go:128,139`) returns `nil` 
when `metrics.GetMethodMetrics` returns a non-`ErrMetricsNotFound` error (a 
transient metrics-layer error). P2C also `panic(...)` outright when the metrics 
value is not `uint64` (~line 145).
   - **ConsistentHash** 
(`cluster/loadbalance/consistenthashing/loadbalance.go:71`) returns `nil` when 
`json.Marshal(invoker)` fails.
   
   The `adaptivesvc` fast path forces P2C and has the same unguarded 
dereference (`cluster/cluster/adaptivesvc/cluster_invoker.go:66-70`).
   
   ### Current behavior
   
   `cluster/cluster/base/cluster_invoker.go:160-163`
   ```go
   selectedInvoker := lb.Select(invokers, invocation)
   
   // judge if the selected Invoker is invoked and available
   if (!selectedInvoker.IsAvailable() && invoker.AvailableCheck) || 
isInvoked(selectedInvoker, invoked) {
   ```
   
   `cluster/cluster/adaptivesvc/cluster_invoker.go:66-70`
   ```go
   lb := extension.GetLoadbalance(lbKey)             // forced to P2C
   invoker := lb.Select(invokers, invocation)        // can return nil
   ...
   res := invoker.Invoke(ctx, invocation)            // nil dereference → panic
   ```
   
   `cluster/loadbalance/p2c/loadbalance.go:128,139,~145`
   ```go
   if err != nil {
       if errors.Is(err, metrics.ErrMetricsNotFound) {
           return invokers[i]
       }
       logger.Warnf(...)
       return nil
   }
   ...
   remainingI, ok := remainingIIface.(uint64)
   if !ok {
       panic(fmt.Sprintf("[Loadbalance][P2C] type check failed: ..."))
   }
   ```
   
   ### Expected behavior
   
   1. `lb.Select` should have a clear contract for non-empty input: either 
never return `nil`, or callers must handle `nil` by degrading to a fallback 
selection.
   2. `doSelectInvoker` and the `adaptivesvc` fast path must nil-check before 
dereferencing.
   3. P2C must not `panic` on an unexpected metrics type; it should degrade and 
warn.
   
   ### Suggested approach
   
   - Add `if selectedInvoker == nil { /* degrade to first available / random */ 
}` in `doSelectInvoker` and in the `adaptivesvc` fast path.
   - Tighten the `LoadBalance.Select` contract (return `(Invoker, error)`, or 
guarantee non-nil for non-empty input) and audit all implementations.
   - Replace P2C's `panic(...)` on type mismatch with a warning + degraded 
selection.
   
   ### Acceptance criteria
   
   - [ ] P2C transient metrics error no longer causes a panic in the cluster 
layer; the call degrades to an available invoker.
   - [ ] ConsistentHash `json.Marshal` failure no longer causes a nil-deref in 
`doSelectInvoker`.
   - [ ] `adaptivesvc` fast path nil-checks the P2C result before `Invoke`.
   - [ ] P2C no longer `panic`s on a non-`uint64` metrics value.
   - [ ] Regression tests cover P2C transient error and ConsistentHash marshal 
failure paths (`-race` clean).
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to