Line data Source code
1 : #pragma once 2 : 3 : #include <chrono> 4 : 5 : #include "envoy/api/api.h" 6 : #include "envoy/config/core/v3/health_check.pb.h" 7 : #include "envoy/data/core/v3/health_check_event.pb.h" 8 : #include "envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.pb.h" 9 : #include "envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.pb.validate.h" 10 : #include "envoy/extensions/health_checkers/redis/v3/redis.pb.h" 11 : 12 : #include "source/extensions/filters/network/common/redis/client_impl.h" 13 : #include "source/extensions/filters/network/redis_proxy/config.h" 14 : #include "source/extensions/filters/network/redis_proxy/conn_pool_impl.h" 15 : #include "source/extensions/health_checkers/common/health_checker_base_impl.h" 16 : 17 : namespace Envoy { 18 : namespace Extensions { 19 : namespace HealthCheckers { 20 : namespace RedisHealthChecker { 21 : 22 : /** 23 : * All redis health checker stats. @see stats_macros.h 24 : */ 25 0 : #define ALL_REDIS_HEALTH_CHECKER_STATS(COUNTER) COUNTER(exists_failure) 26 : 27 : /** 28 : * Definition of all redis health checker stats. @see stats_macros.h 29 : */ 30 : struct RedisHealthCheckerStats { 31 : ALL_REDIS_HEALTH_CHECKER_STATS(GENERATE_COUNTER_STRUCT) 32 : }; 33 : 34 : /** 35 : * Redis health checker implementation. Sends PING and expects PONG. 36 : */ 37 : class RedisHealthChecker : public Upstream::HealthCheckerImplBase { 38 : public: 39 : RedisHealthChecker( 40 : const Upstream::Cluster& cluster, const envoy::config::core::v3::HealthCheck& config, 41 : const envoy::extensions::health_checkers::redis::v3::Redis& redis_config, 42 : Event::Dispatcher& dispatcher, Runtime::Loader& runtime, 43 : Upstream::HealthCheckEventLoggerPtr&& event_logger, Api::Api& api, 44 : Extensions::NetworkFilters::Common::Redis::Client::ClientFactory& client_factory); 45 : 46 0 : static const NetworkFilters::Common::Redis::RespValue& pingHealthCheckRequest() { 47 0 : static HealthCheckRequest* request = new HealthCheckRequest(); 48 0 : return request->request_; 49 0 : } 50 : 51 : static const NetworkFilters::Common::Redis::RespValue& 52 0 : existsHealthCheckRequest(const std::string& key) { 53 0 : static HealthCheckRequest* request = new HealthCheckRequest(key); 54 0 : return request->request_; 55 0 : } 56 : 57 : protected: 58 0 : envoy::data::core::v3::HealthCheckerType healthCheckerType() const override { 59 0 : return envoy::data::core::v3::REDIS; 60 0 : } 61 : 62 : private: 63 : friend class RedisHealthCheckerTest; 64 : RedisHealthCheckerStats generateRedisStats(Stats::Scope& scope); 65 : 66 : struct RedisActiveHealthCheckSession 67 : : public ActiveHealthCheckSession, 68 : public Extensions::NetworkFilters::Common::Redis::Client::Config, 69 : public Extensions::NetworkFilters::Common::Redis::Client::ClientCallbacks, 70 : public Network::ConnectionCallbacks { 71 : RedisActiveHealthCheckSession(RedisHealthChecker& parent, const Upstream::HostSharedPtr& host); 72 : ~RedisActiveHealthCheckSession() override; 73 : 74 : // ActiveHealthCheckSession 75 : void onInterval() override; 76 : void onTimeout() override; 77 : void onDeferredDelete() final; 78 : 79 : // Extensions::NetworkFilters::Common::Redis::Client::Config 80 0 : bool disableOutlierEvents() const override { return true; } 81 0 : std::chrono::milliseconds opTimeout() const override { 82 : // Allow the main Health Check infra to control timeout. 83 0 : return parent_.timeout_ * 2; 84 0 : } 85 0 : bool enableHashtagging() const override { return false; } 86 0 : bool enableRedirection() const override { 87 0 : return true; 88 0 : } // Redirection errors are treated as check successes. 89 0 : NetworkFilters::Common::Redis::Client::ReadPolicy readPolicy() const override { 90 0 : return NetworkFilters::Common::Redis::Client::ReadPolicy::Primary; 91 0 : } 92 : 93 : // Batching 94 0 : unsigned int maxBufferSizeBeforeFlush() const override { 95 0 : return 0; 96 0 : } // Forces an immediate flush 97 0 : std::chrono::milliseconds bufferFlushTimeoutInMs() const override { 98 0 : return std::chrono::milliseconds(1); 99 0 : } 100 : 101 0 : uint32_t maxUpstreamUnknownConnections() const override { return 0; } 102 0 : bool enableCommandStats() const override { return false; } 103 0 : bool connectionRateLimitEnabled() const override { return false; } 104 0 : uint32_t connectionRateLimitPerSec() const override { return 0; } 105 : 106 : // Extensions::NetworkFilters::Common::Redis::Client::ClientCallbacks 107 : void onResponse(NetworkFilters::Common::Redis::RespValuePtr&& value) override; 108 : void onFailure() override; 109 : void onRedirection(NetworkFilters::Common::Redis::RespValuePtr&&, const std::string&, 110 : bool) override; 111 : 112 : // Network::ConnectionCallbacks 113 : void onEvent(Network::ConnectionEvent event) override; 114 0 : void onAboveWriteBufferHighWatermark() override {} 115 0 : void onBelowWriteBufferLowWatermark() override {} 116 : 117 : RedisHealthChecker& parent_; 118 : Extensions::NetworkFilters::Common::Redis::Client::ClientPtr client_; 119 : Extensions::NetworkFilters::Common::Redis::Client::PoolRequest* current_request_{}; 120 : Extensions::NetworkFilters::Common::Redis::RedisCommandStatsSharedPtr redis_command_stats_; 121 : }; 122 : 123 : enum class Type { Ping, Exists }; 124 : 125 : struct HealthCheckRequest { 126 : HealthCheckRequest(const std::string& key); 127 : HealthCheckRequest(); 128 : 129 : NetworkFilters::Common::Redis::RespValue request_; 130 : }; 131 : 132 : using RedisActiveHealthCheckSessionPtr = std::unique_ptr<RedisActiveHealthCheckSession>; 133 : 134 : // HealthCheckerImplBase 135 0 : ActiveHealthCheckSessionPtr makeSession(Upstream::HostSharedPtr host) override { 136 0 : return std::make_unique<RedisActiveHealthCheckSession>(*this, host); 137 0 : } 138 : 139 : Extensions::NetworkFilters::Common::Redis::Client::ClientFactory& client_factory_; 140 : Type type_; 141 : const std::string key_; 142 : RedisHealthCheckerStats redis_stats_; 143 : const std::string auth_username_; 144 : const std::string auth_password_; 145 : }; 146 : 147 : } // namespace RedisHealthChecker 148 : } // namespace HealthCheckers 149 : } // namespace Extensions 150 : } // namespace Envoy