nginx 子进程调度

来源:互联网 发布:会计毕业论文知乎 编辑:程序博客网 时间:2024/06/02 04:24

在linux 下,nginx默认是采用多进程模型的,其中一个是父进程,其他都是子进程,父进程主要做一些全局初始化、调度等工作,而真正的处理时在子进程中完成的,那么当一个请求过来的时候,到底有那个进程去服务呢?

      我看了代码,还是没有找到答案,后来在网上发现了这篇文章<<Nginx0.7.61代码分析(二)--worker子进程之间的负载均衡>>,终于揭开了我心中的疑问。系统根据没有进程已有的链接数来进程调度的。

 

       这里对相关的问题进行总结:

       一  子进程可以继承父进程的socket的,所以如果在父进程中启动了监听的socket后,在子进程中直接进行accept, 这个就是nginx使用的方法。

 

       二 nginx其实不是很好的调度算法,它只是对于负担比较重的进程,不给他们分配任务,所以在任务不是很多的时候,这个算法并不是很好。

 

 

       下面自己写了一个简单的程序,父进程启动监听进程,子进程进程accept,利用共享内存,实现进程之间的通信,使他们轮流执行任务。

 

[cpp] view plaincopy
  1. #include <sys/socket.h>  
  2. #include <sys/epoll.h>  
  3. #include <netinet/in.h>  
  4. #include <arpa/inet.h>  
  5. #include <fcntl.h>  
  6. #include <unistd.h>  
  7. #include <stdio.h>  
  8. #include <pthread.h>  
  9. #include <errno.h>  
  10. #include <unistd.h>  
  11. #include <sys/ipc.h>  
  12. #include <sys/shm.h>  
  13. #include <errno.h>  
  14.   
  15. #define KEY 1234   
  16. #define SIZE 1024   
  17.   
  18. #define PORT 9999   
  19. #define MAXFDS 5000  
  20. #define EVENTSIZE 100  
  21.   
  22. void process();   
  23.   
  24. int fd, cfd,opt=1;  
  25. int shmid;  
  26. char *shmaddr;  
  27. struct shmid_ds buf;  
  28. int num = 0 ;   
  29.   
  30. int main(int argc, char *argv[])  
  31. {  
  32.     shmid = shmget(KEY,SIZE,IPC_CREAT|0600); /* 建立共享内存 */  
  33.     if(shmid == -1){  
  34.         printf("create share memory failed/n");   
  35.     }  
  36.     shmaddr = (char *)shmat(shmid,NULL,0);  
  37.     if(shmaddr == (void *)-1){  
  38.         printf("connect to the share memory failed: %s",strerror(errno));  
  39.         return 0;  
  40.     }  
  41.     strcpy(shmaddr,"1/n");  
  42.       
  43.     struct sockaddr_in sin, cin;  
  44.     socklen_t sin_len = sizeof(struct sockaddr_in);  
  45.   
  46.     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 0)  
  47.     {  
  48.         fprintf(stderr, "socket failed/n");  
  49.         return -1;  
  50.     }  
  51.   
  52.     memset(&sin, 0, sizeof(struct sockaddr_in));  
  53.     sin.sin_family = AF_INET;  
  54.     sin.sin_port = htons((short)(PORT));  
  55.     sin.sin_addr.s_addr = INADDR_ANY;  
  56.     if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) != 0)  
  57.     {  
  58.          fprintf(stderr, "bind failed/n");  
  59.          return -1;  
  60.     }  
  61.     if (listen(fd, 32) != 0)  
  62.     {  
  63.         fprintf(stderr, "listen failed/n");  
  64.         return -1;  
  65.     }  
  66.     int i ;    
  67.     for(i = 0; i < 2; i++)  
  68.     {  
  69.       int pid = fork();  
  70.       if(pid == 0)  
  71.       {  
  72.           process();        
  73.       }  
  74.     }    
  75.     while(1) ;   
  76.      
  77.     return 0;  
  78. }  
  79.   
  80. void process()  
  81. {  
  82.     int pid = getpid();   
  83.     struct sockaddr_in cin;  
  84.     socklen_t sin_len = sizeof(struct sockaddr_in);  
  85.     while(1)  
  86.     {   
  87.         shmaddr = (char *)shmat(shmid,NULL,0);  
  88.         if(shmaddr == (void *)-1){  
  89.         printf("connect the share memory failed: %s",strerror(errno));  
  90.         return ;   
  91.         }  
  92.      
  93.        if(shmaddr[0]=='0')  
  94.            num = 0 ;   
  95.        else num = 1;  
  96.   
  97.        if((pid-num)%2==0)   
  98.        {  
  99.             int fds = accept(fd,(struct sockaddr *)&cin, &sin_len);  
  100.             if(fds>0)  
  101.             {   
  102.                  printf("my pid is %d/n",pid);        
  103.                  fflush(stdout);    
  104.                  if(num == 0)  
  105.                      strcpy(shmaddr,"1/n");  
  106.                  else    
  107.                      strcpy(shmaddr,"0/n");  
  108.             }  
  109.        }  
  110.        shmdt(shmaddr);  
  111.     }  
  112. }  

 

我们启动服务,在客户端输入

 

ab -n 1000 -c 100  http://ip:9999/

 

可以看到在服务器端,两个进程交替处理请求

my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707
my pid is 5708
my pid is 5707

 

原创粉丝点击