Nginx 놀 라 움 해결

7371 단어 운영 체제
놀 라 운 현상: 모든 작업 프로 세 스 가 socket 을 기다 리 고 있 습 니 다. socket 클 라 이언 트 가 연결 되 었 을 때 모든 작업 스 레 드 가 깨 어 났 지만 최종 적 으로 하나의 작업 스 레 드 만 이 연결 을 처리 하고 다른 프로 세 스 는 수면 상태 에 들 어가 야 합 니 다.
Nginx 는 socket 의 프로 세 스 수량 과 ngx 선점 을 제어 합 니 다.accept_mutex 잠 금 으로 놀 라 움 을 해결 합 니 다.오직 하나의 ngxaccept_mutex 자물쇠, 누가 자 물 쇠 를 가 져 왔 는 지, 누가 이 socket 의 요청 을 처리 합 니까?
현재 프로 세 스 의 연결 수 > 최대 연결 수 * 7 / 8 이면 이 프로 세 스 는 이번 라운드 경쟁 에 참여 하지 않 습 니 다.
//nginx   worker     ngx_process_events_and_timers     。     ngx_process_events_and_timers()       。
void ngx_process_events_and_timers(ngx_cycle_t *cycle)  
{  
    //ngx_use_accept_mutex         accept         。 nginx worker   >1         accept_mutex ,      1         
    if (ngx_use_accept_mutex) 
    {
    //ngx_accept_disabled       ,          ,nginx.conf      nginx worker            ,       7/8 ,ngx_accept_disabled  ,   nginx worker      ,         ,             
        if (ngx_accept_disabled > 0) 
        {      
            ngx_accept_disabled--;  
        } 
        else 
        {  
            //       ,        ngx_accept_mutex_held    1。   ,   socket       epoll  ,       , socket   epoll   。  
            //  trylock     ,        ,       ,                。
            if(pthread_mutex_trylock(&ngx_accept_mutex))
            {
                ngx_accept_mutex_held = 1;
            }
            else
            {
                //  time  ,500ms      ,        worker  ,        ,                 fd   。
                timer = 500;
                ngx_accept_mutex_held = 0;
            }

             //     , flag NGX_POST_EVENTS,    ngx_process_events   ,          ,  accept     ngx_posted_accept_events   ,epollin|epollout     ngx_posted_events     
            if (ngx_accept_mutex_held) 
            {   
                flags |= NGX_POST_EVENTS;
            }
        }
        //  epoll_wait      
        int num = epoll_wait(epollfd, events, length, timer);
        for(int i=0; i<num; ++i)
        {
            ......
            //      
            if (revents & EPOLLIN)
            {
                // NGX_POST_EVENTS    ,  accept    ngx_posted_accept_events   ,        ngx_posted_events       
                //       ngx_posted_accept_events
                //        ngx_posted_events
                if (flags & NGX_POST_EVENTS)
                {
                    queue = rev->accept ? 
                        &ngx_posted_accept_events:
                        &ngx_posted_events;

                    ngx_post_event(rev, queue);
                }
                else//  
                {
                    rev->handler(rev);
                }
            }

            //      
            if (revents & EPOLLOUT)
            {
                //  , NGX_POST_EVENTS    ,       ,  ngx_posted_events    
            if (flags & NGX_POST_EVENTS) 
            {
                ngx_post_event(rev, &ngx_posted_events);
            }
            else//  
            {
                rev->handler(rev);
            }
        }
    }

    //           
        ngx_event_process_posted(cycle, &ngx_posted_accept_events);

    //         
    if(ngx_accept_mutex_held)
    {
        pthread_mutex_unlock(&ngx_accept_mutex);
    }

      //               
      ngx_event_process_posted(cycle, &ngx_posted_events);
}

nginx 는 자 물 쇠 를 빼 앗 고 자 물 쇠 를 풀 어 주 는 것 부터 사건 을 처리 하 는 전체 과정 까지 저 는 코드 와 결합 하여 설명 을 했 습 니 다. 여러분 들 이 전체 과정 에 대해 낯 설 지 않 을 것 이 라 고 믿 습 니 다.까지 pthreadmutex_trylock () 에서 프로 세 스 가 어떻게 자 물 쇠 를 선점 하 는 지 는 선점 을 실현 하 는 알고리즘 에 달 려 있다. 여 기 는 처리 과정 만 설명 할 뿐 선점 실현 원리 에 관심 이 없다.관심 있 는 학우 들 은 스스로 관련 자 료 를 검색 할 수 있다.
1. 새 사용자 의 연결 이 벤트 를 처리 하고 새 연결 을 처리 하 는 자 물 쇠 를 풀 어 줍 니 다. 왜 이렇게 디자인 합 니까?자 물 쇠 를 풀 자마자 새로운 연결 이 있 습 니 다. 자 물 쇠 를 얻 은 프로 세 스 가 대기 열 에 sockfd 를 추가 하려 면 원래 자 물 쇠 를 얻 은 프로 세 스 도 대기 열 에서 sockfd 를 삭제 해 야 합 니 다. TCP 의 세 번 악수 연결 은 비 스 레 드 가 안전 합 니 다.오류 가 발생 하지 않도록 sockfd 를 대기 열 에서 삭제 한 후 새로운 프로 세 스 가 자 물 쇠 를 선점 하여 새로운 연결 을 처리 합 니 다.
2. 자 물 쇠 를 가 져 와 임 무 를 퀘 스 트 대기 열 에 두 고 바로 처리 하 는 것 이 아니 라 왜 이렇게 설계 합 니까?모든 프로 세 스 가 새 연결 이 벤트 를 처리 하려 면 자 물 쇠 를 가 져 와 야 합 니 다. 현재 프로 세 스 는 새 연결 이벤트 의 sokect 를 작업 대기 열 에 추가 하고 자 물 쇠 를 즉시 풀 어 다른 프로 세 스 가 빨리 자 물 쇠 를 가 져 와 사용자 의 연결 을 처리 하도록 합 니 다.
잠 금 을 추가 하지 않 으 면 새로운 이벤트 연결 이 있 을 때 모든 프로 세 스 가 깨 어 나 accept 를 실행 합 니 다. 또한 하나의 프로 세 스 만 accept 를 성공 적 으로 되 돌려 주 고 다른 프로 세 스 는 다시 수면 상태 로 들 어 갑 니 다.현재 자물쇠 가 있 습 니 다. accept 가 발생 하기 전에 프로 세 스 들 이 자 물 쇠 를 선점 해 야 합 니 다. 또한 하나의 프로 세 스 만 자 물 쇠 를 빼 앗 고 다른 프로 세 스 도 다시 수면 상태 로 들 어 갑 니 다.즉, accept 자물쇠 가 있 든 없 든 많은 프로 세 스 가 깨 어 나 다시 수면 상태 로 들 어 가 는 과정 이 있 습 니 다. 그 놀 라 운 현상 은 어떻게 설명 합 니까?
사실 자 물 쇠 는 놀 라 움 현상 을 해결 하지 못 하고 놀 라 움 현상 은 해결 할 수 없 으 며 많은 과정 이 동시에 깨 어 나 는 것 은 필연 적 인 과정 이다.Nginx 에 서 는 현재 프로 세 스 의 연결 수 > 최대 연결 수 * 7 / 8 을 검사 하여 현재 프로 세 스 가 새로운 연결 을 처리 할 수 있 는 지 판단 하고 깨 어 난 프로 세 스 의 수 를 줄 이 며 간단 한 부하 균형 을 이 루 었 습 니 다.잠 금 은 모든 프로 세 스 가 accept 함 수 를 호출 하지 않도록 보장 할 수 있 습 니 다. 많은 프로 세 스 가 accept 를 호출 하여 오 류 를 되 돌려 주 었 습 니 다. 잠 금 은 놀 라 운 현상 을 해결 하 는 오 류 를 해결 하 는 것 이지 놀 라 운 현상 을 해결 하 는 것 이 아 닙 니 다!

좋은 웹페이지 즐겨찾기