Envoy源码分析之一--Server初始化(下)

举报
懒得想名字的麻辣香锅 发表于 2020/02/27 10:24:21 2020/02/27
【摘要】 *代码版本:stable/v1.7.1* 这里结合资料及源码仅分析正常场景的主干流程。本系列博文分为四部分,Server初始化,Envoy启动与新连接建立,Envoy对数据的读取、接收和处理,Envoy数据转发到服务端。 Server的初始化,初始化主要分为两部分,一是Envoy进程起来后的入口函数、二是Server的初始化。本章介绍第二部分。

*代码版本:stable/v1.7.1*

这里结合资料及源码仅分析正常场景的主干流程。本系列博文分为四部分,Server初始化,Envoy启动与新连接建立,Envoy对数据的读取、接收和处理,Envoy数据转发到服务端。

Server的初始化,初始化主要分为两部分,一是Envoy进程起来后的入口函数、二是Server的初始化。本章介绍第二部分。

##### 5. Server初始化

回到3和4中

初始化server是在上述构造函数体中的initialize中完成的,

image.png

这部分,这部分完成以下部分的server初始化。

image.png

###### 5.1 bootstrap

在InstanceImpl::initialize中,

image.png

image.png

从loadBootstrapConfig函数可知,通过loadFromFile和loadFromYaml读取配置文件路径下的配置,并完成参数校验。

image.png


5.2 admin API 初始化

admin初始化通过AdminImpl()实现

image.png

AdminImpl其入参,initial_config为Configuration::InitialImpl类型,将5.1中获取的配置文件生成结构化数据对象initial_config,并在初始化admin的时候将其相关参数取出使用。

image.png

这部分5.1的内容inital_config盖过不提,AdminImp()函数实现在admin.cc中,

image.png

image.png


从这里看,Admin API的功能是为管理员提供API管理Envoy。其中handlers_中提供了/certs、/clusters等API,以如下格式提供,

image.png

上面的字段对应的结构体为

image.png

在handler_对应的MAKE_ADMIN_HANDLER部分,对应的宏定义在server/admin.h中

image.png

这里,如果UrlHandler 的prefix字段和请求输入的prefix字段一致,就会执行X(path_and_query, response_headers, data, admin_stream),例如请求的是/config_dumps,则对应上上面/config_dumps那组结构体,那么handlerConfigDump被调用,进行相关解析,如果返回Http::Code:OK,则代表执行成功。具体每个handler函数内部的实现,这次不再分析,放到以后的博文里更新。


###### 5.3 Woker的初始化

Worker的初始化是Server初始化中的一个重要环境,由initialize中的如下代码进行初始化。

image.png

在listener_manager_impl.cc中的ListenerManagerImpl构造函数中实现wokrer的创建如下:

image.png

调用stl的emplace_back给workers List增加新的若干worker,每个woker由createWorker去实现,createWorker在worker_impl.cc中代码如下:

image.png

在createWorker中,初始化dispatcher时,调用api_.allocateDispatcher()获取Event::DispatcherImpl实例,

image.png

在DispatcherImpl的构造函数中,开了Buffer去管理Watermark,关于watermark和callback的机制(Envoy的内存管理)后续会单独有博文,这里简单提一下,这种机制主要是提供作为proxy的envoy在代理client和server间数据缓冲如何处理的能力。这里可以尝试搞一些数据面的性能优化,把Istio-proxy(envoy)的内存消耗设法降一降。DispatcherImpl构造函数代码如下:

image.png

可以看到,调用了DispatcherImpl方法,将Buffer::WatermarkFactoryPtr{new Buffer::WatermarkBufferFactory}作为入参调用下面带有入参的初始化函数。其中,Buffer::WatermarkFactoryPtr和Buffer::WatermarkBufferFactory的代码实现如下:

Buffer::WatermarkFactoryPtr:

image.png

Buffer:WaterBufferFactory:

image.png

可以看出,WatermarkBufferFactory 继承了WatermarkFactory,而WatermarkFactoryPtr独享了WatermarkFactory的实例地址。回到最终的函数调用

image.png

这里的实现很简单:在初始化列表中将上述提到的那个智能指针赋值给一个指向WatermarkBufferFactory 实例类型的unique_tr(  Buffer::WatermarkFactoryPtr buffer_factory_;)智能指针buffer_factory_,而这个buffer_factory智能指针,是DispatcherImpl类的私有成员变量,看下这个类的定义,

image.png

这个类是Event::Dispatcher的libevent implementation

至此,本节开头的 listener_manager_.reset函数就完成了worker的初始化工作。

###### 5.4 Cluster Discover Sevice(CDS)的初始化

初始化完成了worker,回到initialize函数中,继续向下,CDS的初始化,

image.png

cluster_manager_factory声明是一个指向Upstream::ClusterManagerFactory的unique_ptr类型指针,通过reset操作take ownership of reset里面的unique_ptr指针,详见[# std::[unique_ptr]::reset](http://www.cplusplus.com/reference/memory/unique_ptr/reset/)。

> Reset pointer

Destroys the object currently managed by the [unique_ptr](http://www.cplusplus.com/unique_ptr) (if any) and takes ownership of *p*.

If *p* is a *null pointer* (such as a default-initialized pointer), the [unique_ptr](http://www.cplusplus.com/unique_ptr) becomes empty, managing no object after the call.

To release the ownership of the [stored pointer](http://www.cplusplus.com/unique_ptr::get) without destroying it, use member function [release](http://www.cplusplus.com/unique_ptr::release) instead.


那么cluster_manager_factory接管的ProdClusterManagerFactory对象是谁呢?这是一个ClusterManagerFactory的工厂模式的实现,代码如下:

image.png

之后初始化main_config,在main_config->initialize中初始化CDS,其实现在configuration_impl.cc中实现。initialize的核心代码段如下

image.png

clusterManagerFromProto的实现在cluster_manager_impl.cc中

image.png

在一串初始化列表之后,返回了一个ClusterManagerImpl对象,这个对象的实现也在cluster_manager_impl.cc中,其中创建cds的核心代码如下,当从bootstrap中获取到cds的configuration后,就开始进行cds的创建操作。

image.png

createCds实现

image.png

**拿到了配置文件,在cds_api_impl.cc中实现CdsApiImpl::create如下,返回一个CdsApiImpl对象,在这个对象的构造函数中,注册了subscription,每当有事件更新时,都会通过subscriptionCallback注册回调,执行cdsApiImpl::onConfigUpdate(),通过ClusterManager实现addOrUpdateCluster或者removeCluster()并且在Envoy日志中打印关于cluster更新操作的日志。**

image.png

###### 5.5 Listener Discover Service(LDS)的初始化

Lds初始化和cds类似,流程在Cds初始化之后,核心代码如下:

创建:

image.png

createLdsApi:

image.png

 factory_.createLdsApi

image.png

**lds_api.cc中LdsApiImpl的构造函数,其中注册subscription,当有更新事件通过subscriptionCallbacks回调,用LdsApiImpl::onConfigUpdate实现ListenerManager的addOrUpdateListener或者removeListener(),并在Envoy日志中打印记录**

> 监听的是什么listener?


image.png

###### 5.6 GuardDog的初始化

GuardDog用于防止死锁

image.png

至此,Server初始化完成,下篇文章分析 Envoy是如何启动并建立新连接的。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。