Twemproxy源码分析(一)启动过程

23 篇文章 0 订阅
5 篇文章 0 订阅

概述:

Twemproxy是Twitter开发并开源的适用于Redis和Memcached的轻量级的缓存中间件,可以代理对Redis和Memcached的访问。因为项目需要,我们打算在此基础上进行二次开发,加入一些自己需要的功能(例如cluster之间的数据同步),所以需要深入了解一下Twemproxy源码,我将我阅读Twemproxy源码过程的笔记记录在此。

代码概况:

clone源码:

首先看一下代码规模:

代码规模不大只有1w多行,而且功能划分的比较清晰,包括:

  • 事件处理:event/nc_epoll.c、event/nc_event.h、event/nc_evport.c、event/nc_kqueue.c
  • 各种Hash函数:hashkit/nc_crc16.c、hashkit/nc_crc32.c、hashkit/nc_fnv.c、hashkit/nc_hashkit.h、hashkit/nc_hsieh.c、hashkit/nc_jenkins.c、hashkit/nc_ketama.c、hashkit/nc_md5.c、hashkit/nc_modula.c、hashkit/nc_murmur.c、hashkit/nc_one_at_a_time.c、hashkit/nc_random.c
  • 协议:proto/nc_memcache.c、proto/nc_proto.h、proto/nc_redis.c
  • 自定义的数据类型:nc_array.c、nc_array.h、nc_string.c、nc_string.h
  • 网络通信相关:nc_connection.c、nc_connection.h、nc_client.c、nc_client.h、nc_proxy.c、nc_proxy.h
  • 信号处理:nc_signal.c、nc_signal.h
  • 关键数据结构和算法:nc_rbtree.h、nc_rbtree.c、nc_queue.h、nc_request.c、nc_response.c、nc_mbuf.c、nc_mbuf.h、nc_message.c、nc_message.h、nc_server.c、nc_server.h
  • 统计、日志和工具:nc_stats.c、nc_stats.h、nc_log.c、nc_log.h、nc_util.c、nc_util.h
  • 配置文件:nc_conf.c、nc_conf.h
  • 主程序:nc.c、nc_core.c、nc_core.h

以上就是Twemproxy代码的概况。

启动主程序:

我们从main()函数开始看,main()函数在nc.c中,也就是Twemproxy的主程序。Twemproxy的main()函数非常短:

main函数的整理流程非常清晰,包含以下几步:

  1. 初始化option,设置默认值
  2. 从argv中获取option,若argv有错误则调用nc_show_usage()打印使用帮助
  3. 根据argv,判断是否是:show_version、show_help、describe_stats或者test_conf,是则执行相应逻辑后退出
  4. 依次调用nc_pre_run()、nc_run()和nc_post_run()

前面的步骤目前无关紧要,可以看出主要逻辑在nc_pre_run()、nc_run()和nc_post_run()函数中,也就是上面代码中高亮的部分。这三个函数的定义也在nc.c当中。

nc_pre_run()的函数逻辑是:

  1. 初始化日志
  2. 启动守护进程
  3. 初始化信号处理函数
  4. 创建pidfile
  5. 输出启动信息

如果nc_pre_run()运行失败,main()函数的逻辑中会调用nc_post_run()回收资源

nc_post_run()函数的主要逻辑是:

  1. 删除pidfile
  2. 信号处理函数deinit(这里其实什么也不做)
  3. 打印关闭信息
  4. 日志deinit(关闭日志文件描述符)

接下来就是比较重要的nc_run()

nc_run()函数封装的也不错,它的主要逻辑是:

  1. 调用core_start(),初始化上下文ctx
  2. 进入死循环,调用core_loop()进入事件循环
  3. 检查退出条件status != NC_OK,退出循环
  4. 调用core_stop()结束

可以看出细节都封装到了core_start()、core_loop()和core_stop()当中,但是nc.c主程序的逻辑到这里就结束了。值得一提的是,nc_daemonize()函数封装了创建守护进程的一个标准逻辑。

关键数据结构和数据类型:

程序到这里,涉及到了两个关键的数据结构和数据类型,一个是rstatus_t,一个是instance。

rstatus_t的定义在nc_core.h中,与它同时定义的还有err_t

如注释所写,rstatus_t定义返回状态,err_t定义错误类型。其中rstatus_t的可选值如上面宏定义描述,而err_t对应系统的errno。

然后我们看一下instance:

注释很明确,不再一一解释了。启动一个Twemproxy,就是生成一个实例(struct instance nci),这个实例保存了运行所需的一切信息,instance当中的字段通过nc_set_default_options()和nc_get_option()来初始化。

小结:

可以看到,Twemproxy的代码量很小,逻辑封装的也比较清晰,读起来是很舒服的。这一段中我们只看了主程序的启动过程,还未深入到细节,细节我们后面再看。这里需要着重记忆的是instance结构体,后面有多处会应用到

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值