twemproxy0.4原理分析-系统初始化过程原理分析

概述

本文介绍twemproxy的系统初始化过程。该过程包括以下几个方面的内容:

  • 读取配置文件,根据配置文件初始化数据结构
  • 和后台服务器建立连接,形成服务器连接池
  • 初始化事件处理框架,并设置最开始的事件处理函数
  • 创建twemproxy的监听socket,并把该监听socket添加到事件处理框架中,用来监听客户端的连接请求。

加载配置文件

twemproxy0.4是根据YAML文件格式来进行后台参数配置。在进程启动时通过-c或–conf-file选项来指定配置文件。启动的实际命令如下例子:

cd twemproxy-0.4.1
./src/nutcracker -c ./conf/nutcracker.yml

若下载的是twemproxy0.4的源码,配置文件的样例文件在源码根目录下的conf目录下。

样例配置文件example.yml如下:

alpha:
  listen: 0.0.0.0:22121
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  redis: true
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
   - 127.0.0.1:6379:1
   - 127.0.0.1:6378:1
   - 127.0.0.1:6377:1

beta:
  listen: 0.0.0.0:22122
  hash: fnv1a_64
  hash_tag: "{}"
  distribution: ketama
  auto_eject_hosts: false
  timeout: 400 
  redis: true
  servers:
   - 127.0.0.1:6380:1
   - 127.0.0.1:6381:1
   - 127.0.0.1:6382:1

配置文件中各个参数的说明如下:

  • listen参数

配置twemproxy监听的地址和端口。注意:每个服务池都需要配置一个监听地址和端口。监听的地址可以相同,但端口需要不同,这样twemproxy才能区分不同的服务器池。

从example.yml配置文件中的listen参数可以看出,有两个redis的服务器池,这两个服务器池分别由监听22122和22121的代理来服务。

  • client_connections

允许来自redis客户端的最大连接数。默认情况下无限制,但操作系统施加的限制仍然存在。

  • hash

使用的hash函数的名字。可以是以下几种:

函数名
md5
crc16
crc32
crc32a
fnv1_64
fnv1a_64
fnv1_32
fnv1a_32
hsieh
murmur
jenkins
  • hash_tag参数

由于key的分配非常重要,在使用集群时,最好能让key的分配可控性更强。

该参数可以让key的分配可控性更强。若为该服务器池配置了hash_tag,将会使用hash_tag之内的部分作为key分配的依据,否则会使用整个key的内容作为分配依据。

  • distribution

设置key分配算法,可以有三种:

(1) ketama: 通过一致性hash算法来选择后端服务器

(2) modula: 取模方式来选择后端服务器

(3) random: 随机选择一个后端服务器池中的服务器

  • timeout

我们等待建立与服务器的连接或从服务器接收响应的超时值(以毫秒为单位)。默认情况下会无限期地等待。

  • backlog

TCP listen的backlog参数。默认为512。

  • preconnect

一个布尔值,用于控制在进程启动时twemproxy是否应预先连接到此池中的所有服务器。默认为false。

  • redis

一个布尔值,用于控制服务器池是否使用redis或memcached协议。默认为false。

  • redis_auth

在连接时对Redis服务器进行身份验证。

  • redis_db

要在池服务器上使用的库编号(redis中可以通过select命令来选择数据库)。默认为0.注意:Twemproxy将始终以库 0的形式呈现给客户端。

  • server_connections

可以打开到每个服务器的最大连接数。默认情况下,我们最多打开1个服务器连接。

  • auto_eject_hosts

一个布尔值,用于控制服务器在连续失败server_failure_limit次数时是否应暂时去除。默认值为false

  • server_retry_timeout

当auto_eject_host设置为true时,在临时弹出的服务器上重试之前等待的超时值(以毫秒为单位)。默认为30000毫秒。

  • servers

此服务器池的服务器列表。格式如下:

 ip:port:weight  //ip地址:端口:权重

name:port:weight //主机名:端口:权重

系统初始化

系统初始化主要完成以下几件事情:

  • (1) 初始化三个空闲队列:空闲mbuf队列,空闲msg队列,空闲conn队列
  • (2) 初始化服务器池,若需要还要和后端服务建立连接
  • (3) 初始化服务器key分配算法,若选用一致性hash算法,还需要构建服务器的一致性hash环。
  • (4) 初始化事件处理框架,设置初始事件处理回调函数
  • (5) 启动事件处理框架

初始化空闲队列

空闲队列用来保存不再使用的数据结构实体,比如:mbuf,msg,conn,这样就可以复用这些结构体,再次使用时不需要再进行内存分配动作,从而提升了性能。

在twemproxy中会初始化三个空闲队列:mbuf结构体,msg结构体,conn结构体。空闲队列的初始化代码如下:

struct context *
core_start(struct instance *nci)
{
    struct context *ctx;

    mbuf_init(nci); // 初始化mbuf结构体空闲队列
    msg_init(); //初始化msg结构体空闲队列
    conn_init(); //初始化conn结构体空闲队列
    ... ...
}
  • 初始化mbuf队列

初始化mbuf空闲队列相对简单,主要是初始化静态变量:

tatic struct mhdr free_mbufq;

并设置每次创建mbuf结构时的内存块的size大小的变量:mbuf_chunk_size,该变量的默认值是:16k。

void
mbuf_init(struct instance *nci)
{
    nfree_mbufq = 0; //设置空闲队列的mbuf结构体个数
    STAILQ_INIT(&free_mbufq); //初始化队列

    mbuf_chunk_size = nci->mbuf_chunk_size;  //mbuf的chunk大小
    mbuf_offset = mbuf_chunk_size - MBUF_HSIZE; //mbuf的offset大小
    ... ...
}

free_mbufq初始化后的结构如下:

  • 初始化msg空闲队列

初始化msg空闲队列主要是初始化静态变量:free_msgq。

static struct msg_tqh free_msgq;

msg空闲队列初始化要完成以下事项:

(1) 设置msg队列的个数变量nfree_msgq为0

static struct msg_tqh free_msgq;

(2) 初始化静态变量free_msgq,该变量用来管理空闲队列

(3) 初始化一颗红黑树,后面要用该结构来保存msg的引用

初始化的代码如下:

void
msg_init(void)
{       
    ...
    msg_id = 0; //初始化msg_id,这是msg的计数器
    frag_id = 0; //初始化frag_id,这是fragment计数器
    nfree_msgq = 0; //初始化msg的个数为0
    TAILQ_INIT(&free_msgq); //初始化空闲msg队列
    rbtree_init(&tmo_rbt, &tmo_rbs); //初始化超时红黑树
} 
  • 初始化conn空闲队列

初始化conn空闲队列很简单,主要是初始化空闲conn队列的个数,并初始化free_connq队列。

static struct conn_tqh free_connq; 

初始化代码如下:

void
conn_init(void)
{
    ... ...  
    nfree_connq = 0;
    TAILQ_INIT(&free_connq); //初始化conn队列
}

初始化服务器池

若设置了preconnect参数为true,则会预先和后端服务器池中的每个服务器建立好连接。若按上面的服务器池配置,会得到如下的连接图:

上图只是一个示意图,实际上在ketama的这个一致性hash环中,还会存在多个虚拟的节点,会根据配置的权重来安排虚拟节点的个数,这些虚拟节点对应着图中的三个实体节点。详细的ketama算法的实现,可以阅读我的这篇文章:twemproxy0.4原理分析-一致性hash算法实现ketama分析。示意图如下:

设置事件处理函数

twemproxy0.4使用的事件驱动框架的入口都是相同的,只是不同的事件会调用不同的函数来处理。事件处理框架的函数调用流程如下:

总结

本文分析了twemproxy0.4的配置文件和系统的初始化过程。

参考资料

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值