设为首页 收藏本站
查看: 1855|回复: 0

[经验分享] haproxy初始化函数分析

[复制链接]

尚未签到

发表于 2015-11-20 11:19:20 | 显示全部楼层 |阅读模式
现在继续上一篇博文分析一下haproxy的初始化函数,haproxy的初始化函数为void init(int argc, char **argv),其跟主函数在同一源文件中(haproxy.c)。该函数也很长,我们一段一段来分析:void init(int argc, char **argv)
{
int i;
int arg_mode = 0;/* MODE_DEBUG, ... */
char *tmp;
char *cfg_pidfile = NULL;
int err_code = 0;
struct wordlist *wl;
char *progname;
/*
* Initialize the previously static variables.
*/
totalconn = actconn = maxfd = listeners = stopping = 0;

#ifdef HAPROXY_MEMMAX
global.rlimit_memmax = HAPROXY_MEMMAX;
#endif
tv_update_date(-1,-1);
start_date = now;
/* 初始化信号队列 */
signal_init();
/* 初始化timer树和rqueue树,另外创建task的pool内存管理池 */
init_task();
/* 创建session的内存管理池 */
init_session();
/* warning, we init buffers later */
/* 创建pendconn的内存管理池 */
init_pendconn();
/* http协议相关的初始化 */
init_proto_http();
  

这边主要是相关内存管理的初始化,haproxy是怎么样进行内存管理的呢?我们可以阅读memory.c源文件,其实其内存管理很简单,是通过链表来管理的,总的内存管理的链表头是pools,其结构为struct list,链表的节点就是由相关模块创建的内存管理pool头,该结构如下所示:
  

struct pool_head {
void **free_list;   /* 空闲内存链表,free内存时就把其加入到该链表 */
struct list list;/* list of all known pools */
unsigned int used;/* how many chunks are currently in use */
unsigned int allocated;/* how many chunks have been allocated */
unsigned int limit;/* hard limit on the number of chunks */
unsigned int minavail;/* how many chunks are expected to be used */
unsigned int size;/* chunk size */
unsigned int flags;/* MEM_F_*,该标志主要是用来是否可以同别的pool共享 */
unsigned int users;/* number of pools sharing this zone */
char name[12];/* name of the pool */
};
  每个pool能申请的数据长度的按照16字节对齐的,在创建一个pool后都是连接pools为链表头的链表中,我们要在以"name"的pool池中申请内存是调用pool_alloc2宏,先是在查看free_list是否有空闲节点,有直接从那边取,没有则调用pool_refill_alloc函数申请,该函数会判断该pool申请的内存是否超过了限制,超过则返回NULL,没有则调用malloc申请,malloc申请不到则会释放一些别的pool的free_list节点以获取内存。释放内存是调用pool_free2(pool,
ptr)宏,其实说是释放,只是把该内存加入到free_list链表中。总的来说haproxy内存管理相对简单,通过该内存管理我们可以监测各个pool的使用情况及限制各个pool的申请情况。说了那么多内存管理相关的,现在我们回到初始化函数来,我们继续分析:

……
  

略过支持事件的代码,我们来分析解析程序运行参数的代码

while (argc > 0) {
char *flag;
if (**argv == '-') {
flag = *argv+1;
/* 1 arg */
if (*flag == 'v') {
/* 显示haproxy的version */
display_version();
if (flag[1] == 'v')  /* -vv */
display_build_opts();
exit(0);
}
/*
* de、ds、dp、dk删除相关的事件
*/
#if defined(ENABLE_EPOLL)
else if (*flag == 'd' && flag[1] == 'e')
global.tune.options &= ~GTUNE_USE_EPOLL;
#endif
#if defined(ENABLE_SEPOLL)
else if (*flag == 'd' && flag[1] == 's')
global.tune.options &= ~GTUNE_USE_SEPOLL;
#endif
#if defined(ENABLE_POLL)
else if (*flag == 'd' && flag[1] == 'p')
global.tune.options &= ~GTUNE_USE_POLL;
#endif
#if defined(ENABLE_KQUEUE)
else if (*flag == 'd' && flag[1] == 'k')
global.tune.options &= ~GTUNE_USE_KQUEUE;
#endif
#if defined(CONFIG_HAP_LINUX_SPLICE)
else if (*flag == 'd' && flag[1] == 'S')
global.tune.options &= ~GTUNE_USE_SPLICE;
#endif
else if (*flag == 'V')
arg_mode |= MODE_VERBOSE;
else if (*flag == 'd' && flag[1] == 'b')
arg_mode |= MODE_FOREGROUND;
else if (*flag == 'd')
arg_mode |= MODE_DEBUG;
else if (*flag == 'c')
arg_mode |= MODE_CHECK;
else if (*flag == 'D')
arg_mode |= MODE_DAEMON;
else if (*flag == 'q')
arg_mode |= MODE_QUIET;
else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
/* list of pids to finish ('f') or terminate ('t') */
if (flag[1] == 'f')
oldpids_sig = SIGUSR1; /* finish then exit */
else
oldpids_sig = SIGTERM; /* terminate immediately */
argv++; argc--;
if (argc > 0) {
oldpids = calloc(argc, sizeof(int));
while (argc > 0) {
oldpids[nb_oldpids] = atol(*argv);
if (oldpids[nb_oldpids] <= 0)
usage(progname);
argc--; argv++;
nb_oldpids++;
}
}
}
else { /* >=2 args */
argv++; argc--;
if (argc == 0)
usage(progname);
switch (*flag) {
case 'n' : cfg_maxconn = atol(*argv); break;          /* -n: 最大连接数 */
case 'm' : global.rlimit_memmax = atol(*argv); break; /* -m: 最大内存限制 */
case 'N' : cfg_maxpconn = atol(*argv); break;         /* -N: 每个proxy的最大连接数 */
case 'f' :                                            /* -f: 配置文件 */
wl = (struct wordlist *)calloc(1, sizeof(*wl));
if (!wl) {
Alert(&quot;Cannot load configuration file %s : out of memory.\n&quot;, *argv);
exit(1);
}
wl->s = *argv;
LIST_ADDQ(&cfg_cfgfiles, &wl->list);
break;
case 'p' : cfg_pidfile = *argv; break;
default: usage(progname);
}
}
}
else
usage(progname);
argv++; argc--;
}
global.mode = MODE_STARTING | /* during startup, we want most of the alerts */
(arg_mode & (MODE_DAEMON | MODE_FOREGROUND | MODE_VERBOSE
| MODE_QUIET | MODE_CHECK | MODE_DEBUG));
if (LIST_ISEMPTY(&cfg_cfgfiles))
usage(progname);
/* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
* the string in case of truncation, and at least FreeBSD appears not to do
* it.
*/
memset(hostname, 0, sizeof(hostname));
gethostname(hostname, sizeof(hostname) - 1);
have_appsession = 0;
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
init_default_instance();
/* 解析配置文件 */
list_for_each_entry(wl, &cfg_cfgfiles, list) {
int ret;
ret = readcfgfile(wl->s);
if (ret == -1) {
Alert(&quot;Could not open configuration file %s : %s\n&quot;,
wl->s, strerror(errno));
exit(1);
}
if (ret & (ERR_ABORT|ERR_FATAL))
Alert(&quot;Error(s) found in configuration file : %s\n&quot;, wl->s);
err_code |= ret;
if (err_code & ERR_ABORT)
exit(1);
}
/* 检查配置是否正确 */
err_code |= check_config_validity();
if (err_code & (ERR_ABORT|ERR_FATAL)) {
Alert(&quot;Fatal errors found in configuration.\n&quot;);
exit(1);
}
if (global.mode & MODE_CHECK) {
qfprintf(stdout, &quot;Configuration file is valid\n&quot;);
exit(0);
}
/* now we know the buffer size, we can initialize the buffers */
init_buffer();
if (have_appsession)
appsession_init();
if (start_checks() < 0)
exit(1);
if (cfg_maxconn > 0)
global.maxconn = cfg_maxconn;
if (cfg_pidfile) {
free(global.pidfile);
global.pidfile = strdup(cfg_pidfile);
}
if (global.maxconn == 0)
global.maxconn = DEFAULT_MAXCONN;
if (!global.maxpipes) {
/* maxpipes not specified. Count how many frontends and backends
* may be using splicing, and bound that to maxconn.
*/
struct proxy *cur;
int nbfe = 0, nbbe = 0;
for (cur = proxy; cur; cur = cur->next) {
if (cur->options2 & (PR_O2_SPLIC_ANY)) {
if (cur->cap & PR_CAP_FE)
nbfe += cur->maxconn;
if (cur->cap & PR_CAP_BE)
nbbe += cur->fullconn ? cur->fullconn : global.maxconn;
}
}
global.maxpipes = MAX(nbfe, nbbe);
if (global.maxpipes > global.maxconn)
global.maxpipes = global.maxconn;
global.maxpipes /= 4;
}
.......这主要是haproxy初始化的代码,初始化函数主要是创建内存管理相关的及参数解析或者配置文件解析等等

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-141473-1-1.html 上篇帖子: haproxy The Response line 下篇帖子: HAProxy,智能分流的负载均衡方案
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表