Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3506315
  • 博文数量: 1450
  • 博客积分: 11163
  • 博客等级: 上将
  • 技术积分: 11101
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-25 14:40
文章分类

全部博文(1450)

文章存档

2017年(5)

2014年(2)

2013年(3)

2012年(35)

2011年(39)

2010年(88)

2009年(395)

2008年(382)

2007年(241)

2006年(246)

2005年(14)

分类: LINUX

2011-12-08 14:43:01

转自:

Nginx允许设置worker进程的CPU亲和性,这样有利于充分利用服务器资源,减少进程在CPU之间移动的可能性。

在ChinaUnix上看到一个非常好的例子程序——,该示例的源代码如下:

? C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include
#include
#include
#include
#include
 
#define __USE_GNU
#include
#include
#include
 
int main(int argc, char* argv[])
{
//获得CPU的数量,本服务器有8个CPU
int num = sysconf(_SC_NPROCESSORS_CONF);
int created_thread = 0;
int myid;
int i;
int j = 0;
 
cpu_set_t mask;
cpu_set_t get;
 
if (argc != 2)
{
printf("usage : ./cpu num\n");
exit(1);
}
 
myid = atoi(argv[1]);
 
printf("system has %i processor(s). \n", num);
 
CPU_ZERO(&mask);
CPU_SET(myid, &mask);
 
if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
{
printf("warning: could not set CPU affinity, continuing...\n");
}
 
while (1)
{
CPU_ZERO(&get);
if (sched_getaffinity(0, sizeof(get), &get) == -1)
{
printf("warning: cound not get cpu affinity, continuing...\n");
}
for (i = 0; i < num; i++)
{
if (CPU_ISSET(i, &get))
{
printf("this process %d is running processor : %d\n",getpid(), i);
}
}
}
return 0;
}

运行程序如下:

使用top看各CPU的使用率(运行top之后,按1就会显示CPU使用率列表),结果如下:

上面的结果清晰地显示出第0个和第1个CPU较别的CPU更为繁忙。

nginx.c中有两个函数分别为ngx_set_cpu_affinity和ngx_get_cpu_affinity,ngx_set_cpu_affinity根据nginx.conf的配置来设置每个进程的亲和性掩码。典型的设置如下:

根据上面这个配置,Nginx master进程将开启四个worker进程,它们分别运行在第1,2,3,4个CPU上。阅读ngx_get_cpu_affinity可以发现其设置 mask同最上面那个示例程序并不一样,它没有什么CPU_SET这些宏,而是自己来做。

nginx_precess_cycle.c的ngx_start_worker_processes函数负责创建worker process。在spawn进程之前,它会获取该进程的CPU亲和性掩码,并将其赋给cpu_affinity这个全局变量。

? C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static void
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
ngx_int_t i;
ngx_channel_t ch;
 
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
 
ch.command = NGX_CMD_OPEN_CHANNEL;
 
for (i = 0; i < n; i++) {
 
cpu_affinity = ngx_get_cpu_affinity(i);
 
ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
"worker process", type);
 
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
 
ngx_pass_open_channel(cycle, &ch);
}
}

worker进程的回调函数是ngx_worker_process_cycle,该函数会先调用”ngx_worker_process_init(cycle, 1);”初始化本进程,在ngx_worker_process_init中有这样一段代码:

? C
1
2
3
4
5
6
7
8
9
10
11
12
13
#if (NGX_HAVE_SCHED_SETAFFINITY)
 
if (cpu_affinity) {
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"sched_setaffinity(0x%08Xl)", cpu_affinity);
 
//设置cpu亲和性
if (sched_setaffinity(0, 32, (cpu_set_t *) &cpu_affinity) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"sched_setaffinity(0x%08Xl) failed", cpu_affinity);
}
}
#endif

我使用”./configure –with-debug”打开了Nginx的调试选项,启动Nginx之后,可以看到有四个进程启动,但是发现error.log四个这样的错误:

在网上一查,发现很多人都反应这个问题,据说是不支持RHEL 4.0,支持RHEL 5.0。晕死,服务器安装的都是RHEL 4.0,所以就没有可测试的环境了。如果能进行测试的话,就可以分别对设置了亲和性和没有设置亲和性的情况,使用ab进行压力测试,看看效率有没有差别。

阅读(1265) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~