mirror of https://github.com/grpc/grpc.git
parent
24f54fbb4b
commit
799e805e8a
20 changed files with 160 additions and 611 deletions
@ -1,537 +0,0 @@ |
|||||||
//
|
|
||||||
// Copyright 2018 gRPC authors.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <grpc/support/port_platform.h> |
|
||||||
|
|
||||||
#include <grpc/grpc.h> |
|
||||||
|
|
||||||
#include "src/core/ext/filters/client_channel/lb_policy.h" |
|
||||||
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h" |
|
||||||
#include "src/core/ext/filters/client_channel/lb_policy_factory.h" |
|
||||||
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
|
||||||
#include "src/core/ext/xds/xds_client.h" |
|
||||||
#include "src/core/ext/xds/xds_client_stats.h" |
|
||||||
#include "src/core/lib/channel/channel_args.h" |
|
||||||
#include "src/core/lib/gprpp/orphanable.h" |
|
||||||
#include "src/core/lib/gprpp/ref_counted_ptr.h" |
|
||||||
#include "src/core/lib/iomgr/work_serializer.h" |
|
||||||
|
|
||||||
namespace grpc_core { |
|
||||||
|
|
||||||
TraceFlag grpc_lb_lrs_trace(false, "lrs_lb"); |
|
||||||
|
|
||||||
namespace { |
|
||||||
|
|
||||||
constexpr char kLrs[] = "lrs_experimental"; |
|
||||||
|
|
||||||
// Config for LRS LB policy.
|
|
||||||
class LrsLbConfig : public LoadBalancingPolicy::Config { |
|
||||||
public: |
|
||||||
LrsLbConfig(RefCountedPtr<LoadBalancingPolicy::Config> child_policy, |
|
||||||
std::string cluster_name, std::string eds_service_name, |
|
||||||
std::string lrs_load_reporting_server_name, |
|
||||||
RefCountedPtr<XdsLocalityName> locality_name) |
|
||||||
: child_policy_(std::move(child_policy)), |
|
||||||
cluster_name_(std::move(cluster_name)), |
|
||||||
eds_service_name_(std::move(eds_service_name)), |
|
||||||
lrs_load_reporting_server_name_( |
|
||||||
std::move(lrs_load_reporting_server_name)), |
|
||||||
locality_name_(std::move(locality_name)) {} |
|
||||||
|
|
||||||
const char* name() const override { return kLrs; } |
|
||||||
|
|
||||||
RefCountedPtr<LoadBalancingPolicy::Config> child_policy() const { |
|
||||||
return child_policy_; |
|
||||||
} |
|
||||||
const std::string& cluster_name() const { return cluster_name_; } |
|
||||||
const std::string& eds_service_name() const { return eds_service_name_; } |
|
||||||
const std::string& lrs_load_reporting_server_name() const { |
|
||||||
return lrs_load_reporting_server_name_; |
|
||||||
}; |
|
||||||
RefCountedPtr<XdsLocalityName> locality_name() const { |
|
||||||
return locality_name_; |
|
||||||
} |
|
||||||
|
|
||||||
private: |
|
||||||
RefCountedPtr<LoadBalancingPolicy::Config> child_policy_; |
|
||||||
std::string cluster_name_; |
|
||||||
std::string eds_service_name_; |
|
||||||
std::string lrs_load_reporting_server_name_; |
|
||||||
RefCountedPtr<XdsLocalityName> locality_name_; |
|
||||||
}; |
|
||||||
|
|
||||||
// LRS LB policy.
|
|
||||||
class LrsLb : public LoadBalancingPolicy { |
|
||||||
public: |
|
||||||
LrsLb(RefCountedPtr<XdsClient> xds_client, Args args); |
|
||||||
|
|
||||||
const char* name() const override { return kLrs; } |
|
||||||
|
|
||||||
void UpdateLocked(UpdateArgs args) override; |
|
||||||
void ExitIdleLocked() override; |
|
||||||
void ResetBackoffLocked() override; |
|
||||||
|
|
||||||
private: |
|
||||||
// A simple wrapper for ref-counting a picker from the child policy.
|
|
||||||
class RefCountedPicker : public RefCounted<RefCountedPicker> { |
|
||||||
public: |
|
||||||
explicit RefCountedPicker(std::unique_ptr<SubchannelPicker> picker) |
|
||||||
: picker_(std::move(picker)) {} |
|
||||||
PickResult Pick(PickArgs args) { return picker_->Pick(args); } |
|
||||||
|
|
||||||
private: |
|
||||||
std::unique_ptr<SubchannelPicker> picker_; |
|
||||||
}; |
|
||||||
|
|
||||||
// A picker that wraps the picker from the child to perform load reporting.
|
|
||||||
class LoadReportingPicker : public SubchannelPicker { |
|
||||||
public: |
|
||||||
LoadReportingPicker(RefCountedPtr<RefCountedPicker> picker, |
|
||||||
RefCountedPtr<XdsClusterLocalityStats> locality_stats) |
|
||||||
: picker_(std::move(picker)), |
|
||||||
locality_stats_(std::move(locality_stats)) {} |
|
||||||
|
|
||||||
PickResult Pick(PickArgs args); |
|
||||||
|
|
||||||
private: |
|
||||||
RefCountedPtr<RefCountedPicker> picker_; |
|
||||||
RefCountedPtr<XdsClusterLocalityStats> locality_stats_; |
|
||||||
}; |
|
||||||
|
|
||||||
class Helper : public ChannelControlHelper { |
|
||||||
public: |
|
||||||
explicit Helper(RefCountedPtr<LrsLb> lrs_policy) |
|
||||||
: lrs_policy_(std::move(lrs_policy)) {} |
|
||||||
|
|
||||||
~Helper() { lrs_policy_.reset(DEBUG_LOCATION, "Helper"); } |
|
||||||
|
|
||||||
RefCountedPtr<SubchannelInterface> CreateSubchannel( |
|
||||||
ServerAddress address, const grpc_channel_args& args) override; |
|
||||||
void UpdateState(grpc_connectivity_state state, const absl::Status& status, |
|
||||||
std::unique_ptr<SubchannelPicker> picker) override; |
|
||||||
void RequestReresolution() override; |
|
||||||
void AddTraceEvent(TraceSeverity severity, |
|
||||||
absl::string_view message) override; |
|
||||||
|
|
||||||
private: |
|
||||||
RefCountedPtr<LrsLb> lrs_policy_; |
|
||||||
}; |
|
||||||
|
|
||||||
~LrsLb(); |
|
||||||
|
|
||||||
void ShutdownLocked() override; |
|
||||||
|
|
||||||
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked( |
|
||||||
const grpc_channel_args* args); |
|
||||||
void UpdateChildPolicyLocked(ServerAddressList addresses, |
|
||||||
const grpc_channel_args* args); |
|
||||||
|
|
||||||
void MaybeUpdatePickerLocked(); |
|
||||||
|
|
||||||
// Current config from the resolver.
|
|
||||||
RefCountedPtr<LrsLbConfig> config_; |
|
||||||
|
|
||||||
// Internal state.
|
|
||||||
bool shutting_down_ = false; |
|
||||||
|
|
||||||
// The xds client.
|
|
||||||
RefCountedPtr<XdsClient> xds_client_; |
|
||||||
|
|
||||||
// The stats for client-side load reporting.
|
|
||||||
RefCountedPtr<XdsClusterLocalityStats> locality_stats_; |
|
||||||
|
|
||||||
OrphanablePtr<LoadBalancingPolicy> child_policy_; |
|
||||||
|
|
||||||
// Latest state and picker reported by the child policy.
|
|
||||||
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE; |
|
||||||
absl::Status status_; |
|
||||||
RefCountedPtr<RefCountedPicker> picker_; |
|
||||||
}; |
|
||||||
|
|
||||||
//
|
|
||||||
// LrsLb::LoadReportingPicker
|
|
||||||
//
|
|
||||||
|
|
||||||
LoadBalancingPolicy::PickResult LrsLb::LoadReportingPicker::Pick( |
|
||||||
LoadBalancingPolicy::PickArgs args) { |
|
||||||
// Forward the pick to the picker returned from the child policy.
|
|
||||||
PickResult result = picker_->Pick(args); |
|
||||||
if (result.type == PickResult::PICK_COMPLETE && |
|
||||||
result.subchannel != nullptr) { |
|
||||||
// Record a call started.
|
|
||||||
locality_stats_->AddCallStarted(); |
|
||||||
// Intercept the recv_trailing_metadata op to record call completion.
|
|
||||||
XdsClusterLocalityStats* locality_stats = |
|
||||||
locality_stats_->Ref(DEBUG_LOCATION, "LocalityStats+call").release(); |
|
||||||
result.recv_trailing_metadata_ready = |
|
||||||
// Note: This callback does not run in either the control plane
|
|
||||||
// work serializer or in the data plane mutex.
|
|
||||||
[locality_stats](grpc_error* error, MetadataInterface* /*metadata*/, |
|
||||||
CallState* /*call_state*/) { |
|
||||||
const bool call_failed = error != GRPC_ERROR_NONE; |
|
||||||
locality_stats->AddCallFinished(call_failed); |
|
||||||
locality_stats->Unref(DEBUG_LOCATION, "LocalityStats+call"); |
|
||||||
}; |
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
//
|
|
||||||
// LrsLb
|
|
||||||
//
|
|
||||||
|
|
||||||
LrsLb::LrsLb(RefCountedPtr<XdsClient> xds_client, Args args) |
|
||||||
: LoadBalancingPolicy(std::move(args)), xds_client_(std::move(xds_client)) { |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log(GPR_INFO, "[lrs_lb %p] created -- using xds client %p", this, |
|
||||||
xds_client_.get()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
LrsLb::~LrsLb() { |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log(GPR_INFO, "[lrs_lb %p] destroying xds LB policy", this); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::ShutdownLocked() { |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log(GPR_INFO, "[lrs_lb %p] shutting down", this); |
|
||||||
} |
|
||||||
shutting_down_ = true; |
|
||||||
// Remove the child policy's interested_parties pollset_set from the
|
|
||||||
// xDS policy.
|
|
||||||
if (child_policy_ != nullptr) { |
|
||||||
grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(), |
|
||||||
interested_parties()); |
|
||||||
child_policy_.reset(); |
|
||||||
} |
|
||||||
// Drop our ref to the child's picker, in case it's holding a ref to
|
|
||||||
// the child.
|
|
||||||
picker_.reset(); |
|
||||||
locality_stats_.reset(); |
|
||||||
xds_client_.reset(); |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::ExitIdleLocked() { |
|
||||||
if (child_policy_ != nullptr) child_policy_->ExitIdleLocked(); |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::ResetBackoffLocked() { |
|
||||||
// The XdsClient will have its backoff reset by the xds resolver, so we
|
|
||||||
// don't need to do it here.
|
|
||||||
if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked(); |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::UpdateLocked(UpdateArgs args) { |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log(GPR_INFO, "[lrs_lb %p] Received update", this); |
|
||||||
} |
|
||||||
// Update config.
|
|
||||||
auto old_config = std::move(config_); |
|
||||||
config_ = std::move(args.config); |
|
||||||
// Update load reporting if needed.
|
|
||||||
if (old_config == nullptr || |
|
||||||
config_->lrs_load_reporting_server_name() != |
|
||||||
old_config->lrs_load_reporting_server_name() || |
|
||||||
config_->cluster_name() != old_config->cluster_name() || |
|
||||||
config_->eds_service_name() != old_config->eds_service_name() || |
|
||||||
*config_->locality_name() != *old_config->locality_name()) { |
|
||||||
locality_stats_ = xds_client_->AddClusterLocalityStats( |
|
||||||
config_->lrs_load_reporting_server_name(), config_->cluster_name(), |
|
||||||
config_->eds_service_name(), config_->locality_name()); |
|
||||||
MaybeUpdatePickerLocked(); |
|
||||||
} |
|
||||||
// Update child policy.
|
|
||||||
UpdateChildPolicyLocked(std::move(args.addresses), args.args); |
|
||||||
args.args = nullptr; |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::MaybeUpdatePickerLocked() { |
|
||||||
if (picker_ != nullptr) { |
|
||||||
auto lrs_picker = |
|
||||||
absl::make_unique<LoadReportingPicker>(picker_, locality_stats_); |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log( |
|
||||||
GPR_INFO, |
|
||||||
"[lrs_lb %p] updating connectivity: state=%s status=(%s) picker=%p", |
|
||||||
this, ConnectivityStateName(state_), status_.ToString().c_str(), |
|
||||||
lrs_picker.get()); |
|
||||||
} |
|
||||||
channel_control_helper()->UpdateState(state_, status_, |
|
||||||
std::move(lrs_picker)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
OrphanablePtr<LoadBalancingPolicy> LrsLb::CreateChildPolicyLocked( |
|
||||||
const grpc_channel_args* args) { |
|
||||||
LoadBalancingPolicy::Args lb_policy_args; |
|
||||||
lb_policy_args.work_serializer = work_serializer(); |
|
||||||
lb_policy_args.args = args; |
|
||||||
lb_policy_args.channel_control_helper = |
|
||||||
absl::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper")); |
|
||||||
OrphanablePtr<LoadBalancingPolicy> lb_policy = |
|
||||||
MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args), |
|
||||||
&grpc_lb_lrs_trace); |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log(GPR_INFO, "[lrs_lb %p] Created new child policy handler %p", this, |
|
||||||
lb_policy.get()); |
|
||||||
} |
|
||||||
// Add our interested_parties pollset_set to that of the newly created
|
|
||||||
// child policy. This will make the child policy progress upon activity on
|
|
||||||
// this policy, which in turn is tied to the application's call.
|
|
||||||
grpc_pollset_set_add_pollset_set(lb_policy->interested_parties(), |
|
||||||
interested_parties()); |
|
||||||
return lb_policy; |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::UpdateChildPolicyLocked(ServerAddressList addresses, |
|
||||||
const grpc_channel_args* args) { |
|
||||||
// Create policy if needed.
|
|
||||||
if (child_policy_ == nullptr) { |
|
||||||
child_policy_ = CreateChildPolicyLocked(args); |
|
||||||
} |
|
||||||
// Construct update args.
|
|
||||||
UpdateArgs update_args; |
|
||||||
update_args.addresses = std::move(addresses); |
|
||||||
update_args.config = config_->child_policy(); |
|
||||||
update_args.args = args; |
|
||||||
// Update the policy.
|
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log(GPR_INFO, "[lrs_lb %p] Updating child policy handler %p", this, |
|
||||||
child_policy_.get()); |
|
||||||
} |
|
||||||
child_policy_->UpdateLocked(std::move(update_args)); |
|
||||||
} |
|
||||||
|
|
||||||
//
|
|
||||||
// LrsLb::Helper
|
|
||||||
//
|
|
||||||
|
|
||||||
RefCountedPtr<SubchannelInterface> LrsLb::Helper::CreateSubchannel( |
|
||||||
ServerAddress address, const grpc_channel_args& args) { |
|
||||||
if (lrs_policy_->shutting_down_) return nullptr; |
|
||||||
return lrs_policy_->channel_control_helper()->CreateSubchannel( |
|
||||||
std::move(address), args); |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::Helper::UpdateState(grpc_connectivity_state state, |
|
||||||
const absl::Status& status, |
|
||||||
std::unique_ptr<SubchannelPicker> picker) { |
|
||||||
if (lrs_policy_->shutting_down_) return; |
|
||||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) { |
|
||||||
gpr_log( |
|
||||||
GPR_INFO, |
|
||||||
"[lrs_lb %p] child connectivity state update: state=%s (%s) picker=%p", |
|
||||||
lrs_policy_.get(), ConnectivityStateName(state), |
|
||||||
status.ToString().c_str(), picker.get()); |
|
||||||
} |
|
||||||
// Save the state and picker.
|
|
||||||
lrs_policy_->state_ = state; |
|
||||||
lrs_policy_->status_ = status; |
|
||||||
lrs_policy_->picker_ = MakeRefCounted<RefCountedPicker>(std::move(picker)); |
|
||||||
// Wrap the picker and return it to the channel.
|
|
||||||
lrs_policy_->MaybeUpdatePickerLocked(); |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::Helper::RequestReresolution() { |
|
||||||
if (lrs_policy_->shutting_down_) return; |
|
||||||
lrs_policy_->channel_control_helper()->RequestReresolution(); |
|
||||||
} |
|
||||||
|
|
||||||
void LrsLb::Helper::AddTraceEvent(TraceSeverity severity, |
|
||||||
absl::string_view message) { |
|
||||||
if (lrs_policy_->shutting_down_) return; |
|
||||||
lrs_policy_->channel_control_helper()->AddTraceEvent(severity, message); |
|
||||||
} |
|
||||||
|
|
||||||
//
|
|
||||||
// factory
|
|
||||||
//
|
|
||||||
|
|
||||||
class LrsLbFactory : public LoadBalancingPolicyFactory { |
|
||||||
public: |
|
||||||
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy( |
|
||||||
LoadBalancingPolicy::Args args) const override { |
|
||||||
grpc_error* error = GRPC_ERROR_NONE; |
|
||||||
RefCountedPtr<XdsClient> xds_client = XdsClient::GetOrCreate(&error); |
|
||||||
if (error != GRPC_ERROR_NONE) { |
|
||||||
gpr_log(GPR_ERROR, |
|
||||||
"cannot get XdsClient to instantiate lrs LB policy: %s", |
|
||||||
grpc_error_string(error)); |
|
||||||
GRPC_ERROR_UNREF(error); |
|
||||||
return nullptr; |
|
||||||
} |
|
||||||
return MakeOrphanable<LrsLb>(std::move(xds_client), std::move(args)); |
|
||||||
} |
|
||||||
|
|
||||||
const char* name() const override { return kLrs; } |
|
||||||
|
|
||||||
RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig( |
|
||||||
const Json& json, grpc_error** error) const override { |
|
||||||
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); |
|
||||||
if (json.type() == Json::Type::JSON_NULL) { |
|
||||||
// lrs was mentioned as a policy in the deprecated loadBalancingPolicy
|
|
||||||
// field or in the client API.
|
|
||||||
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:loadBalancingPolicy error:lrs policy requires configuration. " |
|
||||||
"Please use loadBalancingConfig field of service config instead."); |
|
||||||
return nullptr; |
|
||||||
} |
|
||||||
std::vector<grpc_error*> error_list; |
|
||||||
// Child policy.
|
|
||||||
RefCountedPtr<LoadBalancingPolicy::Config> child_policy; |
|
||||||
auto it = json.object_value().find("childPolicy"); |
|
||||||
if (it == json.object_value().end()) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:childPolicy error:required field missing")); |
|
||||||
} else { |
|
||||||
grpc_error* parse_error = GRPC_ERROR_NONE; |
|
||||||
child_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( |
|
||||||
it->second, &parse_error); |
|
||||||
if (child_policy == nullptr) { |
|
||||||
GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE); |
|
||||||
std::vector<grpc_error*> child_errors; |
|
||||||
child_errors.push_back(parse_error); |
|
||||||
error_list.push_back( |
|
||||||
GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors)); |
|
||||||
} |
|
||||||
} |
|
||||||
// Cluster name.
|
|
||||||
std::string cluster_name; |
|
||||||
it = json.object_value().find("clusterName"); |
|
||||||
if (it == json.object_value().end()) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:clusterName error:required field missing")); |
|
||||||
} else if (it->second.type() != Json::Type::STRING) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:clusterName error:type should be string")); |
|
||||||
} else { |
|
||||||
cluster_name = it->second.string_value(); |
|
||||||
} |
|
||||||
// EDS service name.
|
|
||||||
std::string eds_service_name; |
|
||||||
it = json.object_value().find("edsServiceName"); |
|
||||||
if (it != json.object_value().end()) { |
|
||||||
if (it->second.type() != Json::Type::STRING) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:edsServiceName error:type should be string")); |
|
||||||
} else { |
|
||||||
eds_service_name = it->second.string_value(); |
|
||||||
} |
|
||||||
} |
|
||||||
// Locality.
|
|
||||||
RefCountedPtr<XdsLocalityName> locality_name; |
|
||||||
it = json.object_value().find("locality"); |
|
||||||
if (it == json.object_value().end()) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:locality error:required field missing")); |
|
||||||
} else { |
|
||||||
std::vector<grpc_error*> child_errors = |
|
||||||
ParseLocality(it->second, &locality_name); |
|
||||||
if (!child_errors.empty()) { |
|
||||||
error_list.push_back( |
|
||||||
GRPC_ERROR_CREATE_FROM_VECTOR("field:locality", &child_errors)); |
|
||||||
} |
|
||||||
} |
|
||||||
// LRS load reporting server name.
|
|
||||||
std::string lrs_load_reporting_server_name; |
|
||||||
it = json.object_value().find("lrsLoadReportingServerName"); |
|
||||||
if (it == json.object_value().end()) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:lrsLoadReportingServerName error:required field missing")); |
|
||||||
} else if (it->second.type() != Json::Type::STRING) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"field:lrsLoadReportingServerName error:type should be string")); |
|
||||||
} else { |
|
||||||
lrs_load_reporting_server_name = it->second.string_value(); |
|
||||||
} |
|
||||||
if (!error_list.empty()) { |
|
||||||
*error = GRPC_ERROR_CREATE_FROM_VECTOR( |
|
||||||
"lrs_experimental LB policy config", &error_list); |
|
||||||
return nullptr; |
|
||||||
} |
|
||||||
return MakeRefCounted<LrsLbConfig>( |
|
||||||
std::move(child_policy), std::move(cluster_name), |
|
||||||
std::move(eds_service_name), std::move(lrs_load_reporting_server_name), |
|
||||||
std::move(locality_name)); |
|
||||||
} |
|
||||||
|
|
||||||
private: |
|
||||||
static std::vector<grpc_error*> ParseLocality( |
|
||||||
const Json& json, RefCountedPtr<XdsLocalityName>* name) { |
|
||||||
std::vector<grpc_error*> error_list; |
|
||||||
if (json.type() != Json::Type::OBJECT) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"locality field is not an object")); |
|
||||||
return error_list; |
|
||||||
} |
|
||||||
std::string region; |
|
||||||
auto it = json.object_value().find("region"); |
|
||||||
if (it != json.object_value().end()) { |
|
||||||
if (it->second.type() != Json::Type::STRING) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"\"region\" field is not a string")); |
|
||||||
} else { |
|
||||||
region = it->second.string_value(); |
|
||||||
} |
|
||||||
} |
|
||||||
std::string zone; |
|
||||||
it = json.object_value().find("zone"); |
|
||||||
if (it != json.object_value().end()) { |
|
||||||
if (it->second.type() != Json::Type::STRING) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"\"zone\" field is not a string")); |
|
||||||
} else { |
|
||||||
zone = it->second.string_value(); |
|
||||||
} |
|
||||||
} |
|
||||||
std::string subzone; |
|
||||||
it = json.object_value().find("subzone"); |
|
||||||
if (it != json.object_value().end()) { |
|
||||||
if (it->second.type() != Json::Type::STRING) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"\"subzone\" field is not a string")); |
|
||||||
} else { |
|
||||||
subzone = it->second.string_value(); |
|
||||||
} |
|
||||||
} |
|
||||||
if (region.empty() && zone.empty() && subzone.empty()) { |
|
||||||
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
||||||
"at least one of region, zone, or subzone must be set")); |
|
||||||
} |
|
||||||
if (error_list.empty()) { |
|
||||||
*name = MakeRefCounted<XdsLocalityName>(region, zone, subzone); |
|
||||||
} |
|
||||||
return error_list; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
} // namespace grpc_core
|
|
||||||
|
|
||||||
//
|
|
||||||
// Plugin registration
|
|
||||||
//
|
|
||||||
|
|
||||||
void grpc_lb_policy_lrs_init() { |
|
||||||
grpc_core::LoadBalancingPolicyRegistry::Builder:: |
|
||||||
RegisterLoadBalancingPolicyFactory( |
|
||||||
absl::make_unique<grpc_core::LrsLbFactory>()); |
|
||||||
} |
|
||||||
|
|
||||||
void grpc_lb_policy_lrs_shutdown() {} |
|
Loading…
Reference in new issue