Line data Source code
1 : #include "source/extensions/health_checkers/thrift/thrift.h" 2 : 3 : #include "source/extensions/filters/network/thrift_proxy/thrift.h" 4 : 5 : namespace Envoy { 6 : namespace Extensions { 7 : namespace HealthCheckers { 8 : namespace ThriftHealthChecker { 9 : 10 : namespace { 11 : 12 : // Helper functions to get the correct hostname for an L7 health check. 13 : const std::string& getHostname(const Upstream::HostSharedPtr& host, 14 0 : const Upstream::ClusterInfoConstSharedPtr& cluster) { 15 0 : return host->hostnameForHealthChecks().empty() ? cluster->name() 16 0 : : host->hostnameForHealthChecks(); 17 0 : } 18 : 19 : } // namespace 20 : 21 : ThriftHealthChecker::ThriftHealthChecker( 22 : const Upstream::Cluster& cluster, const envoy::config::core::v3::HealthCheck& config, 23 : const envoy::extensions::health_checkers::thrift::v3::Thrift& thrift_config, 24 : Event::Dispatcher& dispatcher, Runtime::Loader& runtime, 25 : Upstream::HealthCheckEventLoggerPtr&& event_logger, Api::Api& api, 26 : ClientFactory& client_factory) 27 : : HealthCheckerImplBase(cluster, config, dispatcher, runtime, api.randomGenerator(), 28 : std::move(event_logger)), 29 : method_name_(thrift_config.method_name()), 30 : transport_(ProtoUtils::getTransportType(thrift_config.transport())), 31 : protocol_(ProtoUtils::getProtocolType(thrift_config.protocol())), 32 0 : client_factory_(client_factory) { 33 0 : if (transport_ == TransportType::Auto || protocol_ == ProtocolType::Auto || 34 0 : protocol_ == ProtocolType::Twitter) { 35 0 : throw EnvoyException( 36 0 : fmt::format("Unsupported transport or protocol in thrift health check configuration: {}", 37 0 : thrift_config.DebugString())); 38 0 : } 39 0 : } 40 : 41 : ThriftHealthChecker::ThriftActiveHealthCheckSession::ThriftActiveHealthCheckSession( 42 : ThriftHealthChecker& parent, const Upstream::HostSharedPtr& host) 43 : : ActiveHealthCheckSession(parent, host), parent_(parent), 44 0 : hostname_(getHostname(host, parent_.cluster_.info())) { 45 0 : ENVOY_LOG(trace, "ThriftActiveHealthCheckSession construct hostname={}", hostname_); 46 0 : } 47 : 48 0 : ThriftHealthChecker::ThriftActiveHealthCheckSession::~ThriftActiveHealthCheckSession() { 49 0 : ENVOY_LOG(trace, "ThriftActiveHealthCheckSession destruct"); 50 0 : ASSERT(client_ == nullptr); 51 0 : } 52 : 53 0 : void ThriftHealthChecker::ThriftActiveHealthCheckSession::onDeferredDelete() { 54 0 : if (client_) { 55 0 : expect_close_ = true; 56 0 : client_->close(); 57 0 : } 58 0 : } 59 : 60 0 : void ThriftHealthChecker::ThriftActiveHealthCheckSession::onInterval() { 61 0 : ENVOY_LOG(trace, "ThriftActiveHealthCheckSession onInterval"); 62 0 : if (!client_) { 63 0 : ENVOY_LOG(trace, "ThriftActiveHealthCheckSession construct client"); 64 0 : client_ = parent_.client_factory_.create( 65 0 : *this, parent_.transport_, parent_.protocol_, parent_.method_name_, host_, 66 0 : /* health checker seq id */ 0, /* fixed_seq_id */ true); 67 0 : client_->start(); 68 0 : expect_close_ = false; 69 0 : } 70 : 71 0 : client_->sendRequest(); 72 0 : } 73 : 74 0 : void ThriftHealthChecker::ThriftActiveHealthCheckSession::onTimeout() { 75 0 : if (client_) { 76 0 : expect_close_ = true; 77 0 : client_->close(); 78 0 : } 79 0 : } 80 : 81 0 : void ThriftHealthChecker::ThriftActiveHealthCheckSession::onResponseResult(bool is_success) { 82 0 : if (is_success) { 83 0 : handleSuccess(); 84 0 : } else { 85 : // TODO(kuochunghsu): We might want to define retriable response. 86 0 : handleFailure(envoy::data::core::v3::ACTIVE, /* retriable */ false); 87 0 : } 88 : 89 0 : if (client_ && !parent_.reuse_connection_) { 90 0 : expect_close_ = true; 91 0 : client_->close(); 92 0 : } 93 0 : } 94 : 95 : Upstream::Host::CreateConnectionData 96 0 : ThriftHealthChecker::ThriftActiveHealthCheckSession::createConnection() { 97 0 : return host_->createHealthCheckConnection(parent_.dispatcher_, parent_.transportSocketOptions(), 98 0 : parent_.transportSocketMatchMetadata().get()); 99 0 : } 100 : 101 0 : void ThriftHealthChecker::ThriftActiveHealthCheckSession::onEvent(Network::ConnectionEvent event) { 102 0 : if (event == Network::ConnectionEvent::RemoteClose || 103 0 : event == Network::ConnectionEvent::LocalClose) { 104 0 : ENVOY_LOG(trace, "on event close, is_local_close={} expect_close={}", 105 0 : event == Network::ConnectionEvent::LocalClose, expect_close_); 106 0 : if (!expect_close_) { 107 0 : handleFailure(envoy::data::core::v3::NETWORK); 108 0 : } 109 : 110 0 : if (client_) { 111 : // Report failure if the connection was closed without receiving a full response. 112 0 : parent_.dispatcher_.deferredDelete(std::move(client_)); 113 0 : } 114 0 : } 115 0 : } 116 : 117 : } // namespace ThriftHealthChecker 118 : } // namespace HealthCheckers 119 : } // namespace Extensions 120 : } // namespace Envoy