Store address hierarchy information in attributes instead of channel args.

pull/24167/head
Mark D. Roth 4 years ago
parent 7862366047
commit 855a55a3c6
  1. 79
      src/core/ext/filters/client_channel/lb_policy/address_filtering.cc
  2. 12
      src/core/ext/filters/client_channel/lb_policy/address_filtering.h
  3. 7
      src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
  4. 80
      src/core/ext/filters/client_channel/server_address.cc
  5. 57
      src/core/ext/filters/client_channel/server_address.h
  6. 4
      src/core/ext/xds/xds_api.cc

@ -18,64 +18,77 @@
#include "src/core/ext/filters/client_channel/lb_policy/address_filtering.h" #include "src/core/ext/filters/client_channel/lb_policy/address_filtering.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#define GRPC_ARG_HIERARCHICAL_PATH "grpc.internal.address.hierarchical_path" #define GRPC_ARG_HIERARCHICAL_PATH "grpc.internal.address.hierarchical_path"
namespace grpc_core { namespace grpc_core {
const char* kHierarchicalPathAttributeKey = "hierarchical_path";
namespace { namespace {
void* HierarchicalPathCopy(void* p) { class HierarchicalPathAttribute : public ServerAddress::AttributeInterface {
std::vector<std::string>* path = static_cast<std::vector<std::string>*>(p); public:
return static_cast<void*>(new std::vector<std::string>(*path)); explicit HierarchicalPathAttribute(std::vector<std::string> path)
} : path_(std::move(path)) {}
void HierarchicalPathDestroy(void* p) { std::unique_ptr<AttributeInterface> Copy() const override {
std::vector<std::string>* path = static_cast<std::vector<std::string>*>(p); return absl::make_unique<HierarchicalPathAttribute>(path_);
delete path; }
}
int HierarchicalPathCompare(void* p1, void* p2) { int Cmp(const AttributeInterface* other) const override {
std::vector<std::string>* path1 = static_cast<std::vector<std::string>*>(p1); const std::vector<std::string>& other_path =
std::vector<std::string>* path2 = static_cast<std::vector<std::string>*>(p2); static_cast<const HierarchicalPathAttribute*>(other)->path_;
for (size_t i = 0; i < path1->size(); ++i) { for (size_t i = 0; i < path_.size(); ++i) {
if (path2->size() == i) return 1; if (other_path.size() == i) return 1;
int r = (*path1)[i].compare((*path2)[i]); int r = path_[i].compare(other_path[i]);
if (r != 0) return r; if (r != 0) return r;
} }
if (path2->size() > path1->size()) return -1; if (other_path.size() > path_.size()) return -1;
return 0; return 0;
} }
std::string ToString() const override {
return absl::StrCat("[", absl::StrJoin(path_, ", "), "]");
}
const grpc_arg_pointer_vtable hierarchical_path_arg_vtable = { const std::vector<std::string>& path() const { return path_; }
HierarchicalPathCopy, HierarchicalPathDestroy, HierarchicalPathCompare};
private:
std::vector<std::string> path_;
};
} // namespace } // namespace
grpc_arg MakeHierarchicalPathArg(const std::vector<std::string>& path) { std::unique_ptr<ServerAddress::AttributeInterface>
return grpc_channel_arg_pointer_create( MakeHierarchicalPathAttribute(std::vector<std::string> path) {
const_cast<char*>(GRPC_ARG_HIERARCHICAL_PATH), return absl::make_unique<HierarchicalPathAttribute>(std::move(path));
const_cast<std::vector<std::string>*>(&path),
&hierarchical_path_arg_vtable);
} }
HierarchicalAddressMap MakeHierarchicalAddressMap( HierarchicalAddressMap MakeHierarchicalAddressMap(
const ServerAddressList& addresses) { const ServerAddressList& addresses) {
HierarchicalAddressMap result; HierarchicalAddressMap result;
for (const ServerAddress& address : addresses) { for (const ServerAddress& address : addresses) {
auto* path = grpc_channel_args_find_pointer<std::vector<std::string>>( const HierarchicalPathAttribute* path_attribute =
address.args(), GRPC_ARG_HIERARCHICAL_PATH); static_cast<const HierarchicalPathAttribute*>(
if (path == nullptr || path->empty()) continue; address.GetAttribute(kHierarchicalPathAttributeKey));
auto it = path->begin(); if (path_attribute == nullptr) continue;
const std::vector<std::string>& path = path_attribute->path();
auto it = path.begin();
ServerAddressList& target_list = result[*it]; ServerAddressList& target_list = result[*it];
std::unique_ptr<HierarchicalPathAttribute> new_attribute;
++it; ++it;
std::vector<std::string> remaining_path(it, path->end()); if (it != path.end()) {
const char* name_to_remove = GRPC_ARG_HIERARCHICAL_PATH; std::vector<std::string> remaining_path(it, path.end());
grpc_arg new_arg = MakeHierarchicalPathArg(remaining_path); new_attribute = absl::make_unique<HierarchicalPathAttribute>(
grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove( std::move(remaining_path));
address.args(), &name_to_remove, 1, &new_arg, 1); }
target_list.emplace_back(address.address(), new_args); target_list.emplace_back(address.WithAttribute(
kHierarchicalPathAttributeKey, std::move(new_attribute)));
} }
return result; return result;
} }

@ -23,8 +23,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "absl/strings/string_view.h"
#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/server_address.h"
// The resolver returns a flat list of addresses. When a hierarchy of // The resolver returns a flat list of addresses. When a hierarchy of
@ -81,9 +79,13 @@
namespace grpc_core { namespace grpc_core {
// Constructs a channel arg containing the hierarchical path // The attribute key to be used for hierarchical paths in ServerAddress.
// to be associated with an address. extern const char* kHierarchicalPathAttributeKey;
grpc_arg MakeHierarchicalPathArg(const std::vector<std::string>& path);
// Constructs an address attribute containing the hierarchical path
// to be associated with the address.
std::unique_ptr<ServerAddress::AttributeInterface>
MakeHierarchicalPathAttribute(std::vector<std::string> path);
// A map from the next path element to the addresses that fall under // A map from the next path element to the addresses that fall under
// that path element. // that path element.

@ -591,10 +591,9 @@ ServerAddressList EdsLb::CreateChildPolicyAddressesLocked() {
std::vector<std::string> hierarchical_path = { std::vector<std::string> hierarchical_path = {
priority_child_name, locality_name->AsHumanReadableString()}; priority_child_name, locality_name->AsHumanReadableString()};
for (const auto& endpoint : locality.endpoints) { for (const auto& endpoint : locality.endpoints) {
grpc_arg new_arg = MakeHierarchicalPathArg(hierarchical_path); addresses.emplace_back(endpoint.WithAttribute(
grpc_channel_args* args = kHierarchicalPathAttributeKey,
grpc_channel_args_copy_and_add(endpoint.args(), &new_arg, 1); MakeHierarchicalPathAttribute(hierarchical_path)));
addresses.emplace_back(endpoint.address(), args);
} }
} }
} }

@ -20,6 +20,15 @@
#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/server_address.h"
#include <memory>
#include <string>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
namespace grpc_core { namespace grpc_core {
// //
@ -39,6 +48,38 @@ ServerAddress::ServerAddress(
address_.len = static_cast<socklen_t>(address_len); address_.len = static_cast<socklen_t>(address_len);
} }
ServerAddress::ServerAddress(const ServerAddress& other)
: address_(other.address_), args_(grpc_channel_args_copy(other.args_)) {
for (const auto& p : other.attributes_) {
attributes_[p.first] = p.second->Copy();
}
}
ServerAddress& ServerAddress::operator=(const ServerAddress& other) {
address_ = other.address_;
grpc_channel_args_destroy(args_);
args_ = grpc_channel_args_copy(other.args_);
attributes_.clear();
for (const auto& p : other.attributes_) {
attributes_[p.first] = p.second->Copy();
}
return *this;
}
ServerAddress::ServerAddress(ServerAddress&& other) noexcept
: address_(other.address_),
args_(other.args_),
attributes_(std::move(other.attributes_)) {
other.args_ = nullptr;
}
ServerAddress& ServerAddress::operator=(ServerAddress&& other) noexcept {
address_ = other.address_;
grpc_channel_args_destroy(args_);
args_ = other.args_;
other.args_ = nullptr;
attributes_ = std::move(other.attributes_);
return *this;
}
namespace { namespace {
int CompareAttributes( int CompareAttributes(
@ -78,4 +119,43 @@ int ServerAddress::Cmp(const ServerAddress& other) const {
return CompareAttributes(attributes_, other.attributes_); return CompareAttributes(attributes_, other.attributes_);
} }
const ServerAddress::AttributeInterface* ServerAddress::GetAttribute(
const char* key) const {
auto it = attributes_.find(key);
if (it == attributes_.end()) return nullptr;
return it->second.get();
}
// Returns a copy of the address with a modified attribute.
// If the new value is null, the attribute is removed.
ServerAddress ServerAddress::WithAttribute(
const char* key, std::unique_ptr<AttributeInterface> value) const {
ServerAddress address = *this;
if (value == nullptr) {
address.attributes_.erase(key);
} else {
address.attributes_[key] = std::move(value);
}
return address;
}
std::string ServerAddress::ToString() const {
std::vector<std::string> parts = {
grpc_sockaddr_to_string(&address_, false),
};
if (args_ != nullptr) {
parts.emplace_back(
absl::StrCat("args={", grpc_channel_args_string(args_), "}"));
}
if (!attributes_.empty()) {
std::vector<std::string> attrs;
for (const auto& p : attributes_) {
attrs.emplace_back(absl::StrCat(p.first, "=", p.second->ToString()));
}
parts.emplace_back(
absl::StrCat("attributes={", absl::StrJoin(attrs, ", "), "}"));
}
return absl::StrJoin(parts, " ");
}
} // namespace grpc_core } // namespace grpc_core

@ -22,6 +22,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <map> #include <map>
#include <memory>
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
@ -42,15 +43,22 @@ class ServerAddress {
// Base class for resolver-supplied attributes. // Base class for resolver-supplied attributes.
// Unlike channel args, these attributes don't affect subchannel // Unlike channel args, these attributes don't affect subchannel
// uniqueness or behavior. They are for use by LB policies only. // uniqueness or behavior. They are for use by LB policies only.
//
// Attributes are keyed by a C string that is unique by address, not
// by value. All attributes added with the same key must be of the
// same type.
class AttributeInterface { class AttributeInterface {
public: public:
virtual ~AttributeInterface(); virtual ~AttributeInterface() = default;
// Creates a copy of the attribute. // Creates a copy of the attribute.
virtual std::unique_ptr<AttributeInterface> Copy() const = 0; virtual std::unique_ptr<AttributeInterface> Copy() const = 0;
// Compares this attribute with another. // Compares this attribute with another.
virtual int Cmp(const AttributeInterface* other) const = 0; virtual int Cmp(const AttributeInterface* other) const = 0;
// Returns a human-readable representation of the attribute.
virtual std::string ToString() const = 0;
}; };
// Takes ownership of args. // Takes ownership of args.
@ -65,38 +73,12 @@ class ServerAddress {
~ServerAddress() { grpc_channel_args_destroy(args_); } ~ServerAddress() { grpc_channel_args_destroy(args_); }
// Copyable. // Copyable.
ServerAddress(const ServerAddress& other) ServerAddress(const ServerAddress& other);
: address_(other.address_), args_(grpc_channel_args_copy(other.args_)) { ServerAddress& operator=(const ServerAddress& other);
for (const auto& p : other.attributes_) {
attributes_[p.first] = p.second->Copy();
}
}
ServerAddress& operator=(const ServerAddress& other) {
address_ = other.address_;
grpc_channel_args_destroy(args_);
args_ = grpc_channel_args_copy(other.args_);
attributes_.clear();
for (const auto& p : other.attributes_) {
attributes_[p.first] = p.second->Copy();
}
return *this;
}
// Movable. // Movable.
ServerAddress(ServerAddress&& other) ServerAddress(ServerAddress&& other) noexcept;
: address_(other.address_), ServerAddress& operator=(ServerAddress&& other) noexcept;
args_(other.args_),
attributes_(std::move(other.attributes_)) {
other.args_ = nullptr;
}
ServerAddress& operator=(ServerAddress&& other) {
address_ = other.address_;
grpc_channel_args_destroy(args_);
args_ = other.args_;
other.args_ = nullptr;
attributes_ = std::move(other.attributes_);
return *this;
}
bool operator==(const ServerAddress& other) const { return Cmp(other) == 0; } bool operator==(const ServerAddress& other) const { return Cmp(other) == 0; }
@ -105,11 +87,14 @@ class ServerAddress {
const grpc_resolved_address& address() const { return address_; } const grpc_resolved_address& address() const { return address_; }
const grpc_channel_args* args() const { return args_; } const grpc_channel_args* args() const { return args_; }
const AttributeInterface* GetAttribute(const char* key) const { const AttributeInterface* GetAttribute(const char* key) const;
auto it = attributes_.find(key);
if (it == attributes_.end()) return nullptr; // Returns a copy of the address with a modified attribute.
return it->second.get(); // If the new value is null, the attribute is removed.
} ServerAddress WithAttribute(const char* key,
std::unique_ptr<AttributeInterface> value) const;
std::string ToString() const;
private: private:
grpc_resolved_address address_; grpc_resolved_address address_;

@ -381,9 +381,7 @@ XdsApi::RdsUpdate::VirtualHost* XdsApi::RdsUpdate::FindVirtualHostForDomain(
std::string XdsApi::EdsUpdate::Priority::Locality::ToString() const { std::string XdsApi::EdsUpdate::Priority::Locality::ToString() const {
std::vector<std::string> endpoint_strings; std::vector<std::string> endpoint_strings;
for (const ServerAddress& endpoint : endpoints) { for (const ServerAddress& endpoint : endpoints) {
endpoint_strings.emplace_back( endpoint_strings.emplace_back(endpoint.ToString());
absl::StrCat(grpc_sockaddr_to_string(&endpoint.address(), false), "{",
grpc_channel_args_string(endpoint.args()), "}"));
} }
return absl::StrCat("{name=", name->AsHumanReadableString(), return absl::StrCat("{name=", name->AsHumanReadableString(),
", lb_weight=", lb_weight, ", endpoints=[", ", lb_weight=", lb_weight, ", endpoints=[",

Loading…
Cancel
Save