mirror of https://github.com/grpc/grpc.git
[LB policy API] change metadata mutation API to handle discarded picks (#36968)
Previously, metadata mutations were made by the picker directly, which meant that they would be applied even if the channel winds up discarding the pick due to the returned subchannel having been disconnected by the time the pick result is returned. This changes the API such that pickers return metadata mutations along with the pick result, so that the mutations won't get applied unless the pick result is actually used.
Closes #36968
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36968 from markdroth:lb_metadata_api 2765da6121
PiperOrigin-RevId: 645451869
pull/37017/head
parent
698a66b9c3
commit
34a0318dbf
40 changed files with 355 additions and 259 deletions
@ -0,0 +1,99 @@ |
|||||||
|
// Copyright 2024 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 "src/core/client_channel/lb_metadata.h" |
||||||
|
|
||||||
|
#include "absl/log/log.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
//
|
||||||
|
// LbMetadata
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
class Encoder { |
||||||
|
public: |
||||||
|
void Encode(const Slice& key, const Slice& value) { |
||||||
|
out_.emplace_back(std::string(key.as_string_view()), |
||||||
|
std::string(value.as_string_view())); |
||||||
|
} |
||||||
|
|
||||||
|
template <class Which> |
||||||
|
void Encode(Which, const typename Which::ValueType& value) { |
||||||
|
auto value_slice = Which::Encode(value); |
||||||
|
out_.emplace_back(std::string(Which::key()), |
||||||
|
std::string(value_slice.as_string_view())); |
||||||
|
} |
||||||
|
|
||||||
|
void Encode(GrpcTimeoutMetadata, |
||||||
|
const typename GrpcTimeoutMetadata::ValueType&) {} |
||||||
|
void Encode(HttpPathMetadata, const Slice&) {} |
||||||
|
void Encode(HttpMethodMetadata, |
||||||
|
const typename HttpMethodMetadata::ValueType&) {} |
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> Take() { |
||||||
|
return std::move(out_); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<std::pair<std::string, std::string>> out_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
absl::optional<absl::string_view> LbMetadata::Lookup( |
||||||
|
absl::string_view key, std::string* buffer) const { |
||||||
|
if (batch_ == nullptr) return absl::nullopt; |
||||||
|
return batch_->GetStringValue(key, buffer); |
||||||
|
} |
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> |
||||||
|
LbMetadata::TestOnlyCopyToVector() const { |
||||||
|
if (batch_ == nullptr) return {}; |
||||||
|
Encoder encoder; |
||||||
|
batch_->Encode(&encoder); |
||||||
|
return encoder.Take(); |
||||||
|
} |
||||||
|
|
||||||
|
//
|
||||||
|
// MetadataMutationHandler
|
||||||
|
//
|
||||||
|
|
||||||
|
void MetadataMutationHandler::Apply( |
||||||
|
LoadBalancingPolicy::MetadataMutations& metadata_mutations, |
||||||
|
grpc_metadata_batch* metadata) { |
||||||
|
for (auto& p : metadata_mutations.additions_) { |
||||||
|
absl::string_view key = p.first; |
||||||
|
Slice& value = |
||||||
|
grpc_event_engine::experimental::internal::SliceCast<Slice>(p.second); |
||||||
|
// Gross, egregious hack to support legacy grpclb behavior.
|
||||||
|
// TODO(ctiller): Use a promise context for this once that plumbing is done.
|
||||||
|
if (key == GrpcLbClientStatsMetadata::key()) { |
||||||
|
metadata->Set( |
||||||
|
GrpcLbClientStatsMetadata(), |
||||||
|
const_cast<GrpcLbClientStats*>( |
||||||
|
reinterpret_cast<const GrpcLbClientStats*>(value.data()))); |
||||||
|
continue; |
||||||
|
} |
||||||
|
metadata->Append(key, std::move(value), |
||||||
|
[key](absl::string_view error, const Slice& value) { |
||||||
|
LOG(ERROR) << error << " key:" << key |
||||||
|
<< " value:" << value.as_string_view(); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc_core
|
@ -0,0 +1,50 @@ |
|||||||
|
// Copyright 2024 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.
|
||||||
|
|
||||||
|
#ifndef GRPC_SRC_CORE_CLIENT_CHANNEL_LB_METADATA_H |
||||||
|
#define GRPC_SRC_CORE_CLIENT_CHANNEL_LB_METADATA_H |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "absl/strings/string_view.h" |
||||||
|
#include "absl/types/optional.h" |
||||||
|
|
||||||
|
#include "src/core/lib/transport/metadata_batch.h" |
||||||
|
#include "src/core/load_balancing/lb_policy.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
class LbMetadata : public LoadBalancingPolicy::MetadataInterface { |
||||||
|
public: |
||||||
|
explicit LbMetadata(grpc_metadata_batch* batch) : batch_(batch) {} |
||||||
|
|
||||||
|
absl::optional<absl::string_view> Lookup(absl::string_view key, |
||||||
|
std::string* buffer) const override; |
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> TestOnlyCopyToVector() const; |
||||||
|
|
||||||
|
private: |
||||||
|
grpc_metadata_batch* batch_; |
||||||
|
}; |
||||||
|
|
||||||
|
class MetadataMutationHandler { |
||||||
|
public: |
||||||
|
static void Apply(LoadBalancingPolicy::MetadataMutations& metadata_mutations, |
||||||
|
grpc_metadata_batch* metadata); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
#endif // GRPC_SRC_CORE_CLIENT_CHANNEL_LB_METADATA_H
|
Loading…
Reference in new issue