失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > twemproxy源码解析1 源码文件总体简介

twemproxy源码解析1 源码文件总体简介

时间:2019-07-04 07:17:09

相关推荐

twemproxy源码解析1  源码文件总体简介

在正式开始阅读代码之前,先来看一下代码整体结构

代码规模不大只有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

src/nc.c文件 是程序入口main函数所在,下面我给各个函数加了注释

intmain(int argc, char **argv){rstatus_t status; //rstatus_t 返回类型struct instance nci;//nc实例nc_set_default_options(&nci); //为nc实例设置一些默认的参数属性值 之后具体介绍status = nc_get_options(argc, argv, &nci); //获取参数 解析参数if (status != NC_OK) {nc_show_usage();exit(1);}if (show_version) {//打印版本号log_stderr("This is nutcracker-%s" CRLF, NC_VERSION_STRING);if (show_help) {nc_show_usage(); //这个函数就是打印twemproxy的所有参数介绍}if (describe_stats) {stats_describe();}exit(0);}if (test_conf) {if (!nc_test_conf(&nci)) {exit(1);}exit(0);}status = nc_pre_run(&nci);if (status != NC_OK) {nc_post_run(&nci);exit(1);}nc_run(&nci);nc_post_run(&nci);exit(1);}

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

初始化option,设置默认值

从argv中获取option,若argv有错误则调用nc_show_usage()打印使用帮助

根据argv,判断是否是:show_version、show_help、describe_stats或者test_conf,是则执行相应逻辑后退出

依次调用nc_pre_run()、nc_run()和nc_post_run()

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

下面是对main函数进一步介绍:

二、Twemproxy启动启动流程分析

对于一个由C/C++编写的应用程序而言,程序的启动点一般都是main函数,所以对一个程序进行分析的话,也一般都是有main函数作为入口,我们这里也不例外,以main函数作为入口。

找到文件nc.c定位到main,我们可以看到定义了一个变量,

struct instance nci;

下边我们看下这个instance的定义:

struct instance {struct context *ctx; /* active context */int log_level; /* log level */char *log_filename;/* log filename */char *conf_filename; /* configuration filename */uint16_t stats_port; /* stats monitoring port */int stats_interval; /* stats aggregation interval */char *stats_addr; /* stats monitoring addr */char hostname[NC_MAXHOSTNAMELEN]; /* hostname */size_tmbuf_chunk_size; /* mbuf chunk size */pid_t pid;/* process id */char *pid_filename;/* pid filename */unsigned pidfile:1; /* pid file created? */};

这个instance就相当于是一个twemproxy实例,后边整个程序的初始化很多都会用到。接下来就调用了nc_set_default_options()和nc_get_options()两个函数,其中nc_get_options这个函数是读取命令行参数。其中比较重要的几个参数分别有:

a) test_conf : 用于设置在启动twemproxy之前是否要对配置文件做检查,以确保配置文件格式的正确。

然后就会调用nc_pre_run,启动之前做一些预处理,包括:初始化日志级别以及日志文件;设置是否后台运行;对信号做初始化处理;是否创建pid文件。

接下来调用nc_run开始启动proxy;这个函数完成的工作就是调用core_start创建context,然后进入死循环调用core_loop开始整个事件循环的处理,接受请求并处理。当然,core_start以及core_loop这两个函数里边还包含了大量的处理工作,包括,配置文件解析以及读取,相关组件(server_pool,conf,context)的初始化等等,这些后边详细讲述。

下面介绍一下nc_pre_run、nc_run的逻辑:

nc_pre_run()的函数逻辑是:

初始化日志启动守护进程初始化信号处理函数创建pidfile输出启动信息如果nc_pre_run()运行失败,main()函数的逻辑中会调用nc_post_run()回收资源

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

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

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

nc_run()函数主要逻辑是:

调用core_start(),初始化上下文ctx

进入死循环,调用core_loop()进入事件循环

检查退出条件status != NC_OK,退出循环

调用core_stop()结束

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

总体来说,启动流程就是这些步骤,如下图:

如果觉得《twemproxy源码解析1 源码文件总体简介》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。