Package io.grpc

Class LoadBalancer.PickResult

  • Enclosing class:
    LoadBalancer

    @Immutable
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
    public static final class LoadBalancer.PickResult
    extends Object
    A balancing decision made by SubchannelPicker for an RPC.

    The outcome of the decision will be one of the following:

    • Proceed: if a Subchannel is provided via withSubchannel(), and is in READY state when the RPC tries to start on it, the RPC will proceed on that Subchannel.
    • Error: if an error is provided via withError(), and the RPC is not wait-for-ready (i.e., CallOptions.withWaitForReady() was not called), the RPC will fail immediately with the given error.
    • Buffer: in all other cases, the RPC will be buffered in the Channel, until the next picker is provided via Helper.updateBalancingState(), when the RPC will go through the same picking process again.
    Since:
    1.2.0
    • Method Detail

      • withSubchannel

        public static LoadBalancer.PickResult withSubchannel​(LoadBalancer.Subchannel subchannel,
                                                             @Nullable
                                                             ClientStreamTracer.Factory streamTracerFactory)
        A decision to proceed the RPC on a Subchannel.

        The Subchannel should either be an original Subchannel returned by Helper.createSubchannel(), or a wrapper of it preferably based on ForwardingSubchannel. At the very least its getInternalSubchannel() must return the same object as the one returned by the original. Otherwise the Channel cannot use it for the RPC.

        When the RPC tries to use the return Subchannel, which is briefly after this method returns, the state of the Subchannel will decide where the RPC would go:

        • READY: the RPC will proceed on this Subchannel.
        • IDLE: the RPC will be buffered. Subchannel will attempt to create connection.
        • All other states: the RPC will be buffered.

        All buffered RPCs will stay buffered until the next call of Helper.updateBalancingState(), which will trigger a new picking process.

        Note that Subchannel's state may change at the same time the picker is making the decision, which means the decision may be made with (to-be) outdated information. For example, a picker may return a Subchannel known to be READY, but it has become IDLE when is about to be used by the RPC, which makes the RPC to be buffered. The LoadBalancer will soon learn about the Subchannels' transition from READY to IDLE, create a new picker and allow the RPC to use another READY transport if there is any.

        You will want to avoid running into a situation where there are READY Subchannels out there but some RPCs are still buffered for longer than a brief time.

        • This can happen if you return Subchannels with states other than READY and IDLE. For example, suppose you round-robin on 2 Subchannels, in READY and CONNECTING states respectively. If the picker ignores the state and pick them equally, 50% of RPCs will be stuck in buffered state until both Subchannels are READY.
        • This can also happen if you don't create a new picker at key state changes of Subchannels. Take the above round-robin example again. Suppose you do pick only READY and IDLE Subchannels, and initially both Subchannels are READY. Now one becomes IDLE, then CONNECTING and stays CONNECTING for a long time. If you don't create a new picker in response to the CONNECTING state to exclude that Subchannel, 50% of RPCs will hit it and be buffered even though the other Subchannel is READY.

        In order to prevent unnecessary delay of RPCs, the rules of thumb are:

        1. The picker should only pick Subchannels that are known as READY or IDLE. Whether to pick IDLE Subchannels depends on whether you want Subchannels to connect on-demand or actively:
          • If you want connect-on-demand, include IDLE Subchannels in your pick results, because when an RPC tries to use an IDLE Subchannel, the Subchannel will try to connect.
          • If you want Subchannels to be always connected even when there is no RPC, you would call Subchannel.requestConnection() whenever the Subchannel has transitioned to IDLE, then you don't need to include IDLE Subchannels in your pick results.
        2. Always create a new picker and call Helper.updateBalancingState() whenever handleSubchannelState() is called, unless the new state is SHUTDOWN. See handleSubchannelState's javadoc for more details.
        Parameters:
        subchannel - the picked Subchannel. It must have been started
        streamTracerFactory - if not null, will be used to trace the activities of the stream created as a result of this pick. Note it's possible that no stream is created at all in some cases.
        Since:
        1.3.0
      • withError

        public static LoadBalancer.PickResult withError​(Status error)
        A decision to report a connectivity error to the RPC. If the RPC is wait-for-ready, it will stay buffered. Otherwise, it will fail with the given error.
        Parameters:
        error - the error status. Must not be OK.
        Since:
        1.2.0
      • withDrop

        public static LoadBalancer.PickResult withDrop​(Status status)
        A decision to fail an RPC immediately. This is a final decision and will ignore retry policy.
        Parameters:
        status - the status with which the RPC will fail. Must not be OK.
        Since:
        1.8.0
      • withNoResult

        public static LoadBalancer.PickResult withNoResult()
        No decision could be made. The RPC will stay buffered.
        Since:
        1.2.0
      • getStatus

        public Status getStatus()
        The status associated with this result. Non-OK if created with withError, or OK otherwise.
        Since:
        1.2.0
      • isDrop

        public boolean isDrop()
        Returns true if this result was created by withDrop().
        Since:
        1.8.0
      • hasResult

        public boolean hasResult()
        Returns true if the pick was not created with withNoResult().
      • hashCode

        public int hashCode()
        Overrides:
        hashCode in class Object