• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H
20 #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <functional>
25 #include <iterator>
26 
27 #include "absl/status/status.h"
28 #include "absl/strings/string_view.h"
29 
30 #include "src/core/ext/filters/client_channel/server_address.h"
31 #include "src/core/ext/filters/client_channel/service_config.h"
32 #include "src/core/ext/filters/client_channel/subchannel_interface.h"
33 #include "src/core/lib/gprpp/orphanable.h"
34 #include "src/core/lib/gprpp/ref_counted_ptr.h"
35 #include "src/core/lib/iomgr/polling_entity.h"
36 #include "src/core/lib/iomgr/work_serializer.h"
37 #include "src/core/lib/transport/connectivity_state.h"
38 
39 namespace grpc_core {
40 
41 extern DebugOnlyTraceFlag grpc_trace_lb_policy_refcount;
42 
43 /// Interface for load balancing policies.
44 ///
45 /// The following concepts are used here:
46 ///
47 /// Channel: An abstraction that manages connections to backend servers
48 ///   on behalf of a client application.  The application creates a channel
49 ///   for a given server name and then sends calls (RPCs) on it, and the
50 ///   channel figures out which backend server to send each call to.  A channel
51 ///   contains a resolver, a load balancing policy (or a tree of LB policies),
52 ///   and a set of one or more subchannels.
53 ///
54 /// Subchannel: A subchannel represents a connection to one backend server.
55 ///   The LB policy decides which subchannels to create, manages the
56 ///   connectivity state of those subchannels, and decides which subchannel
57 ///   to send any given call to.
58 ///
59 /// Resolver: A plugin that takes a gRPC server URI and resolves it to a
60 ///   list of one or more addresses and a service config, as described
61 ///   in https://github.com/grpc/grpc/blob/master/doc/naming.md.  See
62 ///   resolver.h for the resolver API.
63 ///
64 /// Load Balancing (LB) Policy: A plugin that takes a list of addresses
65 ///   from the resolver, maintains and manages a subchannel for each
66 ///   backend address, and decides which subchannel to send each call on.
67 ///   An LB policy has two parts:
68 ///   - A LoadBalancingPolicy, which deals with the control plane work of
69 ///     managing subchannels.
70 ///   - A SubchannelPicker, which handles the data plane work of
71 ///     determining which subchannel a given call should be sent on.
72 
73 /// LoadBalacingPolicy API.
74 ///
75 /// Note: All methods with a "Locked" suffix must be called from the
76 /// work_serializer passed to the constructor.
77 ///
78 /// Any I/O done by the LB policy should be done under the pollset_set
79 /// returned by \a interested_parties().
80 // TODO(roth): Once we move to EventManager-based polling, remove the
81 // interested_parties() hooks from the API.
82 class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
83  public:
84   // Represents backend metrics reported by the backend to the client.
85   struct BackendMetricData {
86     /// CPU utilization expressed as a fraction of available CPU resources.
87     double cpu_utilization;
88     /// Memory utilization expressed as a fraction of available memory
89     /// resources.
90     double mem_utilization;
91     /// Total requests per second being served by the backend.  This
92     /// should include all services that a backend is responsible for.
93     uint64_t requests_per_second;
94     /// Application-specific requests cost metrics.  Metric names are
95     /// determined by the application.  Each value is an absolute cost
96     /// (e.g. 3487 bytes of storage) associated with the request.
97     std::map<absl::string_view, double> request_cost;
98     /// Application-specific resource utilization metrics.  Metric names
99     /// are determined by the application.  Each value is expressed as a
100     /// fraction of total resources available.
101     std::map<absl::string_view, double> utilization;
102   };
103 
104   /// Interface for accessing per-call state.
105   /// Implemented by the client channel and used by the SubchannelPicker.
106   class CallState {
107    public:
108     CallState() = default;
109     virtual ~CallState() = default;
110 
111     /// Allocates memory associated with the call, which will be
112     /// automatically freed when the call is complete.
113     /// It is more efficient to use this than to allocate memory directly
114     /// for allocations that need to be made on a per-call basis.
115     virtual void* Alloc(size_t size) = 0;
116 
117     /// Returns the backend metric data returned by the server for the call,
118     /// or null if no backend metric data was returned.
119     // TODO(roth): Move this out of CallState, since it should not be
120     // accessible to the picker, only to the recv_trailing_metadata_ready
121     // callback.  It should instead be in its own interface.
122     virtual const BackendMetricData* GetBackendMetricData() = 0;
123 
124     /// EXPERIMENTAL API.
125     /// Returns the value of the call attribute \a key.
126     /// Keys are static strings, so an attribute can be accessed by an LB
127     /// policy implementation only if it knows about the internal key.
128     /// Returns a null string_view if key not found.
129     virtual absl::string_view ExperimentalGetCallAttribute(const char* key) = 0;
130   };
131 
132   /// Interface for accessing metadata.
133   /// Implemented by the client channel and used by the SubchannelPicker.
134   class MetadataInterface {
135    public:
136     class iterator
137         : public std::iterator<
138               std::input_iterator_tag,
139               std::pair<absl::string_view, absl::string_view>,  // value_type
140               std::ptrdiff_t,  // difference_type
141               std::pair<absl::string_view, absl::string_view>*,  // pointer
142               std::pair<absl::string_view, absl::string_view>&   // reference
143               > {
144      public:
iterator(const MetadataInterface * md,intptr_t handle)145       iterator(const MetadataInterface* md, intptr_t handle)
146           : md_(md), handle_(handle) {}
147       iterator& operator++() {
148         handle_ = md_->IteratorHandleNext(handle_);
149         return *this;
150       }
151       bool operator==(iterator other) const {
152         return md_ == other.md_ && handle_ == other.handle_;
153       }
154       bool operator!=(iterator other) const { return !(*this == other); }
155       value_type operator*() const { return md_->IteratorHandleGet(handle_); }
156 
157      private:
158       friend class MetadataInterface;
159       const MetadataInterface* md_;
160       intptr_t handle_;
161     };
162 
163     virtual ~MetadataInterface() = default;
164 
165     /// Adds a key/value pair.
166     /// Does NOT take ownership of \a key or \a value.
167     /// Implementations must ensure that the key and value remain alive
168     /// until the call ends.  If desired, they may be allocated via
169     /// CallState::Alloc().
170     virtual void Add(absl::string_view key, absl::string_view value) = 0;
171 
172     /// Iteration interface.
173     virtual iterator begin() const = 0;
174     virtual iterator end() const = 0;
175 
176     /// Removes the element pointed to by \a it.
177     /// Returns an iterator pointing to the next element.
178     virtual iterator erase(iterator it) = 0;
179 
180    protected:
GetIteratorHandle(const iterator & it)181     intptr_t GetIteratorHandle(const iterator& it) const { return it.handle_; }
182 
183    private:
184     friend class iterator;
185 
186     virtual intptr_t IteratorHandleNext(intptr_t handle) const = 0;
187     virtual std::pair<absl::string_view /*key*/, absl::string_view /*value */>
188     IteratorHandleGet(intptr_t handle) const = 0;
189   };
190 
191   /// Arguments used when picking a subchannel for a call.
192   struct PickArgs {
193     /// The path of the call.  Indicates the RPC service and method name.
194     absl::string_view path;
195     /// Initial metadata associated with the picking call.
196     /// The LB policy may use the existing metadata to influence its routing
197     /// decision, and it may add new metadata elements to be sent with the
198     /// call to the chosen backend.
199     MetadataInterface* initial_metadata;
200     /// An interface for accessing call state.  Can be used to allocate
201     /// memory associated with the call in an efficient way.
202     CallState* call_state;
203   };
204 
205   /// The result of picking a subchannel for a call.
206   struct PickResult {
207     enum ResultType {
208       /// Pick complete.  If \a subchannel is non-null, the client channel
209       /// will immediately proceed with the call on that subchannel;
210       /// otherwise, it will drop the call.
211       PICK_COMPLETE,
212       /// Pick cannot be completed until something changes on the control
213       /// plane.  The client channel will queue the pick and try again the
214       /// next time the picker is updated.
215       PICK_QUEUE,
216       /// Pick failed.  If the call is wait_for_ready, the client channel
217       /// will wait for the next picker and try again; otherwise, it
218       /// will immediately fail the call with the status indicated via
219       /// \a error (although the call may be retried if the client channel
220       /// is configured to do so).
221       PICK_FAILED,
222     };
223     ResultType type;
224 
225     /// Used only if type is PICK_COMPLETE.  Will be set to the selected
226     /// subchannel, or nullptr if the LB policy decides to drop the call.
227     RefCountedPtr<SubchannelInterface> subchannel;
228 
229     /// Used only if type is PICK_FAILED.
230     /// Error to be set when returning a failure.
231     // TODO(roth): Replace this with something similar to grpc::Status,
232     // so that we don't expose grpc_error to this API.
233     grpc_error* error = GRPC_ERROR_NONE;
234 
235     /// Used only if type is PICK_COMPLETE.
236     /// Callback set by LB policy to be notified of trailing metadata.
237     /// If set by LB policy, the client channel will invoke the callback
238     /// when trailing metadata is returned.
239     /// The metadata may be modified by the callback.  However, the callback
240     /// does not take ownership, so any data that needs to be used after
241     /// returning must be copied.
242     /// The call state can be used to obtain backend metric data.
243     // TODO(roth): The arguments to this callback should be moved into a
244     // struct, so that we can later add new fields without breaking
245     // existing implementations.
246     std::function<void(grpc_error*, MetadataInterface*, CallState*)>
247         recv_trailing_metadata_ready;
248   };
249 
250   /// A subchannel picker is the object used to pick the subchannel to
251   /// use for a given call.  This is implemented by the LB policy and
252   /// used by the client channel to perform picks.
253   ///
254   /// Pickers are intended to encapsulate all of the state and logic
255   /// needed on the data plane (i.e., to actually process picks for
256   /// individual calls sent on the channel) while excluding all of the
257   /// state and logic needed on the control plane (i.e., resolver
258   /// updates, connectivity state notifications, etc); the latter should
259   /// live in the LB policy object itself.
260   ///
261   /// Currently, pickers are always accessed from within the
262   /// client_channel data plane mutex, so they do not have to be
263   /// thread-safe.
264   class SubchannelPicker {
265    public:
266     SubchannelPicker() = default;
267     virtual ~SubchannelPicker() = default;
268 
269     virtual PickResult Pick(PickArgs args) = 0;
270   };
271 
272   /// A proxy object implemented by the client channel and used by the
273   /// LB policy to communicate with the channel.
274   class ChannelControlHelper {
275    public:
276     ChannelControlHelper() = default;
277     virtual ~ChannelControlHelper() = default;
278 
279     /// Creates a new subchannel with the specified channel args.
280     virtual RefCountedPtr<SubchannelInterface> CreateSubchannel(
281         ServerAddress address, const grpc_channel_args& args) = 0;
282 
283     /// Sets the connectivity state and returns a new picker to be used
284     /// by the client channel.
285     virtual void UpdateState(grpc_connectivity_state state,
286                              const absl::Status& status,
287                              std::unique_ptr<SubchannelPicker>) = 0;
288 
289     /// Requests that the resolver re-resolve.
290     virtual void RequestReresolution() = 0;
291 
292     /// Adds a trace message associated with the channel.
293     enum TraceSeverity { TRACE_INFO, TRACE_WARNING, TRACE_ERROR };
294     virtual void AddTraceEvent(TraceSeverity severity,
295                                absl::string_view message) = 0;
296   };
297 
298   /// Interface for configuration data used by an LB policy implementation.
299   /// Individual implementations will create a subclass that adds methods to
300   /// return the parameters they need.
301   class Config : public RefCounted<Config> {
302    public:
303     ~Config() override = default;
304 
305     // Returns the load balancing policy name
306     virtual const char* name() const = 0;
307   };
308 
309   /// Data passed to the UpdateLocked() method when new addresses and
310   /// config are available.
311   struct UpdateArgs {
312     ServerAddressList addresses;
313     RefCountedPtr<Config> config;
314     const grpc_channel_args* args = nullptr;
315 
316     // TODO(roth): Remove everything below once channel args is
317     // converted to a copyable and movable C++ object.
318     UpdateArgs() = default;
~UpdateArgsUpdateArgs319     ~UpdateArgs() { grpc_channel_args_destroy(args); }
320     UpdateArgs(const UpdateArgs& other);
321     UpdateArgs(UpdateArgs&& other) noexcept;
322     UpdateArgs& operator=(const UpdateArgs& other);
323     UpdateArgs& operator=(UpdateArgs&& other) noexcept;
324   };
325 
326   /// Args used to instantiate an LB policy.
327   struct Args {
328     /// The work_serializer under which all LB policy calls will be run.
329     std::shared_ptr<WorkSerializer> work_serializer;
330     /// Channel control helper.
331     /// Note: LB policies MUST NOT call any method on the helper from
332     /// their constructor.
333     std::unique_ptr<ChannelControlHelper> channel_control_helper;
334     /// Channel args.
335     // TODO(roth): Find a better channel args representation for this API.
336     // TODO(roth): Clarify ownership semantics here -- currently, this
337     // does not take ownership of args, which is the opposite of how we
338     // handle them in UpdateArgs.
339     const grpc_channel_args* args = nullptr;
340   };
341 
342   explicit LoadBalancingPolicy(Args args, intptr_t initial_refcount = 1);
343   ~LoadBalancingPolicy() override;
344 
345   // Not copyable nor movable.
346   LoadBalancingPolicy(const LoadBalancingPolicy&) = delete;
347   LoadBalancingPolicy& operator=(const LoadBalancingPolicy&) = delete;
348 
349   /// Returns the name of the LB policy.
350   virtual const char* name() const = 0;
351 
352   /// Updates the policy with new data from the resolver.  Will be invoked
353   /// immediately after LB policy is constructed, and then again whenever
354   /// the resolver returns a new result.
355   virtual void UpdateLocked(UpdateArgs) = 0;  // NOLINT
356 
357   /// Tries to enter a READY connectivity state.
358   /// This is a no-op by default, since most LB policies never go into
359   /// IDLE state.
ExitIdleLocked()360   virtual void ExitIdleLocked() {}
361 
362   /// Resets connection backoff.
363   virtual void ResetBackoffLocked() = 0;
364 
interested_parties()365   grpc_pollset_set* interested_parties() const { return interested_parties_; }
366 
367   // Note: This must be invoked while holding the work_serializer.
368   void Orphan() override;
369 
370   // A picker that returns PICK_QUEUE for all picks.
371   // Also calls the parent LB policy's ExitIdleLocked() method when the
372   // first pick is seen.
373   class QueuePicker : public SubchannelPicker {
374    public:
QueuePicker(RefCountedPtr<LoadBalancingPolicy> parent)375     explicit QueuePicker(RefCountedPtr<LoadBalancingPolicy> parent)
376         : parent_(std::move(parent)) {}
377 
~QueuePicker()378     ~QueuePicker() override { parent_.reset(DEBUG_LOCATION, "QueuePicker"); }
379 
380     PickResult Pick(PickArgs args) override;
381 
382    private:
383     RefCountedPtr<LoadBalancingPolicy> parent_;
384     bool exit_idle_called_ = false;
385   };
386 
387   // A picker that returns PICK_TRANSIENT_FAILURE for all picks.
388   class TransientFailurePicker : public SubchannelPicker {
389    public:
TransientFailurePicker(grpc_error * error)390     explicit TransientFailurePicker(grpc_error* error) : error_(error) {}
~TransientFailurePicker()391     ~TransientFailurePicker() override { GRPC_ERROR_UNREF(error_); }
392 
393     PickResult Pick(PickArgs args) override;
394 
395    private:
396     grpc_error* error_;
397   };
398 
399  protected:
work_serializer()400   std::shared_ptr<WorkSerializer> work_serializer() const {
401     return work_serializer_;
402   }
403 
404   // Note: LB policies MUST NOT call any method on the helper from their
405   // constructor.
channel_control_helper()406   ChannelControlHelper* channel_control_helper() const {
407     return channel_control_helper_.get();
408   }
409 
410   /// Shuts down the policy.
411   virtual void ShutdownLocked() = 0;
412 
413  private:
414   /// Work Serializer under which LB policy actions take place.
415   std::shared_ptr<WorkSerializer> work_serializer_;
416   /// Owned pointer to interested parties in load balancing decisions.
417   grpc_pollset_set* interested_parties_;
418   /// Channel control helper.
419   std::unique_ptr<ChannelControlHelper> channel_control_helper_;
420 };
421 
422 }  // namespace grpc_core
423 
424 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H */
425