您的位置:首页 > 理论基础 > 计算机网络

nginx启动配置加载性能分析(一)-作为http服务器

2014-12-11 09:44 621 查看

转载:http://my.oschina.net/chenzhuo/blog/184892


 nginx启动配置加载性能分析(一)-作为http服务器

发表于12个月前(2013-12-16 16:59)   阅读(2696) | 评论(13
158人收藏此文章,我要收藏

赞25

开源中国 Team 团队协作平台正式开放 —— http://team.oschina.net
本文测试了在配置文件规模较大时, nginx作为http服务器的启动速度, 并分析耗时原因。

结论:

1. nginx初始化中影响性能点在于listen IP:PORT, 其中port的汇聚会造成初始化速度变得很慢

2. 对于server_name的初始化相当快, 对初始化性能无影响

一、测试内容

脚本创建3类配置文件, 规则如下

1. 共创建2万条server{}配置

2. server_name基本定长, PerformanceTestxxx

3. 第1类是listen的IP完全一致,port全不同, 配置文件实例:

http{

  server{

    listen 192.168.0.1:8080;

    server_name PerformanceTest8080;

  } 

  …

  server{

    listen 192.168.0.1:8081;

    server_name PerformanceTest8081; 

    ….

  }

}

3. 第2类是listen的Port完全一致,IP全不同, 配置文件实例:

http{

  server{

    listen 192.168.0.1:80;

    server_name PerformanceTest1;

  } 

  …

  server{

    listen 192.168.0.2:80;

    server_name PerformanceTest2; 

    ….

  }

}

4. 第3类是listen的IP:PORT完全一致, server_name全不同, 配置文件实例:

http{

  server{

    listen 192.168.0.1:80;

    server_name PerformanceTest001;

  } 

  …

  server{

    listen 192.168.0.1:80;

    server_name PerformanceTest002; 

    ….

  }

}

二、 测试数据
对于3类配置, 再加入3组变量:

1. 不配置server_name

2. server_name全配置一样

3. server_name全配置不一样

看server_name对于初始化速度的影响

9种组合的性能如下:

 文件大小文件行数nginx启动时间reload时间
listen相同port

ip全不一样

无server_name
905K60015real    0m23.547s

user    0m8.454s

sys     0m15.075s

real    0m9.503s

user    0m9.339s

sys     0m0.158s

listen相同port

ip全不一样,

server_name全一样
1.7M80015real    0m23.130s

user    0m8.487s

sys     0m14.626s

real    0m9.033s

user    0m8.856s

sys     0m0.170s

listen相同port

ip全不一样,

server_name全不一样
1.8M80015real    0m24.942s

user    0m8.722s

sys     0m16.199s

real    0m8.860s

user    0m8.697s

sys     0m0.157s

listen不同的port

ip全一样

无server_name
880K60015real    0m7.210s

user    0m1.005s

sys     0m6.197s

real    0m1.203s

user    0m1.033s

sys     0m0.169s

listen不同的port

ip全一样

server_name全一样
1.7M80015real    0m7.145s

user    0m1.017s

sys     0m6.121s

real    0m1.238s

user    0m1.043s

sys     0m0.194s

listen不同的port

ip全一样

server_name全不一样
1.8M80015real    0m8.166s

user    0m1.013s

sys     0m7.144s

real    0m1.229s

user    0m1.049s

sys     0m0.179s

listen相同port, ip, server_name全不一样1.8M80015real    0m0.841suser    0m0.693s

sys     0m0.147s

real    0m0.846s

user    0m0.697s

sys     0m0.148s

nginx 启动时间:    time ./nginx -c /root/nginx.conf.sameport.noloc

nginx reload时间: time ./nginx -c /root/nginx.conf.sameport.noloc –s reload
从测试数据可以看出, 对nginx启动速度影响的因素为server{}中listen的port, server_name指令基本无影响

三、 原因分析
[b]3.1 http{}初始化流程简单介绍

[/b]




解析配置文件是递归地调用ngx_conf_parse函数完成的, http{}配置块的解析流程:

1. 解析到http指令, 执行ngx_http_block函数, 创建http module的配置上下文后, 继续ngx_conf_parse解析http{}内部的内容;

2. 解析到server指令, 执行ngx_http_core_server函数, 创建该server{}的配置上下文后, 继续ngx_conf_parse解析server{}内部的内容; 

3. 解析到listen指令, 添加到cscf以及cmcf配置中, 如下图
 

1. cmcf->servers数组保存了所有监听的server数据





2. cmcf->ports数组保存了所有port汇聚的ip的数据. listen同一个ip:port, server_name不同的srv_conf会挂在ngx_http_conf_addr_t的servers数组下。



 

一个配置好的样子可能是这样:





3.2 耗时位置定位

代码中加变量记录函数耗时总时间, 得到启动时耗时在2个步骤:

1) 解析配置文件, 对应ngx_conf_parse函数

2) 初始化socket, 对应ngx_open_listening_sockets函数

函数耗时
Port全一致
IP全一致
IP:PORT全一致
ngx_conf_parse
8.8s
1.2s
0.8s
ngx_open_listening_sockets
16.6s
6.2s
0s
 

3.3 ngx_conf_parse耗时分析

主要是ngx_http_block函数的耗时, 分为以下2个部分

统计项
Port全一致
IP全一致
IP:PORT全一致
ngx_conf_parse
8.3s
0.6s
0.3s
ngx_conf_parse

完成后续工作
0.5s
0.5s
0.5s
统计项
Port全一致
IP全一致
ngx_http_add_addresses调用次数
20000
20000
ngx_http_add_address调用次数
20000
20000
ngx_http_add_server调用次数
20000
20000
ngx_http_add_addresses总耗时
7121ms
0ms
ngx_http_add_address总耗时
18ms
21ms
ngx_http_add_server总耗时
10ms
5ms
很明显, ngx_http_add_addresses函数的性能消耗在对相同port已存在ip的查找上面, 这里用的是线性的遍历查找,

且需要进行字符串比较ngx_memcmp被执行了2w*2w共4亿次

for (i = 0; i < port->addrs.nelts; i++) {
// 遍历查找, 如果配置文件中,相同port的IP过多,字符串比较带来较大性能问题, 2w个listen,这一块耗时需要8s左右
if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) {
continue;
}

/* the address is already in the address list */
// 找到对应的ip, 添加cscf到IP
if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
return NGX_ERROR;
}


3.4 ngx_open_listening_sockets耗时分析

函数中初始化所有listening的socket

/* for each listening socket */
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
…
…
if (listen(s, ls[i].backlog) == -1) {
}


统计项
Port全一致
IP全一致
IP:PORT全一致
cycle->listening.nelts
20000
20000
1
bind总耗时
4.2s
0.02s
0
listen总耗时
13.9s
6.2s
0
对于同1个IP, 新建不同port的socket相比新建多个不同IP的socket更省时间.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: