代碼版本:stable/v1.7.1
這里結(jié)合資料及源碼僅分析正常場景的主干流程项玛。本系列博文分為四部分新娜,Server初始化推穷,Envoy啟動與新連接建立僧著,Envoy對數(shù)據(jù)的讀取履因、接收和處理,Envoy數(shù)據(jù)轉(zhuǎn)發(fā)到服務(wù)端盹愚。
本章介紹第一部分栅迄,Server的初始化,主要分為兩部分皆怕,一是Envoy進程起來后的入口函數(shù)毅舆、二是Server的初始化。
1. 入口
入口在source/exe/main.cc中
聲明并初始化Envoy::MainCommon實例為main_common愈腾,執(zhí)行main_common->run啟動Server憋活。
2. Envoy::MainCommon
main_common.h中Envoy::MainCommon class如下:
MainCommonBase的實例對象執(zhí)行run函數(shù)。
3. Envoy::MainCommonBase
頭文件中類定義如下:
class MainCommonBase函數(shù)實現(xiàn)方放在main_common.cc中如下:
Envoy::MainCommonBase constructor:
MainCommonBase::MainCommonBase(OptionsImpl& options) : options_(options) {
ares_library_init(ARES_LIB_INIT_ALL);
Event::Libevent::Global::initialize();
RELEASE_ASSERT(Envoy::Server::validateProtoDescriptors());
Stats::RawStatData::configure(options_);
switch (options_.mode()) {
case Server::Mode::InitOnly:
case Server::Mode::Serve: {
#ifdef ENVOY_HOT_RESTART
if (!options.hotRestartDisabled()) {
restarter_.reset(new Server::HotRestartImpl(options_));
}
#endif
if (restarter_.get() == nullptr) {
restarter_.reset(new Server::HotRestartNopImpl());
}
tls_.reset(new ThreadLocal::InstanceImpl);
Thread::BasicLockable& log_lock = restarter_->logLock();
Thread::BasicLockable& access_log_lock = restarter_->accessLogLock();
auto local_address = Network::Utility::getLocalAddress(options_.localAddressIpVersion());
Logger::Registry::initialize(options_.logLevel(), options_.logFormat(), log_lock);
stats_store_.reset(new Stats::ThreadLocalStoreImpl(restarter_->statsAllocator()));
server_.reset(new Server::InstanceImpl(
options_, local_address, default_test_hooks_, *restarter_, *stats_store_, access_log_lock,
component_factory_, std::make_unique<Runtime::RandomGeneratorImpl>(), *tls_));
break;
}
case Server::Mode::Validate:
restarter_.reset(new Server::HotRestartNopImpl());
Logger::Registry::initialize(options_.logLevel(), options_.logFormat(), restarter_->logLock());
break;
}
}
在上述構(gòu)造函數(shù)體中虱黄,初始化server
server_.reset(new Server::InstanceImpl(
options_, local_address, default_test_hooks_, *restarter_, *stats_store_, access_log_lock,
component_factory_, std::make_unique<Runtime::RandomGeneratorImpl>(), *tls_));
4. Server::InstanceImpl
Server.h定義InstanceImpl類:
server.cc中實現(xiàn)其構(gòu)造函數(shù)
InstanceImpl::InstanceImpl(Options& options, Network::Address::InstanceConstSharedPtr local_address,
TestHooks& hooks, HotRestart& restarter, Stats::StoreRoot& store,
Thread::BasicLockable& access_log_lock,
ComponentFactory& component_factory,
Runtime::RandomGeneratorPtr&& random_generator,
ThreadLocal::Instance& tls)
: options_(options), restarter_(restarter), start_time_(time(nullptr)),
original_start_time_(start_time_), stats_store_(store), thread_local_(tls),
api_(new Api::Impl(options.fileFlushIntervalMsec())), dispatcher_(api_->allocateDispatcher()),
singleton_manager_(new Singleton::ManagerImpl()),
handler_(new ConnectionHandlerImpl(ENVOY_LOGGER(), *dispatcher_)),
random_generator_(std::move(random_generator)), listener_component_factory_(*this),
worker_factory_(thread_local_, *api_, hooks),
secret_manager_(new Secret::SecretManagerImpl()),
dns_resolver_(dispatcher_->createDnsResolver({})),
access_log_manager_(*api_, *dispatcher_, access_log_lock, store), terminated_(false) {
try {
if (!options.logPath().empty()) {
try {
file_logger_ = std::make_unique<Logger::FileSinkDelegate>(
options.logPath(), access_log_manager_, Logger::Registry::getSink());
} catch (const EnvoyException& e) {
throw EnvoyException(
fmt::format("Failed to open log-file '{}'. e.what(): {}", options.logPath(), e.what()));
}
}
restarter_.initialize(*dispatcher_, *this);
drain_manager_ = component_factory.createDrainManager(*this);
initialize(options, local_address, component_factory);
} catch (const EnvoyException& e) {
ENVOY_LOG(critical, "error initializing configuration '{}': {}", options.configPath(),
e.what());
terminate();
throw;
}
}
其中Server初始化在initialize(options, local_address, component_factory);中進行悦即。
配置文件從InstanceUtil::loadBootstrapConfig中獲取,放到&options中去橱乱。
5. Server初始化
回到3和4中
初始化server是在上述構(gòu)造函數(shù)體中的initialize中完成的辜梳,
server_.reset(new Server::InstanceImpl(
options_, local_address, default_test_hooks_, *restarter_, *stats_store_, access_log_lock,
component_factory_, std::make_unique<Runtime::RandomGeneratorImpl>(), *tls_));
這部分,這部分完成以下部分的server初始化泳叠。
5.1 bootstrap
在InstanceImpl::initialize中作瞄,
// Handle configuration that needs to take place prior to the main configuration load.
InstanceUtil::loadBootstrapConfig(bootstrap_, options);
InstanceUtil::loadBootstrapConfig(envoy::config::bootstrap::v2::Bootstrap& bootstrap,
Options& options) {
try {
if (!options.configPath().empty()) {
MessageUtil::loadFromFile(options.configPath(), bootstrap);
}
if (!options.configYaml().empty()) {
envoy::config::bootstrap::v2::Bootstrap bootstrap_override;
MessageUtil::loadFromYaml(options.configYaml(), bootstrap_override);
bootstrap.MergeFrom(bootstrap_override);
}
MessageUtil::validate(bootstrap);
return BootstrapVersion::V2;
} catch (const EnvoyException& e) {
if (options.v2ConfigOnly()) {
throw;
}
// TODO(htuch): When v1 is deprecated, make this a warning encouraging config upgrade.
ENVOY_LOG(debug, "Unable to initialize config as v2, will retry as v1: {}", e.what());
}
if (!options.configYaml().empty()) {
throw EnvoyException("V1 config (detected) with --config-yaml is not supported");
}
Json::ObjectSharedPtr config_json = Json::Factory::loadFromFile(options.configPath());
Config::BootstrapJson::translateBootstrap(*config_json, bootstrap);
MessageUtil::validate(bootstrap);
return BootstrapVersion::V1;
}
從loadBootstrapConfig函數(shù)可知,通過loadFromFile和loadFromYaml讀取配置文件路徑下的配置危纫,并完成參數(shù)校驗粉洼。
5.2 admin API 初始化
admin初始化通過AdminImpl()實現(xiàn)
AdminImpl其入?yún)ⅲ琲nitial_config為Configuration::InitialImpl類型叶摄,將5.1中獲取的配置文件生成結(jié)構(gòu)化數(shù)據(jù)對象initial_config属韧,并在初始化admin的時候?qū)⑵湎嚓P(guān)參數(shù)取出使用。
Configuration::InitialImpl initial_config(bootstrap_);
這部分5.1的內(nèi)容inital_config蓋過不提蛤吓,AdminImp()函數(shù)實現(xiàn)在admin.cc中宵喂,
AdminImpl::AdminImpl(const std::string& access_log_path, const std::string& profile_path,
const std::string& address_out_path,
Network::Address::InstanceConstSharedPtr address, Server::Instance& server,
Stats::ScopePtr&& listener_scope)
: server_(server), profile_path_(profile_path),
socket_(new Network::TcpListenSocket(address, nullptr, true)),
stats_(Http::ConnectionManagerImpl::generateStats("http.admin.", server_.stats())),
tracing_stats_(
Http::ConnectionManagerImpl::generateTracingStats("http.admin.", no_op_store_)),
handlers_{
{"/", "Admin home page", MAKE_ADMIN_HANDLER(handlerAdminHome), false, false},
{"/certs", "print certs on machine", MAKE_ADMIN_HANDLER(handlerCerts), false, false},
{"/clusters", "upstream cluster status", MAKE_ADMIN_HANDLER(handlerClusters), false,
false},
{"/config_dump", "dump current Envoy configs (experimental)",
MAKE_ADMIN_HANDLER(handlerConfigDump), false, false},
{"/cpuprofiler", "enable/disable the CPU profiler",
MAKE_ADMIN_HANDLER(handlerCpuProfiler), false, true},
{"/healthcheck/fail", "cause the server to fail health checks",
MAKE_ADMIN_HANDLER(handlerHealthcheckFail), false, true},
{"/healthcheck/ok", "cause the server to pass health checks",
MAKE_ADMIN_HANDLER(handlerHealthcheckOk), false, true},
{"/help", "print out list of admin commands", MAKE_ADMIN_HANDLER(handlerHelp), false,
false},
{"/hot_restart_version", "print the hot restart compatibility version",
MAKE_ADMIN_HANDLER(handlerHotRestartVersion), false, false},
{"/logging", "query/change logging levels", MAKE_ADMIN_HANDLER(handlerLogging), false,
true},
{"/quitquitquit", "exit the server", MAKE_ADMIN_HANDLER(handlerQuitQuitQuit), false,
true},
{"/reset_counters", "reset all counters to zero",
MAKE_ADMIN_HANDLER(handlerResetCounters), false, true},
{"/server_info", "print server version/status information",
MAKE_ADMIN_HANDLER(handlerServerInfo), false, false},
{"/stats", "print server stats", MAKE_ADMIN_HANDLER(handlerStats), false, false},
{"/stats/prometheus", "print server stats in prometheus format",
MAKE_ADMIN_HANDLER(handlerPrometheusStats), false, false},
{"/listeners", "print listener addresses", MAKE_ADMIN_HANDLER(handlerListenerInfo), false,
false},
{"/runtime", "print runtime values", MAKE_ADMIN_HANDLER(handlerRuntime), false, false},
{"/runtime_modify", "modify runtime values", MAKE_ADMIN_HANDLER(handlerRuntimeModify),
false, true},
},
// TODO(jsedgwick) add /runtime_reset endpoint that removes all admin-set values
listener_(*this, std::move(listener_scope)),
admin_filter_chain_(std::make_shared<AdminFilterChain>()) {
//函數(shù)體從這里開始
if (!address_out_path.empty()) {
std::ofstream address_out_file(address_out_path);
if (!address_out_file) {
ENVOY_LOG(critical, "cannot open admin address output file {} for writing.",
address_out_path);
} else {
address_out_file << socket_->localAddress()->asString();
}
}
// TODO(mattklein123): Allow admin to use normal access logger extension loading and avoid the
// hard dependency here.
access_logs_.emplace_back(new Extensions::AccessLoggers::File::FileAccessLog(
access_log_path, {}, AccessLog::AccessLogFormatUtils::defaultAccessLogFormatter(),
server.accessLogManager()));
}
從這里看,Admin API的功能是為管理員提供API管理Envoy会傲。其中handlers_中提供了/certs锅棕、/clusters等API拙泽,以如下格式提供,
{"/config_dump", "dump current Envoy configs (experimental)",
MAKE_ADMIN_HANDLER(handlerConfigDump), false, false},
上面的字段對應(yīng)的結(jié)構(gòu)體為
struct UrlHandler {
const std::string prefix_;
const std::string help_text_;
const HandlerCb handler_;
const bool removable_;
const bool mutates_server_state_;
};
在handler_對應(yīng)的MAKE_ADMIN_HANDLER部分裸燎,對應(yīng)的宏定義在server/admin.h中
/**
* This macro is used to add handlers to the Admin HTTP Endpoint. It builds
* a callback that executes X when the specified admin handler is hit. This macro can be
* used to add static handlers as in source/server/http/admin.cc and also dynamic handlers as
* done in the RouteConfigProviderManagerImpl constructor in source/common/router/rds_impl.cc.
*/
#define MAKE_ADMIN_HANDLER(X) \
[this](absl::string_view path_and_query, Http::HeaderMap& response_headers, \
Buffer::Instance& data, AdminStream& admin_stream) -> Http::Code { \
return X(path_and_query, response_headers, data, admin_stream); \
}
這里顾瞻,如果UrlHandler 的prefix字段和請求輸入的prefix字段一致,就會執(zhí)行X(path_and_query, response_headers, data, admin_stream)德绿,例如請求的是/config_dumps荷荤,則對應(yīng)上上面/config_dumps那組結(jié)構(gòu)體,那么handlerConfigDump被調(diào)用移稳,進行相關(guān)解析蕴纳,如果返回Http::Code:OK,則代表執(zhí)行成功。具體每個handler函數(shù)內(nèi)部的實現(xiàn)个粱,這次不再分析古毛,放到以后的博文里更新。
5.3 Woker的初始化
Worker的初始化是Server初始化中的一個重要環(huán)境都许,由initialize中的如下代碼進行初始化稻薇。
// Workers get created first so they register for thread local updates.
listener_manager_.reset(
new ListenerManagerImpl(*this, listener_component_factory_, worker_factory_));
在listener_manager_impl.cc中的ListenerManagerImpl構(gòu)造函數(shù)中實現(xiàn)wokrer的創(chuàng)建如下:
ListenerManagerImpl::ListenerManagerImpl(Instance& server,
ListenerComponentFactory& listener_factory,
WorkerFactory& worker_factory)
: server_(server), factory_(listener_factory), stats_(generateStats(server.stats())),
config_tracker_entry_(server.admin().getConfigTracker().add(
"listeners", [this] { return dumpListenerConfigs(); })) {
for (uint32_t i = 0; i < std::max(1U, server.options().concurrency()); i++) {
workers_.emplace_back(worker_factory.createWorker());
}
}
調(diào)用stl的emplace_back給workers List增加新的若干worker,每個woker由createWorker去實現(xiàn)胶征,createWorker在worker_impl.cc中代碼如下:
WorkerPtr ProdWorkerFactory::createWorker() {
Event::DispatcherPtr dispatcher(api_.allocateDispatcher());
return WorkerPtr{new WorkerImpl(
tls_, hooks_, std::move(dispatcher),
Network::ConnectionHandlerPtr{new ConnectionHandlerImpl(ENVOY_LOGGER(), *dispatcher)})};
}
WorkerImpl::WorkerImpl(ThreadLocal::Instance& tls, TestHooks& hooks,
Event::DispatcherPtr&& dispatcher, Network::ConnectionHandlerPtr handler)
: tls_(tls), hooks_(hooks), dispatcher_(std::move(dispatcher)), handler_(std::move(handler)) {
tls_.registerThread(*dispatcher_, false);
}
在createWorker中塞椎,初始化dispatcher時,調(diào)用api_.allocateDispatcher()獲取Event::DispatcherImpl實例弧烤,
Event::DispatcherPtr Impl::allocateDispatcher() {
return Event::DispatcherPtr{new Event::DispatcherImpl()};
}
在DispatcherImpl的構(gòu)造函數(shù)中忱屑,開了Buffer去管理Watermark,關(guān)于watermark和callback的機制(Envoy的內(nèi)存管理)后續(xù)會單獨有博文暇昂,這里簡單提一下莺戒,這種機制主要是提供作為proxy的envoy在代理client和server間數(shù)據(jù)緩沖如何處理的能力。這里可以嘗試搞一些數(shù)據(jù)面的性能優(yōu)化急波,把Istio-proxy(envoy)的內(nèi)存消耗設(shè)法降一降从铲。DispatcherImpl構(gòu)造函數(shù)代碼如下:
DispatcherImpl::DispatcherImpl()
: DispatcherImpl(Buffer::WatermarkFactoryPtr{new Buffer::WatermarkBufferFactory}) {
// The dispatcher won't work as expected if libevent hasn't been configured to use threads.
RELEASE_ASSERT(Libevent::Global::initialized());
}
DispatcherImpl::DispatcherImpl(Buffer::WatermarkFactoryPtr&& factory)
: buffer_factory_(std::move(factory)), base_(event_base_new()),
deferred_delete_timer_(createTimer([this]() -> void { clearDeferredDeleteList(); })),
post_timer_(createTimer([this]() -> void { runPostCallbacks(); })),
current_to_delete_(&to_delete_1_) {
RELEASE_ASSERT(Libevent::Global::initialized());
}
可以看到,調(diào)用了DispatcherImpl方法澄暮,將Buffer::WatermarkFactoryPtr{new Buffer::WatermarkBufferFactory}作為入?yún)⒄{(diào)用下面帶有入?yún)⒌某跏蓟瘮?shù)名段。其中,Buffer::WatermarkFactoryPtr和Buffer::WatermarkBufferFactory的代碼實現(xiàn)如下:
Buffer::WatermarkFactoryPtr:
class WatermarkFactory {
public:
virtual ~WatermarkFactory() {}
/**
* Creates and returns a unique pointer to a new buffer.
* @param below_low_watermark supplies a function to call if the buffer goes under a configured
* low watermark.
* @param above_high_watermark supplies a function to call if the buffer goes over a configured
* high watermark.
* @return a newly created InstancePtr.
*/
virtual InstancePtr create(std::function<void()> below_low_watermark,
std::function<void()> above_high_watermark) PURE;
};
typedef std::unique_ptr<WatermarkFactory> WatermarkFactoryPtr;
Buffer:WaterBufferFactory:
class WatermarkBufferFactory : public WatermarkFactory {
public:
// Buffer::WatermarkFactory
InstancePtr create(std::function<void()> below_low_watermark,
std::function<void()> above_high_watermark) override {
return InstancePtr{new WatermarkBuffer(below_low_watermark, above_high_watermark)};
}
};
可以看出泣懊,WatermarkBufferFactory 繼承了WatermarkFactory伸辟,而WatermarkFactoryPtr獨享了WatermarkFactory的實例地址♀晒危回到最終的函數(shù)調(diào)用
DispatcherImpl::DispatcherImpl(Buffer::WatermarkFactoryPtr&& factory)
: buffer_factory_(std::move(factory)), base_(event_base_new()),
deferred_delete_timer_(createTimer([this]() -> void { clearDeferredDeleteList(); })),
post_timer_(createTimer([this]() -> void { runPostCallbacks(); })),
current_to_delete_(&to_delete_1_) {
RELEASE_ASSERT(Libevent::Global::initialized());
這里的實現(xiàn)很簡單:在初始化列表中將上述提到的那個智能指針賦值給一個指向WatermarkBufferFactory 實例類型的unique_tr( Buffer::WatermarkFactoryPtr buffer_factory_;)智能指針buffer_factory_信夫,而這個buffer_factory智能指針,是DispatcherImpl類的私有成員變量,看下這個類的定義静稻,
這個類是Event::Dispatcher的libevent implementation
至此警没,本節(jié)開頭的 listener_manager_.reset函數(shù)就完成了worker的初始化工作。
5.4 Cluster Discover Sevice(CDS)的初始化
初始化完成了worker振湾,回到initialize函數(shù)中杀迹,繼續(xù)向下,CDS的初始化押搪,
cluster_manager_factory_.reset(new Upstream::ProdClusterManagerFactory(
runtime(), stats(), threadLocal(), random(), dnsResolver(), sslContextManager(), dispatcher(),
localInfo(), secretManager()));
// Now the configuration gets parsed. The configuration may start setting thread local data
// per above. See MainImpl::initialize() for why we do this pointer dance.
Configuration::MainImpl* main_config = new Configuration::MainImpl();
config_.reset(main_config);
main_config->initialize(bootstrap_, *this, *cluster_manager_factory_);
cluster_manager_factory聲明是一個指向Upstream::ClusterManagerFactory的unique_ptr類型指針搞坝,通過reset操作take ownership of reset里面的unique_ptr指針统刮,詳見# std::[unique_ptr]::reset头滔。
Reset pointer
Destroys the object currently managed by the unique_ptr (if any) and takes ownership of p.
If p is a null pointer (such as a default-initialized pointer), the unique_ptr becomes empty, managing no object after the call.
To release the ownership of the stored pointer without destroying it, use member function release instead.
那么cluster_manager_factory接管的ProdClusterManagerFactory對象是誰呢辣苏?這是一個ClusterManagerFactory的工廠模式的實現(xiàn)及穗,代碼如下:
/**
* Production implementation of ClusterManagerFactory.
*/
class ProdClusterManagerFactory : public ClusterManagerFactory {
public:
ProdClusterManagerFactory(Runtime::Loader& runtime, Stats::Store& stats,
ThreadLocal::Instance& tls, Runtime::RandomGenerator& random,
Network::DnsResolverSharedPtr dns_resolver,
Ssl::ContextManager& ssl_context_manager,
Event::Dispatcher& main_thread_dispatcher,
const LocalInfo::LocalInfo& local_info,
Secret::SecretManager& secret_manager)
: main_thread_dispatcher_(main_thread_dispatcher), runtime_(runtime), stats_(stats),
tls_(tls), random_(random), dns_resolver_(dns_resolver),
ssl_context_manager_(ssl_context_manager), local_info_(local_info),
secret_manager_(secret_manager) {}
// Upstream::ClusterManagerFactory
ClusterManagerPtr
clusterManagerFromProto(const envoy::config::bootstrap::v2::Bootstrap& bootstrap,
Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime,
Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info,
AccessLog::AccessLogManager& log_manager, Server::Admin& admin) override;
Http::ConnectionPool::InstancePtr
allocateConnPool(Event::Dispatcher& dispatcher, HostConstSharedPtr host,
ResourcePriority priority, Http::Protocol protocol,
const Network::ConnectionSocket::OptionsSharedPtr& options) override;
ClusterSharedPtr clusterFromProto(const envoy::api::v2::Cluster& cluster, ClusterManager& cm,
Outlier::EventLoggerSharedPtr outlier_event_logger,
bool added_via_api) override;
CdsApiPtr createCds(const envoy::api::v2::core::ConfigSource& cds_config,
const absl::optional<envoy::api::v2::core::ConfigSource>& eds_config,
ClusterManager& cm) override;
Secret::SecretManager& secretManager() override { return secret_manager_; }
protected:
Event::Dispatcher& main_thread_dispatcher_;
private:
Runtime::Loader& runtime_;
Stats::Store& stats_;
ThreadLocal::Instance& tls_;
Runtime::RandomGenerator& random_;
Network::DnsResolverSharedPtr dns_resolver_;
Ssl::ContextManager& ssl_context_manager_;
const LocalInfo::LocalInfo& local_info_;
Secret::SecretManager& secret_manager_;
};
之后初始化main_config摧茴,在main_config->initialize中初始化CDS,其實現(xiàn)在configuration_impl.cc中實現(xiàn)埂陆。initialize的核心代碼段如下
cluster_manager_ = cluster_manager_factory.clusterManagerFromProto(
bootstrap, server.stats(), server.threadLocal(), server.runtime(), server.random(),
server.localInfo(), server.accessLogManager(), server.admin());
clusterManagerFromProto的實現(xiàn)在cluster_manager_impl.cc中
ClusterManagerPtr ProdClusterManagerFactory::clusterManagerFromProto(
const envoy::config::bootstrap::v2::Bootstrap& bootstrap, Stats::Store& stats,
ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random,
const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager,
Server::Admin& admin) {
return ClusterManagerPtr{new ClusterManagerImpl(bootstrap, *this, stats, tls, runtime, random,
local_info, log_manager, main_thread_dispatcher_,
admin)};
}
在一串初始化列表之后苛白,返回了一個ClusterManagerImpl對象,這個對象的實現(xiàn)也在cluster_manager_impl.cc中焚虱,其中創(chuàng)建cds的核心代碼如下,當(dāng)從bootstrap中獲取到cds的configuration后购裙,就開始進行cds的創(chuàng)建操作。
cds_api_ = factory_.createCds(bootstrap.dynamic_resources().cds_config(), eds_config_, *this);
init_helper_.setCds(cds_api_.get());
createCds實現(xiàn)
CdsApiPtr ProdClusterManagerFactory::createCds(
const envoy::api::v2::core::ConfigSource& cds_config,
const absl::optional<envoy::api::v2::core::ConfigSource>& eds_config, ClusterManager& cm) {
return CdsApiImpl::create(cds_config, eds_config, cm, main_thread_dispatcher_, random_,
local_info_, stats_);
}
拿到了配置文件鹃栽,在cds_api_impl.cc中實現(xiàn)CdsApiImpl::create如下躏率,返回一個CdsApiImpl對象,在這個對象的構(gòu)造函數(shù)中民鼓,注冊了subscription薇芝,每當(dāng)有事件更新時,都會通過subscriptionCallback注冊回調(diào)丰嘉,執(zhí)行cdsApiImpl::onConfigUpdate(),通過ClusterManager實現(xiàn)addOrUpdateCluster或者removeCluster()并且在Envoy日志中打印關(guān)于cluster更新操作的日志夯到。
CdsApiPtr CdsApiImpl::create(const envoy::api::v2::core::ConfigSource& cds_config,
const absl::optional<envoy::api::v2::core::ConfigSource>& eds_config,
ClusterManager& cm, Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random,
const LocalInfo::LocalInfo& local_info, Stats::Scope& scope) {
return CdsApiPtr{
new CdsApiImpl(cds_config, eds_config, cm, dispatcher, random, local_info, scope)};
}
CdsApiImpl::CdsApiImpl(const envoy::api::v2::core::ConfigSource& cds_config,
const absl::optional<envoy::api::v2::core::ConfigSource>& eds_config,
ClusterManager& cm, Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info,
Stats::Scope& scope)
: cm_(cm), scope_(scope.createScope("cluster_manager.cds.")) {
Config::Utility::checkLocalInfo("cds", local_info);
subscription_ =
Config::SubscriptionFactory::subscriptionFromConfigSource<envoy::api::v2::Cluster>(
cds_config, local_info.node(), dispatcher, cm, random, *scope_,
[this, &cds_config, &eds_config, &cm, &dispatcher, &random,
&local_info]() -> Config::Subscription<envoy::api::v2::Cluster>* {
return new CdsSubscription(Config::Utility::generateStats(*scope_), cds_config,
eds_config, cm, dispatcher, random, local_info);
},
"envoy.api.v2.ClusterDiscoveryService.FetchClusters",
"envoy.api.v2.ClusterDiscoveryService.StreamClusters");
}
5.5 Listener Discover Service(LDS)的初始化
Lds初始化和cds類似,流程在Cds初始化之后饮亏,核心代碼如下:
創(chuàng)建:
listener_manager_->createLdsApi(bootstrap_.dynamic_resources().lds_config());
createLdsApi:
void createLdsApi(const envoy::api::v2::core::ConfigSource& lds_config) override {
ASSERT(lds_api_ == nullptr);
lds_api_ = factory_.createLdsApi(lds_config);
}
factory_.createLdsApi
// Server::ListenerComponentFactory
LdsApiPtr createLdsApi(const envoy::api::v2::core::ConfigSource& lds_config) override {
return std::make_unique<LdsApiImpl>(
lds_config, server_.clusterManager(), server_.dispatcher(), server_.random(),
server_.initManager(), server_.localInfo(), server_.stats(), server_.listenerManager());
}
lds_api.cc中LdsApiImpl的構(gòu)造函數(shù)耍贾,其中注冊subscription,當(dāng)有更新事件通過subscriptionCallbacks回調(diào)路幸,用LdsApiImpl::onConfigUpdate實現(xiàn)ListenerManager的addOrUpdateListener或者removeListener()荐开,并在Envoy日志中打印記錄
監(jiān)聽的是什么listener?
LdsApiImpl::LdsApiImpl(const envoy::api::v2::core::ConfigSource& lds_config,
Upstream::ClusterManager& cm, Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random, Init::Manager& init_manager,
const LocalInfo::LocalInfo& local_info, Stats::Scope& scope,
ListenerManager& lm)
: listener_manager_(lm), scope_(scope.createScope("listener_manager.lds.")), cm_(cm) {
subscription_ =
Envoy::Config::SubscriptionFactory::subscriptionFromConfigSource<envoy::api::v2::Listener>(
lds_config, local_info.node(), dispatcher, cm, random, *scope_,
[this, &lds_config, &cm, &dispatcher, &random,
&local_info]() -> Config::Subscription<envoy::api::v2::Listener>* {
return new LdsSubscription(Config::Utility::generateStats(*scope_), lds_config, cm,
dispatcher, random, local_info);
},
"envoy.api.v2.ListenerDiscoveryService.FetchListeners",
"envoy.api.v2.ListenerDiscoveryService.StreamListeners");
Config::Utility::checkLocalInfo("lds", local_info);
init_manager.registerTarget(*this);
}
5.6 GuardDog的初始化
GuardDog用于防止死鎖
guard_dog_.reset(
new Server::GuardDogImpl(stats_store_, *config_, ProdMonotonicTimeSource::instance_));
至此简肴,Server初始化完成晃听,下篇文章分析 Envoy是如何啟動并建立新連接的。