-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Redis health check is not sending the auth command on it's connection #8166
Changes from 8 commits
662ebe4
fc133da
7a2f64d
36591d6
4898669
bc29429
d8d7217
4c8ab45
6531a42
73d02c8
a656dfa
92cd158
ff82723
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -214,10 +214,10 @@ class RedisCluster : public Upstream::BaseDynamicClusterImpl { | |
uint32_t maxBufferSizeBeforeFlush() const override { return 0; } | ||
std::chrono::milliseconds bufferFlushTimeoutInMs() const override { return buffer_timeout_; } | ||
uint32_t maxUpstreamUnknownConnections() const override { return 0; } | ||
// This is effectively not in used for making the "Cluster Slots" calls. | ||
// since we call cluster slots on both the master and slaves, ANY is more appropriate here. | ||
// This is effectively not in used for making the "Cluster Slots" calls, using Master to avoid | ||
// the READONLY command when establishing connection. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you flesh this comment out more? I don't understand from the comment why this was changed from any to master and what this is actually used for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before the change, the RedisDiscoverySession don't send "READONLY" and this readPolicy was not used at all in this context. After the change, the code to send "READONLY" command when a connection is created is move to RedisClientImpl, and it's gated on the readPolicy, so we need to set it to Master here to have the same behavior as before. |
||
Extensions::NetworkFilters::Common::Redis::Client::ReadPolicy readPolicy() const override { | ||
return Extensions::NetworkFilters::Common::Redis::Client::ReadPolicy::Any; | ||
return Extensions::NetworkFilters::Common::Redis::Client::ReadPolicy::Master; | ||
} | ||
|
||
// Extensions::NetworkFilters::Common::Redis::Client::PoolCallbacks | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,9 @@ namespace NetworkFilters { | |
namespace Common { | ||
namespace Redis { | ||
namespace Client { | ||
namespace { | ||
Common::Redis::Client::DoNothingPoolCallbacks null_pool_callbacks; | ||
} // namespace | ||
|
||
ConfigImpl::ConfigImpl( | ||
const envoy::config::filter::network::redis_proxy::v2::RedisProxy::ConnPoolSettings& config) | ||
|
@@ -49,7 +52,6 @@ ConfigImpl::ConfigImpl( | |
ClientPtr ClientImpl::create(Upstream::HostConstSharedPtr host, Event::Dispatcher& dispatcher, | ||
EncoderPtr&& encoder, DecoderFactory& decoder_factory, | ||
const Config& config) { | ||
|
||
std::unique_ptr<ClientImpl> client( | ||
new ClientImpl(host, dispatcher, std::move(encoder), decoder_factory, config)); | ||
client->connection_ = host->createConnection(dispatcher, nullptr, nullptr).connection_; | ||
|
@@ -245,12 +247,28 @@ void ClientImpl::PendingRequest::cancel() { | |
canceled_ = true; | ||
} | ||
|
||
void ClientImpl::initialize(const std::string& auth_password) { | ||
if (!auth_password.empty()) { | ||
// Send an AUTH command to the upstream server. | ||
makeRequest(Utility::makeAuthCommand(auth_password), null_pool_callbacks); | ||
} | ||
// Any connection to replica requires the READONLY command in order to perform read. | ||
// Also the READONLY command is a no-opt for the master. | ||
// We only need to send the READONLY command iff it's possible that the host is a replica. | ||
if (config_.readPolicy() != Common::Redis::Client::ReadPolicy::Master) { | ||
makeRequest(Utility::ReadOnlyRequest::instance(), null_pool_callbacks); | ||
} | ||
} | ||
|
||
ClientFactoryImpl ClientFactoryImpl::instance_; | ||
|
||
ClientPtr ClientFactoryImpl::create(Upstream::HostConstSharedPtr host, | ||
Event::Dispatcher& dispatcher, const Config& config) { | ||
return ClientImpl::create(host, dispatcher, EncoderPtr{new EncoderImpl()}, decoder_factory_, | ||
config); | ||
Event::Dispatcher& dispatcher, const Config& config, | ||
const std::string& auth_password) { | ||
ClientPtr client = | ||
ClientImpl::create(host, dispatcher, EncoderPtr{new EncoderImpl()}, decoder_factory_, config); | ||
client->initialize(auth_password); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason to have an explicit initialize function vs. doing this from within the context of the create/constructor call? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having the explicit initialize function makes it easier to test and adhere to the single responsibility principal better. The small perf hit of a function call is probably not a big issue given we don't create that many connections. I'm open to change this if you think it's better to put it in the create call. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine if you need it for testing, but generally I try to avoid extra functions unless its really beneficial. |
||
return client; | ||
} | ||
|
||
} // namespace Client | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.