envoy源码分析(一):启动

目录

第一节 main函数

第二节 创建server

创建ListenerManager

创建ClusterManager

第三节 启动server


envoy在处理请求时用到的主要的组件为Listener和Cluster,Listener负责监听downstream发送的请求,Listener监听到downstream发送的请求后,由Cluster来选择upstream中的某个端点来处理该请求,最终Listener将端点的回复信息传回到downstream,其架构图如下所示:

 Listener,Cluster在系统启动时会根据其配置被初始化。  Listener,Cluster和系统其余组件构成了一个完整的服务器,当所有这些组件初始化成功后,envoy服务器也初始化成功了,运行中的服务器可以不断的利用Listener,Cluster等组件来完成其工作。

envoy有一个基于事件的线程模型,主线程会管理envoy服务器的生命周期,配置处理,运行状态等,其余还有一些工作线程,这些工作线程用来处理各种网络请求。所有线程都围绕一个事件循环(libevent)操作,任何给定的downstream的TCP连接(包括其上的所有多路复用流)在其生命周期内都将由一个工作线程处理。每个工作线程会维护一个到 upstream的端点的TCP连接池。

接下来通过分析envoy的启动过程源码来看envoy是怎么创建其服务器的。

envoy源码地址:https://github.com/envoyproxy/envoy.git

第一节 main函数

envoy实现main函数的文件为source/exe/main.cc,main函数调用MainCommon::main实现了envoy的启动,MainCommon::main的代码如下所示:

source/exe/main_common.cc

  图1-1

第234,235行代码一起实例化了一个server,255行代码启动该server,至此,envoy就启动起来了。

第二节 创建server

envoy通过启动一个服务器server来工作,该server由各种组件组成,这里最关键的组件就是用于管理系统中的监听器listener的监听管理器ListenerManager,用来管理集群cluster的集群管理器ClusterManager,  server在初始化时会初始化这些组件。

第一节中234,235创建server时最终调用的server创建代码如下:

 source/exe/main_common.cc

图2-1

 这里是调用的Server::InstanceImpl类的构造函数构造了server的实例,下面来分析Server::InstanceImpl类的构造函数,代码如下所示:

source/server/server.cc

图2-2

Server::InstanceImpl类构造了server对象,并创建了该server需要的所有组件,比如用于管理系统中的监听器listener的监听管理器ListenerManager,用来管理集群cluster的集群管理器ClusterManager等。

 95行:创建并初始化文件日志系统,用于管理日志;

105行:初始化envoy的热重启功能模块,用于管理envoy服务器的热重启;

106行:初始化一个DrainManager,这个在服务器热重启或者动态删除Listener时会使用

107行:Server::InstanceImpl构造函数调用initialize来创建服务器的其余组件,监听管理器ListenerManager和集群管理器ClusterManager也是在这里创建的。

initialize核心代码如下所示:

source/server/server.cc

图2-3

图2-4

图2-5

346行:从配置文件中加载bootstrap信息

510行:创建ListenerManager来管理Listener

591行:通过从配置文件加载出来的bootstrap信息来创建静态的ClusterManager和listener

609行:初始化静态ClusterManager

创建ListenerManager

ListenerManager拥有一个或多个工作线程,每个工作线程会去处理一个给定的downstream的TCP连接,它会维护一个到 upstream的端点的TCP连接池。ListenerManager负责创建这些工作线程,工作线程创建好了以后ListenerManager就创建完成了。

上文中ListenerManager在source/server/server.cc的510行通过ListenerManagerImpl类的构造函数被创建,该构造函数传入了4个参数:

第一个参数this,是这里的server对象;第二个参数listener_component_factory_是监听器组件工厂类ProdListenerComponentFactory,它将创建真实的套接字,在系统热启动时它会尝试从父进程获取套接字;第三个参数worker_factory_是一个工作线程工厂类ProdWorkerFactory,它将用于为服务器创建工作线程;第四个参数是个布尔类型,指示是否启用事件分发器的统计功能,这个值默认是false,因为启用了事件分发器的统计功能后数据量可能会非常大,如果需要启用该统计功能,需要将bootstrap的enable_dispatcher_stats的值配置为true。下面我们来看ListenerManagerImpl类构造函数的代码:

envoy/source/server/listener_manager_impl.cc

图2-6

261行:server.options().concurrency() 是命令行指定的工作线程的个数,默认是一个

262行:创建工作线程,这里的worker_factory就是上文中提到的工作线程工厂类ProdWorkerFactory,其创建线程的额函数createWorker()如下所示:

envoy/source/server/worker_impl.cc

图2-7

创建ClusterManager

图2-5中,server创建了ClusterManager,config_是一个Configuration::MainImpl对象,其initialize方法实现如下:

source/server/configuration_impl.cc

图2-8

94行:通过bootstrap的中集群的配置来创建集群管理器。

96行:通过bootstrap的中配置的静态资源来创建了一系列静态的监听器。

98~101行:将这里创建的静态监听器加入到了前面已经创建好的监听管理器ListenerManager中

到这里,envoy服务器就创建完成了。接下来就要启动服务器了

第三节 启动server

图1-1中255行代码启动了server。这里最终调用的是Server::InstanceImpl对象的run()方法,run()代码如下:

source/server/server.cc

 图3-1

run()通过调用Server::RunHelper来运行,Server::RunHelper只有一个构造函数,这个构造函数在构造Server::RunHelper对象时启动server,Server::RunHelper的关键代码如下:

source/server/server.cc

图3-2

732行:这里初始化了一个init_watcher_,这是一个Init::WatcherImpl对象,这个对象的构造函数有两个参数,第一个参数是个字符串,是这个对象的名称,第二个参数是个回调函数,当Init::WatcherImpl对象被初始化管理器InitManager调用时,会执行该回调函数,回调函数中执行的是post_init_cb回调函数,从图3-1可知这里的post_init_cb回调函数中执行了startWorkers()函数,前文中在创建ListenerManager时创建了创建工作线程,这里startWorkers()函数就是将ListenerManager中的工作线程都启动起来。

770行:这里设置ClusterManager的初始化回调函数,当ClusterManager初始化成功后会调用该回调函数,该回调函数执行时,在786行InitManager会处理732行的init_watcher_对象,此时,post_init_cb函数会被执行,ListenerManager中的工作线程启动起来了,到此,ClusterManager和ListenerManager都就绪了,整个envoy服务器也就绪了。

Note:ClusterManager初始化包括静态初始化和动态初始化,如图2-5 ClusterManager的静态初始化发生在创建server时,当运行server时,静态的ClusterManager已经初始化成功,ListenerManager中工作线程会立即开始工作。CDs可以动态初始化ClusterManager,CDs相关的内容会在后续介绍

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值