grpc 1.28.0.pre2 → 1.28.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +8 -2
- data/src/core/ext/filters/client_channel/client_channel.cc +27 -3
- data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +291 -0
- data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h +83 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +37 -178
- data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +38 -9
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +242 -396
- data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +27 -5
- data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +27 -165
- data/src/core/ext/filters/client_channel/resolving_lb_policy.h +2 -4
- data/src/core/ext/filters/client_channel/xds/xds_api.cc +679 -56
- data/src/core/ext/filters/client_channel/xds/xds_api.h +30 -9
- data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +82 -5
- data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +5 -1
- data/src/core/ext/filters/client_channel/xds/xds_client.cc +273 -137
- data/src/core/ext/filters/client_channel/xds/xds_client.h +28 -12
- data/src/core/lib/gprpp/sync.h +9 -0
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +32 -30
@@ -71,6 +71,7 @@
|
|
71
71
|
#include <grpc/support/time.h>
|
72
72
|
|
73
73
|
#include "src/core/ext/filters/client_channel/client_channel.h"
|
74
|
+
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
|
74
75
|
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
|
75
76
|
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
|
76
77
|
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
|
@@ -296,14 +297,8 @@ class GrpcLb : public LoadBalancingPolicy {
|
|
296
297
|
void RequestReresolution() override;
|
297
298
|
void AddTraceEvent(TraceSeverity severity, StringView message) override;
|
298
299
|
|
299
|
-
void set_child(LoadBalancingPolicy* child) { child_ = child; }
|
300
|
-
|
301
300
|
private:
|
302
|
-
bool CalledByPendingChild() const;
|
303
|
-
bool CalledByCurrentChild() const;
|
304
|
-
|
305
301
|
RefCountedPtr<GrpcLb> parent_;
|
306
|
-
LoadBalancingPolicy* child_ = nullptr;
|
307
302
|
};
|
308
303
|
|
309
304
|
~GrpcLb();
|
@@ -334,7 +329,7 @@ class GrpcLb : public LoadBalancingPolicy {
|
|
334
329
|
grpc_channel_args* CreateChildPolicyArgsLocked(
|
335
330
|
bool is_backend_from_grpclb_load_balancer);
|
336
331
|
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
|
337
|
-
const
|
332
|
+
const grpc_channel_args* args);
|
338
333
|
void CreateOrUpdateChildPolicyLocked();
|
339
334
|
|
340
335
|
// Who the client is trying to communicate with.
|
@@ -385,9 +380,6 @@ class GrpcLb : public LoadBalancingPolicy {
|
|
385
380
|
|
386
381
|
// The child policy to use for the backends.
|
387
382
|
OrphanablePtr<LoadBalancingPolicy> child_policy_;
|
388
|
-
// When switching child policies, the new policy will be stored here
|
389
|
-
// until it reports READY, at which point it will be moved to child_policy_.
|
390
|
-
OrphanablePtr<LoadBalancingPolicy> pending_child_policy_;
|
391
383
|
// The child policy config.
|
392
384
|
RefCountedPtr<LoadBalancingPolicy::Config> child_policy_config_;
|
393
385
|
// Child policy in state READY.
|
@@ -629,46 +621,15 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
|
|
629
621
|
// GrpcLb::Helper
|
630
622
|
//
|
631
623
|
|
632
|
-
bool GrpcLb::Helper::CalledByPendingChild() const {
|
633
|
-
GPR_ASSERT(child_ != nullptr);
|
634
|
-
return child_ == parent_->pending_child_policy_.get();
|
635
|
-
}
|
636
|
-
|
637
|
-
bool GrpcLb::Helper::CalledByCurrentChild() const {
|
638
|
-
GPR_ASSERT(child_ != nullptr);
|
639
|
-
return child_ == parent_->child_policy_.get();
|
640
|
-
}
|
641
|
-
|
642
624
|
RefCountedPtr<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
|
643
625
|
const grpc_channel_args& args) {
|
644
|
-
if (parent_->shutting_down_
|
645
|
-
(!CalledByPendingChild() && !CalledByCurrentChild())) {
|
646
|
-
return nullptr;
|
647
|
-
}
|
626
|
+
if (parent_->shutting_down_) return nullptr;
|
648
627
|
return parent_->channel_control_helper()->CreateSubchannel(args);
|
649
628
|
}
|
650
629
|
|
651
630
|
void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
|
652
631
|
std::unique_ptr<SubchannelPicker> picker) {
|
653
632
|
if (parent_->shutting_down_) return;
|
654
|
-
// If this request is from the pending child policy, ignore it until
|
655
|
-
// it reports READY, at which point we swap it into place.
|
656
|
-
if (CalledByPendingChild()) {
|
657
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
|
658
|
-
gpr_log(GPR_INFO,
|
659
|
-
"[grpclb %p helper %p] pending child policy %p reports state=%s",
|
660
|
-
parent_.get(), this, parent_->pending_child_policy_.get(),
|
661
|
-
ConnectivityStateName(state));
|
662
|
-
}
|
663
|
-
if (state != GRPC_CHANNEL_READY) return;
|
664
|
-
grpc_pollset_set_del_pollset_set(
|
665
|
-
parent_->child_policy_->interested_parties(),
|
666
|
-
parent_->interested_parties());
|
667
|
-
parent_->child_policy_ = std::move(parent_->pending_child_policy_);
|
668
|
-
} else if (!CalledByCurrentChild()) {
|
669
|
-
// This request is from an outdated child, so ignore it.
|
670
|
-
return;
|
671
|
-
}
|
672
633
|
// Record whether child policy reports READY.
|
673
634
|
parent_->child_policy_ready_ = state == GRPC_CHANNEL_READY;
|
674
635
|
// Enter fallback mode if needed.
|
@@ -721,16 +682,6 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
|
|
721
682
|
|
722
683
|
void GrpcLb::Helper::RequestReresolution() {
|
723
684
|
if (parent_->shutting_down_) return;
|
724
|
-
const LoadBalancingPolicy* latest_child_policy =
|
725
|
-
parent_->pending_child_policy_ != nullptr
|
726
|
-
? parent_->pending_child_policy_.get()
|
727
|
-
: parent_->child_policy_.get();
|
728
|
-
if (child_ != latest_child_policy) return;
|
729
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
|
730
|
-
gpr_log(GPR_INFO,
|
731
|
-
"[grpclb %p] Re-resolution requested from %schild policy (%p).",
|
732
|
-
parent_.get(), CalledByPendingChild() ? "pending " : "", child_);
|
733
|
-
}
|
734
685
|
// If we are talking to a balancer, we expect to get updated addresses
|
735
686
|
// from the balancer, so we can ignore the re-resolution request from
|
736
687
|
// the child policy. Otherwise, pass the re-resolution request up to the
|
@@ -742,10 +693,7 @@ void GrpcLb::Helper::RequestReresolution() {
|
|
742
693
|
}
|
743
694
|
|
744
695
|
void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
|
745
|
-
if (parent_->shutting_down_
|
746
|
-
(!CalledByPendingChild() && !CalledByCurrentChild())) {
|
747
|
-
return;
|
748
|
-
}
|
696
|
+
if (parent_->shutting_down_) return;
|
749
697
|
parent_->channel_control_helper()->AddTraceEvent(severity, message);
|
750
698
|
}
|
751
699
|
|
@@ -1411,13 +1359,8 @@ void GrpcLb::ShutdownLocked() {
|
|
1411
1359
|
if (child_policy_ != nullptr) {
|
1412
1360
|
grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
|
1413
1361
|
interested_parties());
|
1362
|
+
child_policy_.reset();
|
1414
1363
|
}
|
1415
|
-
if (pending_child_policy_ != nullptr) {
|
1416
|
-
grpc_pollset_set_del_pollset_set(
|
1417
|
-
pending_child_policy_->interested_parties(), interested_parties());
|
1418
|
-
}
|
1419
|
-
child_policy_.reset();
|
1420
|
-
pending_child_policy_.reset();
|
1421
1364
|
// We destroy the LB channel here instead of in our destructor because
|
1422
1365
|
// destroying the channel triggers a last callback to
|
1423
1366
|
// OnBalancerChannelConnectivityChangedLocked(), and we need to be
|
@@ -1439,9 +1382,6 @@ void GrpcLb::ResetBackoffLocked() {
|
|
1439
1382
|
if (child_policy_ != nullptr) {
|
1440
1383
|
child_policy_->ResetBackoffLocked();
|
1441
1384
|
}
|
1442
|
-
if (pending_child_policy_ != nullptr) {
|
1443
|
-
pending_child_policy_->ResetBackoffLocked();
|
1444
|
-
}
|
1445
1385
|
}
|
1446
1386
|
|
1447
1387
|
void GrpcLb::UpdateLocked(UpdateArgs args) {
|
@@ -1727,25 +1667,17 @@ grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
|
|
1727
1667
|
}
|
1728
1668
|
|
1729
1669
|
OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
|
1730
|
-
const
|
1731
|
-
Helper* helper = new Helper(Ref());
|
1670
|
+
const grpc_channel_args* args) {
|
1732
1671
|
LoadBalancingPolicy::Args lb_policy_args;
|
1733
1672
|
lb_policy_args.combiner = combiner();
|
1734
1673
|
lb_policy_args.args = args;
|
1735
|
-
lb_policy_args.channel_control_helper =
|
1736
|
-
std::unique_ptr<ChannelControlHelper>(helper);
|
1674
|
+
lb_policy_args.channel_control_helper = absl::make_unique<Helper>(Ref());
|
1737
1675
|
OrphanablePtr<LoadBalancingPolicy> lb_policy =
|
1738
|
-
|
1739
|
-
|
1740
|
-
if (GPR_UNLIKELY(lb_policy == nullptr)) {
|
1741
|
-
gpr_log(GPR_ERROR, "[grpclb %p] Failure creating child policy %s", this,
|
1742
|
-
name);
|
1743
|
-
return nullptr;
|
1744
|
-
}
|
1745
|
-
helper->set_child(lb_policy.get());
|
1676
|
+
MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
|
1677
|
+
&grpc_lb_glb_trace);
|
1746
1678
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
|
1747
|
-
gpr_log(GPR_INFO, "[grpclb %p] Created new child policy
|
1748
|
-
|
1679
|
+
gpr_log(GPR_INFO, "[grpclb %p] Created new child policy handler (%p)", this,
|
1680
|
+
lb_policy.get());
|
1749
1681
|
}
|
1750
1682
|
// Add the gRPC LB's interested_parties pollset_set to that of the newly
|
1751
1683
|
// created child policy. This will make the child policy progress upon
|
@@ -1776,97 +1708,16 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
|
|
1776
1708
|
CreateChildPolicyArgsLocked(is_backend_from_grpclb_load_balancer);
|
1777
1709
|
GPR_ASSERT(update_args.args != nullptr);
|
1778
1710
|
update_args.config = child_policy_config_;
|
1779
|
-
//
|
1780
|
-
|
1781
|
-
|
1782
|
-
// policy transitions into state READY, we swap it into child_policy_,
|
1783
|
-
// replacing the original child policy. So pending_child_policy_ is
|
1784
|
-
// non-null only between when we apply an update that changes the child
|
1785
|
-
// policy name and when the new child reports state READY.
|
1786
|
-
//
|
1787
|
-
// Updates can arrive at any point during this transition. We always
|
1788
|
-
// apply updates relative to the most recently created child policy,
|
1789
|
-
// even if the most recent one is still in pending_child_policy_. This
|
1790
|
-
// is true both when applying the updates to an existing child policy
|
1791
|
-
// and when determining whether we need to create a new policy.
|
1792
|
-
//
|
1793
|
-
// As a result of this, there are several cases to consider here:
|
1794
|
-
//
|
1795
|
-
// 1. We have no existing child policy (i.e., we have started up but
|
1796
|
-
// have not yet received a serverlist from the balancer or gone
|
1797
|
-
// into fallback mode; in this case, both child_policy_ and
|
1798
|
-
// pending_child_policy_ are null). In this case, we create a
|
1799
|
-
// new child policy and store it in child_policy_.
|
1800
|
-
//
|
1801
|
-
// 2. We have an existing child policy and have no pending child policy
|
1802
|
-
// from a previous update (i.e., either there has not been a
|
1803
|
-
// previous update that changed the policy name, or we have already
|
1804
|
-
// finished swapping in the new policy; in this case, child_policy_
|
1805
|
-
// is non-null but pending_child_policy_ is null). In this case:
|
1806
|
-
// a. If child_policy_->name() equals child_policy_name, then we
|
1807
|
-
// update the existing child policy.
|
1808
|
-
// b. If child_policy_->name() does not equal child_policy_name,
|
1809
|
-
// we create a new policy. The policy will be stored in
|
1810
|
-
// pending_child_policy_ and will later be swapped into
|
1811
|
-
// child_policy_ by the helper when the new child transitions
|
1812
|
-
// into state READY.
|
1813
|
-
//
|
1814
|
-
// 3. We have an existing child policy and have a pending child policy
|
1815
|
-
// from a previous update (i.e., a previous update set
|
1816
|
-
// pending_child_policy_ as per case 2b above and that policy has
|
1817
|
-
// not yet transitioned into state READY and been swapped into
|
1818
|
-
// child_policy_; in this case, both child_policy_ and
|
1819
|
-
// pending_child_policy_ are non-null). In this case:
|
1820
|
-
// a. If pending_child_policy_->name() equals child_policy_name,
|
1821
|
-
// then we update the existing pending child policy.
|
1822
|
-
// b. If pending_child_policy->name() does not equal
|
1823
|
-
// child_policy_name, then we create a new policy. The new
|
1824
|
-
// policy is stored in pending_child_policy_ (replacing the one
|
1825
|
-
// that was there before, which will be immediately shut down)
|
1826
|
-
// and will later be swapped into child_policy_ by the helper
|
1827
|
-
// when the new child transitions into state READY.
|
1828
|
-
const char* child_policy_name = child_policy_config_ == nullptr
|
1829
|
-
? "round_robin"
|
1830
|
-
: child_policy_config_->name();
|
1831
|
-
const bool create_policy =
|
1832
|
-
// case 1
|
1833
|
-
child_policy_ == nullptr ||
|
1834
|
-
// case 2b
|
1835
|
-
(pending_child_policy_ == nullptr &&
|
1836
|
-
strcmp(child_policy_->name(), child_policy_name) != 0) ||
|
1837
|
-
// case 3b
|
1838
|
-
(pending_child_policy_ != nullptr &&
|
1839
|
-
strcmp(pending_child_policy_->name(), child_policy_name) != 0);
|
1840
|
-
LoadBalancingPolicy* policy_to_update = nullptr;
|
1841
|
-
if (create_policy) {
|
1842
|
-
// Cases 1, 2b, and 3b: create a new child policy.
|
1843
|
-
// If child_policy_ is null, we set it (case 1), else we set
|
1844
|
-
// pending_child_policy_ (cases 2b and 3b).
|
1845
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
|
1846
|
-
gpr_log(GPR_INFO, "[grpclb %p] Creating new %schild policy %s", this,
|
1847
|
-
child_policy_ == nullptr ? "" : "pending ", child_policy_name);
|
1848
|
-
}
|
1849
|
-
// Swap the policy into place.
|
1850
|
-
auto& lb_policy =
|
1851
|
-
child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
|
1852
|
-
lb_policy = CreateChildPolicyLocked(child_policy_name, update_args.args);
|
1853
|
-
policy_to_update = lb_policy.get();
|
1854
|
-
} else {
|
1855
|
-
// Cases 2a and 3a: update an existing policy.
|
1856
|
-
// If we have a pending child policy, send the update to the pending
|
1857
|
-
// policy (case 3a), else send it to the current policy (case 2a).
|
1858
|
-
policy_to_update = pending_child_policy_ != nullptr
|
1859
|
-
? pending_child_policy_.get()
|
1860
|
-
: child_policy_.get();
|
1711
|
+
// Create child policy if needed.
|
1712
|
+
if (child_policy_ == nullptr) {
|
1713
|
+
child_policy_ = CreateChildPolicyLocked(update_args.args);
|
1861
1714
|
}
|
1862
|
-
GPR_ASSERT(policy_to_update != nullptr);
|
1863
1715
|
// Update the policy.
|
1864
1716
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
|
1865
|
-
gpr_log(GPR_INFO, "[grpclb %p] Updating
|
1866
|
-
|
1867
|
-
policy_to_update);
|
1717
|
+
gpr_log(GPR_INFO, "[grpclb %p] Updating child policy handler %p", this,
|
1718
|
+
child_policy_.get());
|
1868
1719
|
}
|
1869
|
-
|
1720
|
+
child_policy_->UpdateLocked(std::move(update_args));
|
1870
1721
|
}
|
1871
1722
|
|
1872
1723
|
//
|
@@ -1889,21 +1740,29 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory {
|
|
1889
1740
|
return MakeRefCounted<GrpcLbConfig>(nullptr);
|
1890
1741
|
}
|
1891
1742
|
std::vector<grpc_error*> error_list;
|
1892
|
-
|
1743
|
+
Json child_policy_config_json_tmp;
|
1744
|
+
const Json* child_policy_config_json;
|
1893
1745
|
auto it = json.object_value().find("childPolicy");
|
1894
|
-
if (it
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1746
|
+
if (it == json.object_value().end()) {
|
1747
|
+
child_policy_config_json_tmp = Json::Array{Json::Object{
|
1748
|
+
{"round_robin", Json::Object()},
|
1749
|
+
}};
|
1750
|
+
child_policy_config_json = &child_policy_config_json_tmp;
|
1751
|
+
} else {
|
1752
|
+
child_policy_config_json = &it->second;
|
1753
|
+
}
|
1754
|
+
grpc_error* parse_error = GRPC_ERROR_NONE;
|
1755
|
+
RefCountedPtr<LoadBalancingPolicy::Config> child_policy_config =
|
1756
|
+
LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
|
1757
|
+
*child_policy_config_json, &parse_error);
|
1758
|
+
if (parse_error != GRPC_ERROR_NONE) {
|
1759
|
+
std::vector<grpc_error*> child_errors;
|
1760
|
+
child_errors.push_back(parse_error);
|
1761
|
+
error_list.push_back(
|
1762
|
+
GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
|
1904
1763
|
}
|
1905
1764
|
if (error_list.empty()) {
|
1906
|
-
return MakeRefCounted<GrpcLbConfig>(std::move(
|
1765
|
+
return MakeRefCounted<GrpcLbConfig>(std::move(child_policy_config));
|
1907
1766
|
} else {
|
1908
1767
|
*error = GRPC_ERROR_CREATE_FROM_VECTOR("GrpcLb Parser", &error_list);
|
1909
1768
|
return nullptr;
|
@@ -113,8 +113,14 @@ class CdsLb : public LoadBalancingPolicy {
|
|
113
113
|
|
114
114
|
void CdsLb::ClusterWatcher::OnClusterChanged(XdsApi::CdsUpdate cluster_data) {
|
115
115
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
116
|
-
gpr_log(GPR_INFO,
|
117
|
-
|
116
|
+
gpr_log(GPR_INFO,
|
117
|
+
"[cdslb %p] received CDS update from xds client %p: "
|
118
|
+
"eds_service_name=%s lrs_load_reporting_server_name=%s",
|
119
|
+
parent_.get(), parent_->xds_client_.get(),
|
120
|
+
cluster_data.eds_service_name.c_str(),
|
121
|
+
cluster_data.lrs_load_reporting_server_name.has_value()
|
122
|
+
? cluster_data.lrs_load_reporting_server_name.value().c_str()
|
123
|
+
: "(unset)");
|
118
124
|
}
|
119
125
|
// Construct config for child policy.
|
120
126
|
Json::Object child_config = {
|
@@ -152,9 +158,18 @@ void CdsLb::ClusterWatcher::OnClusterChanged(XdsApi::CdsUpdate cluster_data) {
|
|
152
158
|
parent_->child_policy_ =
|
153
159
|
LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
|
154
160
|
"xds_experimental", std::move(args));
|
161
|
+
if (parent_->child_policy_ == nullptr) {
|
162
|
+
OnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
163
|
+
"failed to create xds_experimental child policy"));
|
164
|
+
return;
|
165
|
+
}
|
155
166
|
grpc_pollset_set_add_pollset_set(
|
156
167
|
parent_->child_policy_->interested_parties(),
|
157
168
|
parent_->interested_parties());
|
169
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
170
|
+
gpr_log(GPR_INFO, "[cdslb %p] created child policy xds_experimental (%p)",
|
171
|
+
parent_.get(), parent_->child_policy_.get());
|
172
|
+
}
|
158
173
|
}
|
159
174
|
// Update child policy.
|
160
175
|
UpdateArgs args;
|
@@ -220,9 +235,9 @@ void CdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
|
|
220
235
|
CdsLb::CdsLb(Args args)
|
221
236
|
: LoadBalancingPolicy(std::move(args)),
|
222
237
|
xds_client_(XdsClient::GetFromChannelArgs(*args.args)) {
|
223
|
-
if (
|
224
|
-
gpr_log(GPR_INFO, "[cdslb %p]
|
225
|
-
xds_client_.get());
|
238
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
239
|
+
gpr_log(GPR_INFO, "[cdslb %p] created -- using xds client %p from channel",
|
240
|
+
this, xds_client_.get());
|
226
241
|
}
|
227
242
|
}
|
228
243
|
|
@@ -245,6 +260,10 @@ void CdsLb::ShutdownLocked() {
|
|
245
260
|
}
|
246
261
|
if (xds_client_ != nullptr) {
|
247
262
|
if (cluster_watcher_ != nullptr) {
|
263
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
264
|
+
gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
|
265
|
+
config_->cluster().c_str());
|
266
|
+
}
|
248
267
|
xds_client_->CancelClusterDataWatch(
|
249
268
|
StringView(config_->cluster().c_str()), cluster_watcher_);
|
250
269
|
}
|
@@ -257,12 +276,13 @@ void CdsLb::ResetBackoffLocked() {
|
|
257
276
|
}
|
258
277
|
|
259
278
|
void CdsLb::UpdateLocked(UpdateArgs args) {
|
260
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
261
|
-
gpr_log(GPR_INFO, "[cdslb %p] received update", this);
|
262
|
-
}
|
263
279
|
// Update config.
|
264
280
|
auto old_config = std::move(config_);
|
265
281
|
config_ = std::move(args.config);
|
282
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
283
|
+
gpr_log(GPR_INFO, "[cdslb %p] received update: cluster=%s", this,
|
284
|
+
config_->cluster().c_str());
|
285
|
+
}
|
266
286
|
// Update args.
|
267
287
|
grpc_channel_args_destroy(args_);
|
268
288
|
args_ = args.args;
|
@@ -270,8 +290,17 @@ void CdsLb::UpdateLocked(UpdateArgs args) {
|
|
270
290
|
// If cluster name changed, cancel watcher and restart.
|
271
291
|
if (old_config == nullptr || old_config->cluster() != config_->cluster()) {
|
272
292
|
if (old_config != nullptr) {
|
293
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
294
|
+
gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
|
295
|
+
old_config->cluster().c_str());
|
296
|
+
}
|
273
297
|
xds_client_->CancelClusterDataWatch(
|
274
|
-
StringView(old_config->cluster().c_str()), cluster_watcher_
|
298
|
+
StringView(old_config->cluster().c_str()), cluster_watcher_,
|
299
|
+
/*delay_unsubscription=*/true);
|
300
|
+
}
|
301
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
|
302
|
+
gpr_log(GPR_INFO, "[cdslb %p] starting watch for cluster %s", this,
|
303
|
+
config_->cluster().c_str());
|
275
304
|
}
|
276
305
|
auto watcher = absl::make_unique<ClusterWatcher>(Ref());
|
277
306
|
cluster_watcher_ = watcher.get();
|
@@ -25,6 +25,8 @@
|
|
25
25
|
#include <limits.h>
|
26
26
|
#include <string.h>
|
27
27
|
|
28
|
+
#include "absl/types/optional.h"
|
29
|
+
|
28
30
|
#include <grpc/grpc.h>
|
29
31
|
#include <grpc/support/alloc.h>
|
30
32
|
#include <grpc/support/string_util.h>
|
@@ -32,6 +34,7 @@
|
|
32
34
|
|
33
35
|
#include "src/core/ext/filters/client_channel/client_channel.h"
|
34
36
|
#include "src/core/ext/filters/client_channel/lb_policy.h"
|
37
|
+
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
|
35
38
|
#include "src/core/ext/filters/client_channel/lb_policy/xds/xds.h"
|
36
39
|
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
|
37
40
|
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
|
@@ -68,7 +71,7 @@
|
|
68
71
|
|
69
72
|
namespace grpc_core {
|
70
73
|
|
71
|
-
TraceFlag grpc_lb_xds_trace(false, "
|
74
|
+
TraceFlag grpc_lb_xds_trace(false, "xds_lb");
|
72
75
|
|
73
76
|
namespace {
|
74
77
|
|
@@ -79,7 +82,7 @@ class XdsConfig : public LoadBalancingPolicy::Config {
|
|
79
82
|
XdsConfig(RefCountedPtr<LoadBalancingPolicy::Config> child_policy,
|
80
83
|
RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy,
|
81
84
|
std::string eds_service_name,
|
82
|
-
|
85
|
+
absl::optional<std::string> lrs_load_reporting_server_name)
|
83
86
|
: child_policy_(std::move(child_policy)),
|
84
87
|
fallback_policy_(std::move(fallback_policy)),
|
85
88
|
eds_service_name_(std::move(eds_service_name)),
|
@@ -100,7 +103,7 @@ class XdsConfig : public LoadBalancingPolicy::Config {
|
|
100
103
|
return eds_service_name_.empty() ? nullptr : eds_service_name_.c_str();
|
101
104
|
};
|
102
105
|
|
103
|
-
const
|
106
|
+
const absl::optional<std::string>& lrs_load_reporting_server_name() const {
|
104
107
|
return lrs_load_reporting_server_name_;
|
105
108
|
};
|
106
109
|
|
@@ -108,7 +111,7 @@ class XdsConfig : public LoadBalancingPolicy::Config {
|
|
108
111
|
RefCountedPtr<LoadBalancingPolicy::Config> child_policy_;
|
109
112
|
RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy_;
|
110
113
|
std::string eds_service_name_;
|
111
|
-
|
114
|
+
absl::optional<std::string> lrs_load_reporting_server_name_;
|
112
115
|
};
|
113
116
|
|
114
117
|
class XdsLb : public LoadBalancingPolicy {
|
@@ -198,14 +201,8 @@ class XdsLb : public LoadBalancingPolicy {
|
|
198
201
|
void RequestReresolution() override;
|
199
202
|
void AddTraceEvent(TraceSeverity severity, StringView message) override;
|
200
203
|
|
201
|
-
void set_child(LoadBalancingPolicy* child) { child_ = child; }
|
202
|
-
|
203
204
|
private:
|
204
|
-
bool CalledByPendingFallback() const;
|
205
|
-
bool CalledByCurrentFallback() const;
|
206
|
-
|
207
205
|
RefCountedPtr<XdsLb> parent_;
|
208
|
-
LoadBalancingPolicy* child_ = nullptr;
|
209
206
|
};
|
210
207
|
|
211
208
|
// Each LocalityMap holds a ref to the XdsLb.
|
@@ -262,19 +259,14 @@ class XdsLb : public LoadBalancingPolicy {
|
|
262
259
|
// client, which is a watch-based API.
|
263
260
|
void RequestReresolution() override {}
|
264
261
|
void AddTraceEvent(TraceSeverity severity, StringView message) override;
|
265
|
-
void set_child(LoadBalancingPolicy* child) { child_ = child; }
|
266
262
|
|
267
263
|
private:
|
268
|
-
bool CalledByPendingChild() const;
|
269
|
-
bool CalledByCurrentChild() const;
|
270
|
-
|
271
264
|
RefCountedPtr<Locality> locality_;
|
272
|
-
LoadBalancingPolicy* child_ = nullptr;
|
273
265
|
};
|
274
266
|
|
275
267
|
// Methods for dealing with the child policy.
|
276
268
|
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
|
277
|
-
const
|
269
|
+
const grpc_channel_args* args);
|
278
270
|
grpc_channel_args* CreateChildPolicyArgsLocked(
|
279
271
|
const grpc_channel_args* args);
|
280
272
|
|
@@ -291,7 +283,6 @@ class XdsLb : public LoadBalancingPolicy {
|
|
291
283
|
RefCountedPtr<XdsLocalityName> name_;
|
292
284
|
RefCountedPtr<XdsClusterLocalityStats> stats_;
|
293
285
|
OrphanablePtr<LoadBalancingPolicy> child_policy_;
|
294
|
-
OrphanablePtr<LoadBalancingPolicy> pending_child_policy_;
|
295
286
|
RefCountedPtr<RefCountedEndpointPicker> picker_wrapper_;
|
296
287
|
RefCountedPtr<LoadReportingPicker> load_reporting_picker_;
|
297
288
|
grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_IDLE;
|
@@ -309,7 +300,7 @@ class XdsLb : public LoadBalancingPolicy {
|
|
309
300
|
~LocalityMap() { xds_policy_.reset(DEBUG_LOCATION, "LocalityMap"); }
|
310
301
|
|
311
302
|
void UpdateLocked(
|
312
|
-
const XdsApi::PriorityListUpdate::LocalityMap&
|
303
|
+
const XdsApi::PriorityListUpdate::LocalityMap& priority_update,
|
313
304
|
bool update_locality_stats);
|
314
305
|
void ResetBackoffLocked();
|
315
306
|
void UpdateXdsPickerLocked();
|
@@ -403,7 +394,7 @@ class XdsLb : public LoadBalancingPolicy {
|
|
403
394
|
static void OnFallbackTimerLocked(void* arg, grpc_error* error);
|
404
395
|
void UpdateFallbackPolicyLocked();
|
405
396
|
OrphanablePtr<LoadBalancingPolicy> CreateFallbackPolicyLocked(
|
406
|
-
const
|
397
|
+
const grpc_channel_args* args);
|
407
398
|
void MaybeExitFallbackMode();
|
408
399
|
|
409
400
|
// Server name from target URI.
|
@@ -445,7 +436,6 @@ class XdsLb : public LoadBalancingPolicy {
|
|
445
436
|
|
446
437
|
// Non-null iff we are in fallback mode.
|
447
438
|
OrphanablePtr<LoadBalancingPolicy> fallback_policy_;
|
448
|
-
OrphanablePtr<LoadBalancingPolicy> pending_fallback_policy_;
|
449
439
|
|
450
440
|
const grpc_millis locality_retention_interval_ms_;
|
451
441
|
const grpc_millis locality_map_failover_timeout_ms_;
|
@@ -506,6 +496,16 @@ XdsLb::PickResult XdsLb::LocalityPicker::Pick(PickArgs args) {
|
|
506
496
|
result.type = PickResult::PICK_COMPLETE;
|
507
497
|
return result;
|
508
498
|
}
|
499
|
+
// If we didn't drop, we better have some localities to pick from.
|
500
|
+
if (pickers_.empty()) { // Should never happen.
|
501
|
+
PickResult result;
|
502
|
+
result.type = PickResult::PICK_FAILED;
|
503
|
+
result.error =
|
504
|
+
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
505
|
+
"xds picker not given any localities"),
|
506
|
+
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
|
507
|
+
return result;
|
508
|
+
}
|
509
509
|
// Generate a random number in [0, total weight).
|
510
510
|
const uint32_t key = rand() % pickers_[pickers_.size() - 1].first;
|
511
511
|
// Forward pick to whichever locality maps to the range in which the
|
@@ -539,71 +539,26 @@ XdsLb::PickResult XdsLb::LocalityPicker::PickFromLocality(const uint32_t key,
|
|
539
539
|
// XdsLb::FallbackHelper
|
540
540
|
//
|
541
541
|
|
542
|
-
bool XdsLb::FallbackHelper::CalledByPendingFallback() const {
|
543
|
-
GPR_ASSERT(child_ != nullptr);
|
544
|
-
return child_ == parent_->pending_fallback_policy_.get();
|
545
|
-
}
|
546
|
-
|
547
|
-
bool XdsLb::FallbackHelper::CalledByCurrentFallback() const {
|
548
|
-
GPR_ASSERT(child_ != nullptr);
|
549
|
-
return child_ == parent_->fallback_policy_.get();
|
550
|
-
}
|
551
|
-
|
552
542
|
RefCountedPtr<SubchannelInterface> XdsLb::FallbackHelper::CreateSubchannel(
|
553
543
|
const grpc_channel_args& args) {
|
554
|
-
if (parent_->shutting_down_
|
555
|
-
(!CalledByPendingFallback() && !CalledByCurrentFallback())) {
|
556
|
-
return nullptr;
|
557
|
-
}
|
544
|
+
if (parent_->shutting_down_) return nullptr;
|
558
545
|
return parent_->channel_control_helper()->CreateSubchannel(args);
|
559
546
|
}
|
560
547
|
|
561
548
|
void XdsLb::FallbackHelper::UpdateState(
|
562
549
|
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) {
|
563
550
|
if (parent_->shutting_down_) return;
|
564
|
-
// If this request is from the pending fallback policy, ignore it until
|
565
|
-
// it reports READY, at which point we swap it into place.
|
566
|
-
if (CalledByPendingFallback()) {
|
567
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
568
|
-
gpr_log(
|
569
|
-
GPR_INFO,
|
570
|
-
"[xdslb %p helper %p] pending fallback policy %p reports state=%s",
|
571
|
-
parent_.get(), this, parent_->pending_fallback_policy_.get(),
|
572
|
-
ConnectivityStateName(state));
|
573
|
-
}
|
574
|
-
if (state != GRPC_CHANNEL_READY) return;
|
575
|
-
grpc_pollset_set_del_pollset_set(
|
576
|
-
parent_->fallback_policy_->interested_parties(),
|
577
|
-
parent_->interested_parties());
|
578
|
-
parent_->fallback_policy_ = std::move(parent_->pending_fallback_policy_);
|
579
|
-
} else if (!CalledByCurrentFallback()) {
|
580
|
-
// This request is from an outdated fallback policy, so ignore it.
|
581
|
-
return;
|
582
|
-
}
|
583
551
|
parent_->channel_control_helper()->UpdateState(state, std::move(picker));
|
584
552
|
}
|
585
553
|
|
586
554
|
void XdsLb::FallbackHelper::RequestReresolution() {
|
587
555
|
if (parent_->shutting_down_) return;
|
588
|
-
const LoadBalancingPolicy* latest_fallback_policy =
|
589
|
-
parent_->pending_fallback_policy_ != nullptr
|
590
|
-
? parent_->pending_fallback_policy_.get()
|
591
|
-
: parent_->fallback_policy_.get();
|
592
|
-
if (child_ != latest_fallback_policy) return;
|
593
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
594
|
-
gpr_log(GPR_INFO,
|
595
|
-
"[xdslb %p] Re-resolution requested from the fallback policy (%p).",
|
596
|
-
parent_.get(), child_);
|
597
|
-
}
|
598
556
|
parent_->channel_control_helper()->RequestReresolution();
|
599
557
|
}
|
600
558
|
|
601
559
|
void XdsLb::FallbackHelper::AddTraceEvent(TraceSeverity severity,
|
602
560
|
StringView message) {
|
603
|
-
if (parent_->shutting_down_
|
604
|
-
(!CalledByPendingFallback() && !CalledByCurrentFallback())) {
|
605
|
-
return;
|
606
|
-
}
|
561
|
+
if (parent_->shutting_down_) return;
|
607
562
|
parent_->channel_control_helper()->AddTraceEvent(severity, message);
|
608
563
|
}
|
609
564
|
|
@@ -625,7 +580,7 @@ class XdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
|
|
625
580
|
}
|
626
581
|
// If the balancer tells us to drop all the calls, we should exit fallback
|
627
582
|
// mode immediately.
|
628
|
-
if (update.drop_all) xds_policy_->MaybeExitFallbackMode();
|
583
|
+
if (update.drop_config->drop_all()) xds_policy_->MaybeExitFallbackMode();
|
629
584
|
// Update the drop config.
|
630
585
|
const bool drop_config_changed =
|
631
586
|
xds_policy_->drop_config_ == nullptr ||
|
@@ -676,6 +631,9 @@ class XdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
|
|
676
631
|
if (strstr(grpc_error_string(error), "xds call failed")) {
|
677
632
|
xds_policy_->channel_control_helper()->RequestReresolution();
|
678
633
|
}
|
634
|
+
} else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
635
|
+
gpr_log(GPR_INFO, "[xdslb %p] xds watcher reported error (ignoring): %s",
|
636
|
+
xds_policy_.get(), grpc_error_string(error));
|
679
637
|
}
|
680
638
|
GRPC_ERROR_UNREF(error);
|
681
639
|
}
|
@@ -700,9 +658,8 @@ XdsLb::XdsLb(Args args)
|
|
700
658
|
locality_map_failover_timeout_ms_(grpc_channel_args_find_integer(
|
701
659
|
args.args, GRPC_ARG_XDS_FAILOVER_TIMEOUT_MS,
|
702
660
|
{GRPC_XDS_DEFAULT_FAILOVER_TIMEOUT_MS, 0, INT_MAX})) {
|
703
|
-
if (
|
704
|
-
|
705
|
-
gpr_log(GPR_INFO, "[xdslb %p] Using xds client %p from channel", this,
|
661
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
662
|
+
gpr_log(GPR_INFO, "[xdslb %p] created -- xds client from channel: %p", this,
|
706
663
|
xds_client_from_channel_.get());
|
707
664
|
}
|
708
665
|
// Record server name.
|
@@ -737,18 +694,17 @@ void XdsLb::ShutdownLocked() {
|
|
737
694
|
if (fallback_policy_ != nullptr) {
|
738
695
|
grpc_pollset_set_del_pollset_set(fallback_policy_->interested_parties(),
|
739
696
|
interested_parties());
|
697
|
+
fallback_policy_.reset();
|
740
698
|
}
|
741
|
-
if (pending_fallback_policy_ != nullptr) {
|
742
|
-
grpc_pollset_set_del_pollset_set(
|
743
|
-
pending_fallback_policy_->interested_parties(), interested_parties());
|
744
|
-
}
|
745
|
-
fallback_policy_.reset();
|
746
|
-
pending_fallback_policy_.reset();
|
747
699
|
// Cancel the endpoint watch here instead of in our dtor if we are using the
|
748
700
|
// XdsResolver, because the watcher holds a ref to us and we might not be
|
749
701
|
// destroying the Xds client leading to a situation where the Xds lb policy is
|
750
702
|
// never destroyed.
|
751
703
|
if (xds_client_from_channel_ != nullptr) {
|
704
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
705
|
+
gpr_log(GPR_INFO, "[xdslb %p] cancelling watch for %s", this,
|
706
|
+
eds_service_name());
|
707
|
+
}
|
752
708
|
xds_client()->CancelEndpointDataWatch(StringView(eds_service_name()),
|
753
709
|
endpoint_watcher_);
|
754
710
|
xds_client_from_channel_.reset();
|
@@ -771,9 +727,6 @@ void XdsLb::ResetBackoffLocked() {
|
|
771
727
|
if (fallback_policy_ != nullptr) {
|
772
728
|
fallback_policy_->ResetBackoffLocked();
|
773
729
|
}
|
774
|
-
if (pending_fallback_policy_ != nullptr) {
|
775
|
-
pending_fallback_policy_->ResetBackoffLocked();
|
776
|
-
}
|
777
730
|
}
|
778
731
|
|
779
732
|
void XdsLb::UpdateLocked(UpdateArgs args) {
|
@@ -782,7 +735,6 @@ void XdsLb::UpdateLocked(UpdateArgs args) {
|
|
782
735
|
}
|
783
736
|
const bool is_initial_update = args_ == nullptr;
|
784
737
|
// Update config.
|
785
|
-
const char* old_eds_service_name = eds_service_name();
|
786
738
|
auto old_config = std::move(config_);
|
787
739
|
config_ = std::move(args.config);
|
788
740
|
// Update fallback address list.
|
@@ -830,30 +782,27 @@ void XdsLb::UpdateLocked(UpdateArgs args) {
|
|
830
782
|
eds_service_name(), eds_service_name());
|
831
783
|
}
|
832
784
|
}
|
833
|
-
//
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
if (!is_initial_update) {
|
839
|
-
const bool update_locality_stats =
|
840
|
-
config_->lrs_load_reporting_server_name() !=
|
841
|
-
old_config->lrs_load_reporting_server_name() ||
|
842
|
-
strcmp(old_eds_service_name, eds_service_name()) != 0;
|
843
|
-
UpdatePrioritiesLocked(update_locality_stats);
|
844
|
-
}
|
845
|
-
// Update endpoint watcher if needed.
|
846
|
-
if (is_initial_update ||
|
847
|
-
strcmp(old_eds_service_name, eds_service_name()) != 0) {
|
848
|
-
if (!is_initial_update) {
|
849
|
-
xds_client()->CancelEndpointDataWatch(StringView(old_eds_service_name),
|
850
|
-
endpoint_watcher_);
|
785
|
+
// On the initial update, create the endpoint watcher.
|
786
|
+
if (is_initial_update) {
|
787
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
788
|
+
gpr_log(GPR_INFO, "[xdslb %p] starting watch for %s", this,
|
789
|
+
eds_service_name());
|
851
790
|
}
|
852
791
|
auto watcher = absl::make_unique<EndpointWatcher>(
|
853
792
|
Ref(DEBUG_LOCATION, "EndpointWatcher"));
|
854
793
|
endpoint_watcher_ = watcher.get();
|
855
794
|
xds_client()->WatchEndpointData(StringView(eds_service_name()),
|
856
795
|
std::move(watcher));
|
796
|
+
} else {
|
797
|
+
// Update priority list.
|
798
|
+
// Note that this comes after updating drop_stats_, since we want that
|
799
|
+
// to be used by any new picker we create here.
|
800
|
+
// No need to do this on the initial update, since there won't be any
|
801
|
+
// priorities to update yet.
|
802
|
+
const bool update_locality_stats =
|
803
|
+
config_->lrs_load_reporting_server_name() !=
|
804
|
+
old_config->lrs_load_reporting_server_name();
|
805
|
+
UpdatePrioritiesLocked(update_locality_stats);
|
857
806
|
}
|
858
807
|
}
|
859
808
|
|
@@ -896,127 +845,37 @@ void XdsLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
|
|
896
845
|
|
897
846
|
void XdsLb::UpdateFallbackPolicyLocked() {
|
898
847
|
if (shutting_down_) return;
|
899
|
-
//
|
848
|
+
// Create policy if needed.
|
849
|
+
if (fallback_policy_ == nullptr) {
|
850
|
+
fallback_policy_ = CreateFallbackPolicyLocked(args_);
|
851
|
+
GPR_ASSERT(fallback_policy_ != nullptr);
|
852
|
+
}
|
853
|
+
// Perform update.
|
900
854
|
UpdateArgs update_args;
|
901
855
|
update_args.addresses = fallback_backend_addresses_;
|
902
856
|
update_args.config = config_->fallback_policy();
|
903
857
|
update_args.args = grpc_channel_args_copy(args_);
|
904
|
-
// If the child policy name changes, we need to create a new child
|
905
|
-
// policy. When this happens, we leave child_policy_ as-is and store
|
906
|
-
// the new child policy in pending_child_policy_. Once the new child
|
907
|
-
// policy transitions into state READY, we swap it into child_policy_,
|
908
|
-
// replacing the original child policy. So pending_child_policy_ is
|
909
|
-
// non-null only between when we apply an update that changes the child
|
910
|
-
// policy name and when the new child reports state READY.
|
911
|
-
//
|
912
|
-
// Updates can arrive at any point during this transition. We always
|
913
|
-
// apply updates relative to the most recently created child policy,
|
914
|
-
// even if the most recent one is still in pending_child_policy_. This
|
915
|
-
// is true both when applying the updates to an existing child policy
|
916
|
-
// and when determining whether we need to create a new policy.
|
917
|
-
//
|
918
|
-
// As a result of this, there are several cases to consider here:
|
919
|
-
//
|
920
|
-
// 1. We have no existing child policy (i.e., we have started up but
|
921
|
-
// have not yet received a serverlist from the balancer or gone
|
922
|
-
// into fallback mode; in this case, both child_policy_ and
|
923
|
-
// pending_child_policy_ are null). In this case, we create a
|
924
|
-
// new child policy and store it in child_policy_.
|
925
|
-
//
|
926
|
-
// 2. We have an existing child policy and have no pending child policy
|
927
|
-
// from a previous update (i.e., either there has not been a
|
928
|
-
// previous update that changed the policy name, or we have already
|
929
|
-
// finished swapping in the new policy; in this case, child_policy_
|
930
|
-
// is non-null but pending_child_policy_ is null). In this case:
|
931
|
-
// a. If child_policy_->name() equals child_policy_name, then we
|
932
|
-
// update the existing child policy.
|
933
|
-
// b. If child_policy_->name() does not equal child_policy_name,
|
934
|
-
// we create a new policy. The policy will be stored in
|
935
|
-
// pending_child_policy_ and will later be swapped into
|
936
|
-
// child_policy_ by the helper when the new child transitions
|
937
|
-
// into state READY.
|
938
|
-
//
|
939
|
-
// 3. We have an existing child policy and have a pending child policy
|
940
|
-
// from a previous update (i.e., a previous update set
|
941
|
-
// pending_child_policy_ as per case 2b above and that policy has
|
942
|
-
// not yet transitioned into state READY and been swapped into
|
943
|
-
// child_policy_; in this case, both child_policy_ and
|
944
|
-
// pending_child_policy_ are non-null). In this case:
|
945
|
-
// a. If pending_child_policy_->name() equals child_policy_name,
|
946
|
-
// then we update the existing pending child policy.
|
947
|
-
// b. If pending_child_policy->name() does not equal
|
948
|
-
// child_policy_name, then we create a new policy. The new
|
949
|
-
// policy is stored in pending_child_policy_ (replacing the one
|
950
|
-
// that was there before, which will be immediately shut down)
|
951
|
-
// and will later be swapped into child_policy_ by the helper
|
952
|
-
// when the new child transitions into state READY.
|
953
|
-
const char* fallback_policy_name = update_args.config == nullptr
|
954
|
-
? "round_robin"
|
955
|
-
: update_args.config->name();
|
956
|
-
const bool create_policy =
|
957
|
-
// case 1
|
958
|
-
fallback_policy_ == nullptr ||
|
959
|
-
// case 2b
|
960
|
-
(pending_fallback_policy_ == nullptr &&
|
961
|
-
strcmp(fallback_policy_->name(), fallback_policy_name) != 0) ||
|
962
|
-
// case 3b
|
963
|
-
(pending_fallback_policy_ != nullptr &&
|
964
|
-
strcmp(pending_fallback_policy_->name(), fallback_policy_name) != 0);
|
965
|
-
LoadBalancingPolicy* policy_to_update = nullptr;
|
966
|
-
if (create_policy) {
|
967
|
-
// Cases 1, 2b, and 3b: create a new child policy.
|
968
|
-
// If child_policy_ is null, we set it (case 1), else we set
|
969
|
-
// pending_child_policy_ (cases 2b and 3b).
|
970
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
971
|
-
gpr_log(GPR_INFO, "[xdslb %p] Creating new %sfallback policy %s", this,
|
972
|
-
fallback_policy_ == nullptr ? "" : "pending ",
|
973
|
-
fallback_policy_name);
|
974
|
-
}
|
975
|
-
auto& lb_policy = fallback_policy_ == nullptr ? fallback_policy_
|
976
|
-
: pending_fallback_policy_;
|
977
|
-
lb_policy =
|
978
|
-
CreateFallbackPolicyLocked(fallback_policy_name, update_args.args);
|
979
|
-
policy_to_update = lb_policy.get();
|
980
|
-
} else {
|
981
|
-
// Cases 2a and 3a: update an existing policy.
|
982
|
-
// If we have a pending child policy, send the update to the pending
|
983
|
-
// policy (case 3a), else send it to the current policy (case 2a).
|
984
|
-
policy_to_update = pending_fallback_policy_ != nullptr
|
985
|
-
? pending_fallback_policy_.get()
|
986
|
-
: fallback_policy_.get();
|
987
|
-
}
|
988
|
-
GPR_ASSERT(policy_to_update != nullptr);
|
989
|
-
// Update the policy.
|
990
858
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
991
|
-
gpr_log(
|
992
|
-
|
993
|
-
policy_to_update == pending_fallback_policy_.get() ? "pending " : "",
|
994
|
-
policy_to_update);
|
859
|
+
gpr_log(GPR_INFO, "[xdslb %p] Updating fallback child policy handler %p",
|
860
|
+
this, fallback_policy_.get());
|
995
861
|
}
|
996
|
-
|
862
|
+
fallback_policy_->UpdateLocked(std::move(update_args));
|
997
863
|
}
|
998
864
|
|
999
865
|
OrphanablePtr<LoadBalancingPolicy> XdsLb::CreateFallbackPolicyLocked(
|
1000
|
-
const
|
1001
|
-
FallbackHelper* helper =
|
1002
|
-
new FallbackHelper(Ref(DEBUG_LOCATION, "FallbackHelper"));
|
866
|
+
const grpc_channel_args* args) {
|
1003
867
|
LoadBalancingPolicy::Args lb_policy_args;
|
1004
868
|
lb_policy_args.combiner = combiner();
|
1005
869
|
lb_policy_args.args = args;
|
1006
870
|
lb_policy_args.channel_control_helper =
|
1007
|
-
|
871
|
+
absl::make_unique<FallbackHelper>(Ref(DEBUG_LOCATION, "FallbackHelper"));
|
1008
872
|
OrphanablePtr<LoadBalancingPolicy> lb_policy =
|
1009
|
-
|
1010
|
-
|
1011
|
-
if (GPR_UNLIKELY(lb_policy == nullptr)) {
|
1012
|
-
gpr_log(GPR_ERROR, "[xdslb %p] Failure creating fallback policy %s", this,
|
1013
|
-
name);
|
1014
|
-
return nullptr;
|
1015
|
-
}
|
1016
|
-
helper->set_child(lb_policy.get());
|
873
|
+
MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
|
874
|
+
&grpc_lb_xds_trace);
|
1017
875
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1018
|
-
gpr_log(GPR_INFO,
|
1019
|
-
|
876
|
+
gpr_log(GPR_INFO,
|
877
|
+
"[xdslb %p] Created new fallback child policy handler (%p)", this,
|
878
|
+
lb_policy.get());
|
1020
879
|
}
|
1021
880
|
// Add the xDS's interested_parties pollset_set to that of the newly created
|
1022
881
|
// child policy. This will make the child policy progress upon activity on xDS
|
@@ -1030,7 +889,6 @@ void XdsLb::MaybeExitFallbackMode() {
|
|
1030
889
|
if (fallback_policy_ == nullptr) return;
|
1031
890
|
gpr_log(GPR_INFO, "[xdslb %p] Exiting fallback mode", this);
|
1032
891
|
fallback_policy_.reset();
|
1033
|
-
pending_fallback_policy_.reset();
|
1034
892
|
}
|
1035
893
|
|
1036
894
|
//
|
@@ -1071,13 +929,24 @@ void XdsLb::UpdatePrioritiesLocked(bool update_locality_stats) {
|
|
1071
929
|
void XdsLb::UpdateXdsPickerLocked() {
|
1072
930
|
// If we are in fallback mode, don't generate an xds picker from localities.
|
1073
931
|
if (fallback_policy_ != nullptr) return;
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
|
932
|
+
// If we're dropping all calls, report READY, even though we won't
|
933
|
+
// have a selected priority.
|
934
|
+
if (drop_config_ != nullptr && drop_config_->drop_all()) {
|
1078
935
|
channel_control_helper()->UpdateState(
|
1079
|
-
|
1080
|
-
absl::make_unique<
|
936
|
+
GRPC_CHANNEL_READY,
|
937
|
+
absl::make_unique<LocalityPicker>(this, LocalityPicker::PickerList{}));
|
938
|
+
return;
|
939
|
+
}
|
940
|
+
// If we don't have a selected priority, report TRANSIENT_FAILURE.
|
941
|
+
if (current_priority_ == UINT32_MAX) {
|
942
|
+
if (fallback_policy_ == nullptr) {
|
943
|
+
grpc_error* error = grpc_error_set_int(
|
944
|
+
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready locality map"),
|
945
|
+
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
|
946
|
+
channel_control_helper()->UpdateState(
|
947
|
+
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
948
|
+
absl::make_unique<TransientFailurePicker>(error));
|
949
|
+
}
|
1081
950
|
return;
|
1082
951
|
}
|
1083
952
|
priorities_[current_priority_]->UpdateXdsPickerLocked();
|
@@ -1139,7 +1008,16 @@ OrphanablePtr<XdsLb::LocalityMap::Locality> XdsLb::ExtractLocalityLocked(
|
|
1139
1008
|
if (priority == exclude_priority) continue;
|
1140
1009
|
LocalityMap* locality_map = priorities_[priority].get();
|
1141
1010
|
auto locality = locality_map->ExtractLocalityLocked(name);
|
1142
|
-
if (locality != nullptr)
|
1011
|
+
if (locality != nullptr) {
|
1012
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1013
|
+
gpr_log(GPR_INFO,
|
1014
|
+
"[xdslb %p] moving locality %p %s to new priority (%" PRIu32
|
1015
|
+
" -> %" PRIu32 ")",
|
1016
|
+
this, locality.get(), name->AsHumanReadableString(),
|
1017
|
+
exclude_priority, priority);
|
1018
|
+
}
|
1019
|
+
return locality;
|
1020
|
+
}
|
1143
1021
|
}
|
1144
1022
|
return nullptr;
|
1145
1023
|
}
|
@@ -1165,7 +1043,7 @@ XdsLb::LocalityMap::LocalityMap(RefCountedPtr<XdsLb> xds_policy,
|
|
1165
1043
|
&on_failover_timer_);
|
1166
1044
|
failover_timer_callback_pending_ = true;
|
1167
1045
|
// This is the first locality map ever created, report CONNECTING.
|
1168
|
-
if (priority_ == 0) {
|
1046
|
+
if (priority_ == 0 && xds_policy_->fallback_policy_ == nullptr) {
|
1169
1047
|
xds_policy_->channel_control_helper()->UpdateState(
|
1170
1048
|
GRPC_CHANNEL_CONNECTING,
|
1171
1049
|
absl::make_unique<QueuePicker>(
|
@@ -1174,7 +1052,7 @@ XdsLb::LocalityMap::LocalityMap(RefCountedPtr<XdsLb> xds_policy,
|
|
1174
1052
|
}
|
1175
1053
|
|
1176
1054
|
void XdsLb::LocalityMap::UpdateLocked(
|
1177
|
-
const XdsApi::PriorityListUpdate::LocalityMap&
|
1055
|
+
const XdsApi::PriorityListUpdate::LocalityMap& priority_update,
|
1178
1056
|
bool update_locality_stats) {
|
1179
1057
|
if (xds_policy_->shutting_down_) return;
|
1180
1058
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
@@ -1184,11 +1062,11 @@ void XdsLb::LocalityMap::UpdateLocked(
|
|
1184
1062
|
// Maybe reactivate the locality map in case all the active locality maps have
|
1185
1063
|
// failed.
|
1186
1064
|
MaybeReactivateLocked();
|
1187
|
-
// Remove (later) the localities not in
|
1065
|
+
// Remove (later) the localities not in priority_update.
|
1188
1066
|
for (auto iter = localities_.begin(); iter != localities_.end();) {
|
1189
1067
|
const auto& name = iter->first;
|
1190
1068
|
Locality* locality = iter->second.get();
|
1191
|
-
if (
|
1069
|
+
if (priority_update.Contains(name)) {
|
1192
1070
|
++iter;
|
1193
1071
|
continue;
|
1194
1072
|
}
|
@@ -1199,8 +1077,8 @@ void XdsLb::LocalityMap::UpdateLocked(
|
|
1199
1077
|
++iter;
|
1200
1078
|
}
|
1201
1079
|
}
|
1202
|
-
// Add or update the localities in
|
1203
|
-
for (const auto& p :
|
1080
|
+
// Add or update the localities in priority_update.
|
1081
|
+
for (const auto& p : priority_update.localities) {
|
1204
1082
|
const auto& name = p.first;
|
1205
1083
|
const auto& locality_update = p.second;
|
1206
1084
|
OrphanablePtr<Locality>& locality = localities_[name];
|
@@ -1220,6 +1098,32 @@ void XdsLb::LocalityMap::UpdateLocked(
|
|
1220
1098
|
locality->UpdateLocked(locality_update.lb_weight,
|
1221
1099
|
locality_update.serverlist, update_locality_stats);
|
1222
1100
|
}
|
1101
|
+
// If this is the current priority and we removed all of the READY
|
1102
|
+
// localities, go into state CONNECTING.
|
1103
|
+
// TODO(roth): Ideally, we should model this as a graceful policy
|
1104
|
+
// switch: we should keep using the old localities for a short period
|
1105
|
+
// of time, long enough to give the new localities a chance to get
|
1106
|
+
// connected. As part of refactoring this policy, we should try to
|
1107
|
+
// fix that.
|
1108
|
+
if (priority_ == xds_policy()->current_priority_) {
|
1109
|
+
bool found_ready = false;
|
1110
|
+
for (auto& p : localities_) {
|
1111
|
+
const auto& locality_name = p.first;
|
1112
|
+
Locality* locality = p.second.get();
|
1113
|
+
if (!locality_map_update()->Contains(locality_name)) continue;
|
1114
|
+
if (locality->connectivity_state() == GRPC_CHANNEL_READY) {
|
1115
|
+
found_ready = true;
|
1116
|
+
break;
|
1117
|
+
}
|
1118
|
+
}
|
1119
|
+
if (!found_ready) {
|
1120
|
+
xds_policy_->channel_control_helper()->UpdateState(
|
1121
|
+
GRPC_CHANNEL_CONNECTING,
|
1122
|
+
absl::make_unique<QueuePicker>(
|
1123
|
+
xds_policy_->Ref(DEBUG_LOCATION, "QueuePicker")));
|
1124
|
+
xds_policy_->current_priority_ = UINT32_MAX;
|
1125
|
+
}
|
1126
|
+
}
|
1223
1127
|
}
|
1224
1128
|
|
1225
1129
|
void XdsLb::LocalityMap::ResetBackoffLocked() {
|
@@ -1227,6 +1131,9 @@ void XdsLb::LocalityMap::ResetBackoffLocked() {
|
|
1227
1131
|
}
|
1228
1132
|
|
1229
1133
|
void XdsLb::LocalityMap::UpdateXdsPickerLocked() {
|
1134
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1135
|
+
gpr_log(GPR_INFO, "[xdslb %p] constructing new picker", xds_policy());
|
1136
|
+
}
|
1230
1137
|
// Construct a new xds picker which maintains a map of all locality pickers
|
1231
1138
|
// that are ready. Each locality is represented by a portion of the range
|
1232
1139
|
// proportional to its weight, such that the total range is the sum of the
|
@@ -1237,11 +1144,18 @@ void XdsLb::LocalityMap::UpdateXdsPickerLocked() {
|
|
1237
1144
|
const auto& locality_name = p.first;
|
1238
1145
|
Locality* locality = p.second.get();
|
1239
1146
|
// Skip the localities that are not in the latest locality map update.
|
1240
|
-
|
1147
|
+
const auto* locality_update = locality_map_update();
|
1148
|
+
if (locality_update == nullptr) continue;
|
1149
|
+
if (!locality_update->Contains(locality_name)) continue;
|
1241
1150
|
if (locality->connectivity_state() != GRPC_CHANNEL_READY) continue;
|
1242
1151
|
end += locality->weight();
|
1243
1152
|
picker_list.push_back(
|
1244
1153
|
std::make_pair(end, locality->GetLoadReportingPicker()));
|
1154
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1155
|
+
gpr_log(GPR_INFO, "[xdslb %p] locality=%s weight=%d picker=%p",
|
1156
|
+
xds_policy(), locality_name->AsHumanReadableString(),
|
1157
|
+
locality->weight(), picker_list.back().second.get());
|
1158
|
+
}
|
1245
1159
|
}
|
1246
1160
|
xds_policy()->channel_control_helper()->UpdateState(
|
1247
1161
|
GRPC_CHANNEL_READY,
|
@@ -1263,6 +1177,10 @@ XdsLb::LocalityMap::ExtractLocalityLocked(
|
|
1263
1177
|
}
|
1264
1178
|
|
1265
1179
|
void XdsLb::LocalityMap::DeactivateLocked() {
|
1180
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1181
|
+
gpr_log(GPR_INFO, "[xdslb %p] deactivating priority %" PRIu32, xds_policy(),
|
1182
|
+
priority_);
|
1183
|
+
}
|
1266
1184
|
// If already deactivated, don't do it again.
|
1267
1185
|
if (delayed_removal_timer_callback_pending_) return;
|
1268
1186
|
MaybeCancelFailoverTimerLocked();
|
@@ -1287,6 +1205,10 @@ bool XdsLb::LocalityMap::MaybeReactivateLocked() {
|
|
1287
1205
|
// Don't reactivate a priority that is not higher than the current one.
|
1288
1206
|
if (priority_ >= xds_policy_->current_priority_) return false;
|
1289
1207
|
// Reactivate this priority by cancelling deletion timer.
|
1208
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1209
|
+
gpr_log(GPR_INFO, "[xdslb %p] reactivating priority %" PRIu32, xds_policy(),
|
1210
|
+
priority_);
|
1211
|
+
}
|
1290
1212
|
if (delayed_removal_timer_callback_pending_) {
|
1291
1213
|
grpc_timer_cancel(&delayed_removal_timer_);
|
1292
1214
|
}
|
@@ -1513,27 +1435,19 @@ grpc_channel_args* XdsLb::LocalityMap::Locality::CreateChildPolicyArgsLocked(
|
|
1513
1435
|
|
1514
1436
|
OrphanablePtr<LoadBalancingPolicy>
|
1515
1437
|
XdsLb::LocalityMap::Locality::CreateChildPolicyLocked(
|
1516
|
-
const
|
1517
|
-
Helper* helper = new Helper(this->Ref(DEBUG_LOCATION, "Helper"));
|
1438
|
+
const grpc_channel_args* args) {
|
1518
1439
|
LoadBalancingPolicy::Args lb_policy_args;
|
1519
1440
|
lb_policy_args.combiner = xds_policy()->combiner();
|
1520
1441
|
lb_policy_args.args = args;
|
1521
1442
|
lb_policy_args.channel_control_helper =
|
1522
|
-
|
1443
|
+
absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
|
1523
1444
|
OrphanablePtr<LoadBalancingPolicy> lb_policy =
|
1524
|
-
|
1525
|
-
|
1526
|
-
if (GPR_UNLIKELY(lb_policy == nullptr)) {
|
1527
|
-
gpr_log(GPR_ERROR,
|
1528
|
-
"[xdslb %p] Locality %p %s: failure creating child policy %s",
|
1529
|
-
xds_policy(), this, name_->AsHumanReadableString(), name);
|
1530
|
-
return nullptr;
|
1531
|
-
}
|
1532
|
-
helper->set_child(lb_policy.get());
|
1445
|
+
MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
|
1446
|
+
&grpc_lb_xds_trace);
|
1533
1447
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1534
1448
|
gpr_log(GPR_INFO,
|
1535
|
-
"[xdslb %p] Locality %p %s: Created new child policy
|
1536
|
-
xds_policy(), this, name_->AsHumanReadableString(),
|
1449
|
+
"[xdslb %p] Locality %p %s: Created new child policy handler (%p)",
|
1450
|
+
xds_policy(), this, name_->AsHumanReadableString(),
|
1537
1451
|
lb_policy.get());
|
1538
1452
|
}
|
1539
1453
|
// Add the xDS's interested_parties pollset_set to that of the newly created
|
@@ -1551,6 +1465,10 @@ void XdsLb::LocalityMap::Locality::UpdateLocked(uint32_t locality_weight,
|
|
1551
1465
|
// Update locality weight.
|
1552
1466
|
weight_ = locality_weight;
|
1553
1467
|
if (delayed_removal_timer_callback_pending_) {
|
1468
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1469
|
+
gpr_log(GPR_INFO, "[xdslb %p] Locality %p %s: reactivating", xds_policy(),
|
1470
|
+
this, name_->AsHumanReadableString());
|
1471
|
+
}
|
1554
1472
|
grpc_timer_cancel(&delayed_removal_timer_);
|
1555
1473
|
}
|
1556
1474
|
// Update locality stats.
|
@@ -1560,101 +1478,19 @@ void XdsLb::LocalityMap::Locality::UpdateLocked(uint32_t locality_weight,
|
|
1560
1478
|
update_args.addresses = std::move(serverlist);
|
1561
1479
|
update_args.config = xds_policy()->config_->child_policy();
|
1562
1480
|
update_args.args = CreateChildPolicyArgsLocked(xds_policy()->args_);
|
1563
|
-
//
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
// non-null only between when we apply an update that changes the child
|
1569
|
-
// policy name and when the new child reports state READY.
|
1570
|
-
//
|
1571
|
-
// Updates can arrive at any point during this transition. We always
|
1572
|
-
// apply updates relative to the most recently created child policy,
|
1573
|
-
// even if the most recent one is still in pending_child_policy_. This
|
1574
|
-
// is true both when applying the updates to an existing child policy
|
1575
|
-
// and when determining whether we need to create a new policy.
|
1576
|
-
//
|
1577
|
-
// As a result of this, there are several cases to consider here:
|
1578
|
-
//
|
1579
|
-
// 1. We have no existing child policy (i.e., we have started up but
|
1580
|
-
// have not yet received a serverlist from the balancer or gone
|
1581
|
-
// into fallback mode; in this case, both child_policy_ and
|
1582
|
-
// pending_child_policy_ are null). In this case, we create a
|
1583
|
-
// new child policy and store it in child_policy_.
|
1584
|
-
//
|
1585
|
-
// 2. We have an existing child policy and have no pending child policy
|
1586
|
-
// from a previous update (i.e., either there has not been a
|
1587
|
-
// previous update that changed the policy name, or we have already
|
1588
|
-
// finished swapping in the new policy; in this case, child_policy_
|
1589
|
-
// is non-null but pending_child_policy_ is null). In this case:
|
1590
|
-
// a. If child_policy_->name() equals child_policy_name, then we
|
1591
|
-
// update the existing child policy.
|
1592
|
-
// b. If child_policy_->name() does not equal child_policy_name,
|
1593
|
-
// we create a new policy. The policy will be stored in
|
1594
|
-
// pending_child_policy_ and will later be swapped into
|
1595
|
-
// child_policy_ by the helper when the new child transitions
|
1596
|
-
// into state READY.
|
1597
|
-
//
|
1598
|
-
// 3. We have an existing child policy and have a pending child policy
|
1599
|
-
// from a previous update (i.e., a previous update set
|
1600
|
-
// pending_child_policy_ as per case 2b above and that policy has
|
1601
|
-
// not yet transitioned into state READY and been swapped into
|
1602
|
-
// child_policy_; in this case, both child_policy_ and
|
1603
|
-
// pending_child_policy_ are non-null). In this case:
|
1604
|
-
// a. If pending_child_policy_->name() equals child_policy_name,
|
1605
|
-
// then we update the existing pending child policy.
|
1606
|
-
// b. If pending_child_policy->name() does not equal
|
1607
|
-
// child_policy_name, then we create a new policy. The new
|
1608
|
-
// policy is stored in pending_child_policy_ (replacing the one
|
1609
|
-
// that was there before, which will be immediately shut down)
|
1610
|
-
// and will later be swapped into child_policy_ by the helper
|
1611
|
-
// when the new child transitions into state READY.
|
1612
|
-
// TODO(juanlishen): If the child policy is not configured via service config,
|
1613
|
-
// use whatever algorithm is specified by the balancer.
|
1614
|
-
const char* child_policy_name = update_args.config == nullptr
|
1615
|
-
? "round_robin"
|
1616
|
-
: update_args.config->name();
|
1617
|
-
const bool create_policy =
|
1618
|
-
// case 1
|
1619
|
-
child_policy_ == nullptr ||
|
1620
|
-
// case 2b
|
1621
|
-
(pending_child_policy_ == nullptr &&
|
1622
|
-
strcmp(child_policy_->name(), child_policy_name) != 0) ||
|
1623
|
-
// case 3b
|
1624
|
-
(pending_child_policy_ != nullptr &&
|
1625
|
-
strcmp(pending_child_policy_->name(), child_policy_name) != 0);
|
1626
|
-
LoadBalancingPolicy* policy_to_update = nullptr;
|
1627
|
-
if (create_policy) {
|
1628
|
-
// Cases 1, 2b, and 3b: create a new child policy.
|
1629
|
-
// If child_policy_ is null, we set it (case 1), else we set
|
1630
|
-
// pending_child_policy_ (cases 2b and 3b).
|
1631
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1632
|
-
gpr_log(GPR_INFO,
|
1633
|
-
"[xdslb %p] Locality %p %s: Creating new %schild policy %s",
|
1634
|
-
xds_policy(), this, name_->AsHumanReadableString(),
|
1635
|
-
child_policy_ == nullptr ? "" : "pending ", child_policy_name);
|
1636
|
-
}
|
1637
|
-
auto& lb_policy =
|
1638
|
-
child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
|
1639
|
-
lb_policy = CreateChildPolicyLocked(child_policy_name, update_args.args);
|
1640
|
-
policy_to_update = lb_policy.get();
|
1641
|
-
} else {
|
1642
|
-
// Cases 2a and 3a: update an existing policy.
|
1643
|
-
// If we have a pending child policy, send the update to the pending
|
1644
|
-
// policy (case 3a), else send it to the current policy (case 2a).
|
1645
|
-
policy_to_update = pending_child_policy_ != nullptr
|
1646
|
-
? pending_child_policy_.get()
|
1647
|
-
: child_policy_.get();
|
1648
|
-
}
|
1649
|
-
GPR_ASSERT(policy_to_update != nullptr);
|
1481
|
+
// Create child policy if needed.
|
1482
|
+
if (child_policy_ == nullptr) {
|
1483
|
+
child_policy_ = CreateChildPolicyLocked(update_args.args);
|
1484
|
+
GPR_ASSERT(child_policy_ != nullptr);
|
1485
|
+
}
|
1650
1486
|
// Update the policy.
|
1651
1487
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1652
|
-
gpr_log(GPR_INFO,
|
1488
|
+
gpr_log(GPR_INFO,
|
1489
|
+
"[xdslb %p] Locality %p %s: Updating child policy handler %p",
|
1653
1490
|
xds_policy(), this, name_->AsHumanReadableString(),
|
1654
|
-
|
1655
|
-
policy_to_update);
|
1491
|
+
child_policy_.get());
|
1656
1492
|
}
|
1657
|
-
|
1493
|
+
child_policy_->UpdateLocked(std::move(update_args));
|
1658
1494
|
}
|
1659
1495
|
|
1660
1496
|
void XdsLb::LocalityMap::Locality::ShutdownLocked() {
|
@@ -1668,12 +1504,6 @@ void XdsLb::LocalityMap::Locality::ShutdownLocked() {
|
|
1668
1504
|
grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
|
1669
1505
|
xds_policy()->interested_parties());
|
1670
1506
|
child_policy_.reset();
|
1671
|
-
if (pending_child_policy_ != nullptr) {
|
1672
|
-
grpc_pollset_set_del_pollset_set(
|
1673
|
-
pending_child_policy_->interested_parties(),
|
1674
|
-
xds_policy()->interested_parties());
|
1675
|
-
pending_child_policy_.reset();
|
1676
|
-
}
|
1677
1507
|
// Drop our ref to the child's picker, in case it's holding a ref to
|
1678
1508
|
// the child.
|
1679
1509
|
load_reporting_picker_.reset();
|
@@ -1686,9 +1516,6 @@ void XdsLb::LocalityMap::Locality::ShutdownLocked() {
|
|
1686
1516
|
|
1687
1517
|
void XdsLb::LocalityMap::Locality::ResetBackoffLocked() {
|
1688
1518
|
child_policy_->ResetBackoffLocked();
|
1689
|
-
if (pending_child_policy_ != nullptr) {
|
1690
|
-
pending_child_policy_->ResetBackoffLocked();
|
1691
|
-
}
|
1692
1519
|
}
|
1693
1520
|
|
1694
1521
|
void XdsLb::LocalityMap::Locality::Orphan() {
|
@@ -1699,6 +1526,10 @@ void XdsLb::LocalityMap::Locality::Orphan() {
|
|
1699
1526
|
void XdsLb::LocalityMap::Locality::DeactivateLocked() {
|
1700
1527
|
// If already deactivated, don't do that again.
|
1701
1528
|
if (weight_ == 0) return;
|
1529
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1530
|
+
gpr_log(GPR_INFO, "[xdslb %p] Locality %p %s: deactivating", xds_policy(),
|
1531
|
+
this, name_->AsHumanReadableString());
|
1532
|
+
}
|
1702
1533
|
// Set the locality weight to 0 so that future xds picker won't contain this
|
1703
1534
|
// locality.
|
1704
1535
|
weight_ = 0;
|
@@ -1736,23 +1567,10 @@ void XdsLb::LocalityMap::Locality::OnDelayedRemovalTimerLocked(
|
|
1736
1567
|
// XdsLb::LocalityMap::Locality::Helper
|
1737
1568
|
//
|
1738
1569
|
|
1739
|
-
bool XdsLb::LocalityMap::Locality::Helper::CalledByPendingChild() const {
|
1740
|
-
GPR_ASSERT(child_ != nullptr);
|
1741
|
-
return child_ == locality_->pending_child_policy_.get();
|
1742
|
-
}
|
1743
|
-
|
1744
|
-
bool XdsLb::LocalityMap::Locality::Helper::CalledByCurrentChild() const {
|
1745
|
-
GPR_ASSERT(child_ != nullptr);
|
1746
|
-
return child_ == locality_->child_policy_.get();
|
1747
|
-
}
|
1748
|
-
|
1749
1570
|
RefCountedPtr<SubchannelInterface>
|
1750
1571
|
XdsLb::LocalityMap::Locality::Helper::CreateSubchannel(
|
1751
1572
|
const grpc_channel_args& args) {
|
1752
|
-
if (locality_->xds_policy()->shutting_down_
|
1753
|
-
(!CalledByPendingChild() && !CalledByCurrentChild())) {
|
1754
|
-
return nullptr;
|
1755
|
-
}
|
1573
|
+
if (locality_->xds_policy()->shutting_down_) return nullptr;
|
1756
1574
|
return locality_->xds_policy()->channel_control_helper()->CreateSubchannel(
|
1757
1575
|
args);
|
1758
1576
|
}
|
@@ -1760,24 +1578,11 @@ XdsLb::LocalityMap::Locality::Helper::CreateSubchannel(
|
|
1760
1578
|
void XdsLb::LocalityMap::Locality::Helper::UpdateState(
|
1761
1579
|
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) {
|
1762
1580
|
if (locality_->xds_policy()->shutting_down_) return;
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
"[xdslb %p helper %p] pending child policy %p reports state=%s",
|
1769
|
-
locality_->xds_policy(), this,
|
1770
|
-
locality_->pending_child_policy_.get(),
|
1771
|
-
ConnectivityStateName(state));
|
1772
|
-
}
|
1773
|
-
if (state != GRPC_CHANNEL_READY) return;
|
1774
|
-
grpc_pollset_set_del_pollset_set(
|
1775
|
-
locality_->child_policy_->interested_parties(),
|
1776
|
-
locality_->xds_policy()->interested_parties());
|
1777
|
-
locality_->child_policy_ = std::move(locality_->pending_child_policy_);
|
1778
|
-
} else if (!CalledByCurrentChild()) {
|
1779
|
-
// This request is from an outdated child, so ignore it.
|
1780
|
-
return;
|
1581
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
|
1582
|
+
gpr_log(GPR_INFO,
|
1583
|
+
"[xdslb %p helper %p] child policy handler %p reports state=%s",
|
1584
|
+
locality_->xds_policy(), this, locality_->child_policy_.get(),
|
1585
|
+
ConnectivityStateName(state));
|
1781
1586
|
}
|
1782
1587
|
// Cache the state and picker in the locality.
|
1783
1588
|
locality_->connectivity_state_ = state;
|
@@ -1789,10 +1594,7 @@ void XdsLb::LocalityMap::Locality::Helper::UpdateState(
|
|
1789
1594
|
|
1790
1595
|
void XdsLb::LocalityMap::Locality::Helper::AddTraceEvent(TraceSeverity severity,
|
1791
1596
|
StringView message) {
|
1792
|
-
if (locality_->xds_policy()->shutting_down_
|
1793
|
-
(!CalledByPendingChild() && !CalledByCurrentChild())) {
|
1794
|
-
return;
|
1795
|
-
}
|
1597
|
+
if (locality_->xds_policy()->shutting_down_) return;
|
1796
1598
|
locality_->xds_policy()->channel_control_helper()->AddTraceEvent(severity,
|
1797
1599
|
message);
|
1798
1600
|
}
|
@@ -1805,7 +1607,7 @@ class XdsFactory : public LoadBalancingPolicyFactory {
|
|
1805
1607
|
public:
|
1806
1608
|
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
|
1807
1609
|
LoadBalancingPolicy::Args args) const override {
|
1808
|
-
return MakeOrphanable<
|
1610
|
+
return MakeOrphanable<XdsChildHandler>(std::move(args), &grpc_lb_xds_trace);
|
1809
1611
|
}
|
1810
1612
|
|
1811
1613
|
const char* name() const override { return kXds; }
|
@@ -1823,34 +1625,48 @@ class XdsFactory : public LoadBalancingPolicyFactory {
|
|
1823
1625
|
}
|
1824
1626
|
std::vector<grpc_error*> error_list;
|
1825
1627
|
// Child policy.
|
1826
|
-
|
1628
|
+
Json json_tmp;
|
1629
|
+
const Json* child_policy_json;
|
1827
1630
|
auto it = json.object_value().find("childPolicy");
|
1828
|
-
if (it
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1631
|
+
if (it == json.object_value().end()) {
|
1632
|
+
json_tmp = Json::Array{Json::Object{
|
1633
|
+
{"round_robin", Json::Object()},
|
1634
|
+
}};
|
1635
|
+
child_policy_json = &json_tmp;
|
1636
|
+
} else {
|
1637
|
+
child_policy_json = &it->second;
|
1638
|
+
}
|
1639
|
+
grpc_error* parse_error = GRPC_ERROR_NONE;
|
1640
|
+
RefCountedPtr<LoadBalancingPolicy::Config> child_policy =
|
1641
|
+
LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
|
1642
|
+
*child_policy_json, &parse_error);
|
1643
|
+
if (child_policy == nullptr) {
|
1644
|
+
GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
|
1645
|
+
std::vector<grpc_error*> child_errors;
|
1646
|
+
child_errors.push_back(parse_error);
|
1647
|
+
error_list.push_back(
|
1648
|
+
GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
|
1839
1649
|
}
|
1840
1650
|
// Fallback policy.
|
1841
|
-
|
1651
|
+
const Json* fallback_policy_json;
|
1842
1652
|
it = json.object_value().find("fallbackPolicy");
|
1843
|
-
if (it
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1653
|
+
if (it == json.object_value().end()) {
|
1654
|
+
json_tmp = Json::Array{Json::Object{
|
1655
|
+
{"round_robin", Json::Object()},
|
1656
|
+
}};
|
1657
|
+
fallback_policy_json = &json_tmp;
|
1658
|
+
} else {
|
1659
|
+
fallback_policy_json = &it->second;
|
1660
|
+
}
|
1661
|
+
RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy =
|
1662
|
+
LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
|
1663
|
+
*fallback_policy_json, &parse_error);
|
1664
|
+
if (fallback_policy == nullptr) {
|
1665
|
+
GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
|
1666
|
+
std::vector<grpc_error*> child_errors;
|
1667
|
+
child_errors.push_back(parse_error);
|
1668
|
+
error_list.push_back(
|
1669
|
+
GRPC_ERROR_CREATE_FROM_VECTOR("field:fallbackPolicy", &child_errors));
|
1854
1670
|
}
|
1855
1671
|
// EDS service name.
|
1856
1672
|
const char* eds_service_name = nullptr;
|
@@ -1875,7 +1691,7 @@ class XdsFactory : public LoadBalancingPolicyFactory {
|
|
1875
1691
|
}
|
1876
1692
|
}
|
1877
1693
|
if (error_list.empty()) {
|
1878
|
-
|
1694
|
+
absl::optional<std::string> optional_lrs_load_reporting_server_name;
|
1879
1695
|
if (lrs_load_reporting_server_name != nullptr) {
|
1880
1696
|
optional_lrs_load_reporting_server_name.emplace(
|
1881
1697
|
std::string(lrs_load_reporting_server_name));
|
@@ -1889,6 +1705,36 @@ class XdsFactory : public LoadBalancingPolicyFactory {
|
|
1889
1705
|
return nullptr;
|
1890
1706
|
}
|
1891
1707
|
}
|
1708
|
+
|
1709
|
+
private:
|
1710
|
+
class XdsChildHandler : public ChildPolicyHandler {
|
1711
|
+
public:
|
1712
|
+
XdsChildHandler(Args args, TraceFlag* tracer)
|
1713
|
+
: ChildPolicyHandler(std::move(args), tracer) {}
|
1714
|
+
|
1715
|
+
bool ConfigChangeRequiresNewPolicyInstance(
|
1716
|
+
LoadBalancingPolicy::Config* old_config,
|
1717
|
+
LoadBalancingPolicy::Config* new_config) const override {
|
1718
|
+
GPR_ASSERT(old_config->name() == kXds);
|
1719
|
+
GPR_ASSERT(new_config->name() == kXds);
|
1720
|
+
XdsConfig* old_xds_config = static_cast<XdsConfig*>(old_config);
|
1721
|
+
XdsConfig* new_xds_config = static_cast<XdsConfig*>(new_config);
|
1722
|
+
const char* old_eds_service_name =
|
1723
|
+
old_xds_config->eds_service_name() == nullptr
|
1724
|
+
? ""
|
1725
|
+
: old_xds_config->eds_service_name();
|
1726
|
+
const char* new_eds_service_name =
|
1727
|
+
new_xds_config->eds_service_name() == nullptr
|
1728
|
+
? ""
|
1729
|
+
: new_xds_config->eds_service_name();
|
1730
|
+
return strcmp(old_eds_service_name, new_eds_service_name) != 0;
|
1731
|
+
}
|
1732
|
+
|
1733
|
+
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
|
1734
|
+
const char* name, LoadBalancingPolicy::Args args) const override {
|
1735
|
+
return MakeOrphanable<XdsLb>(std::move(args));
|
1736
|
+
}
|
1737
|
+
};
|
1892
1738
|
};
|
1893
1739
|
|
1894
1740
|
} // namespace
|