1:整体初始化过程
第二节中我们谈到了在twemproxy启动过程中,需要在core_start这个函数中创建context,这个core_start函数里就完成了配置文件的解析以及相应组件的初始化。下边定位到core.c: core_start这个函数,我们来看看它的具体实现。
1):struct context *ctx;
首先,在这个函数的开始,创建了一个context对象。context,顾名思义:上下文,我们看它的定义:
一个context含有id, cf(配置),stats,
pool:server_pool, 因为一个配置文件中会有很多个节点,每一个节点其实就是一个server_ pool, 所以这里的pool是一个array.
ep:epoll描述符,twemproxy的事件驱动是基于epoll的。
nevent:调用epoll_waite是返回epoll_event的个数。
2):定义了context之后,便是对context这个变量分配内存以及对里边的元素做一些初始化。然后主要的初始化过程都在core_ctx_create这个函数里。
3):ctx->cf = conf_create(nci->conf_filename);这个函数里将会读取并解析配置文件,相关的配置将会存储在conf这样一个对象中并返回赋值给ctx->cf。
4): status = server_pool_init(&ctx->pool, &ctx->cf->pool, ctx); 这个函数主要完成的是将配置中的每一个节点(conf_pool)转换成server_pool,最后的转换结果会存储在ctx->pool(array对象)中。
5): ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval, nci->hostname, &ctx->pool); 为每一个server创建stats。
6): status = event_init(ctx, EVENT_SIZE_HINT);初始化epoll。
7): status = server_pool_preconnect(ctx);根据配置中的preconnect这项判断是否跟后端server建立一个连接。
8):status = proxy_init(ctx);对每一个server_pool(配置文件中的一个节点)初始化proxy, 即创建套接字,绑定proxy监听的接口,给套接字增加读写事件处理函数,并添加到epoll中。
通过这八个步骤,server_pool, stats, proxy都初始化完成,core_create创建context成功返回,最后回到nc_run启动事件轮训,程序启动,调用epoll_wait开始事件的处理。
2:server_pool及server的初始化
上面我们谈到了在context的创建过程中会调用server_pool_init进行server_pool的初始化,现在我们看下server_pool具体的初始化过程。即nc_server.c: server_pool_init这个函数,
首先通过 npool = array_n(conf_pool);通过这里,计算出总共配置了多少个server_pool(配置节点)。然后通过array_init初始化server_pool这个数组,其中这个array_init函数主要干的就是给server_pool的elem分配npool*sizeof(server_pool)大小的内存,然后将其他的属性也相应的初始化。注意,调用server_pool_init这个函数的时候,传递的第一个数是context-pool, 这个pool是一个array类型的数组,所以下边会调用array_each,并且传递一个函数指针作为回调函数,在这个回调函数里,会根据配置文件的配置信息,完成每一个struct server_pool的初始化工作。