웹 서버의 세부 사항을 이해하려고합니다. Apache와 같이 서버가 새로운 요청을 지속적으로 폴링하는지 또는 일종의 인터럽트 시스템으로 작동하는지 궁금합니다. 인터럽트 인 경우 인터럽트를 발생시키는 원인은 네트워크 카드 드라이버입니까?
웹 서버의 세부 사항을 이해하려고합니다. Apache와 같이 서버가 새로운 요청을 지속적으로 폴링하는지 또는 일종의 인터럽트 시스템으로 작동하는지 궁금합니다. 인터럽트 인 경우 인터럽트를 발생시키는 원인은 네트워크 카드 드라이버입니까?
답변:
짧은 대답은 일종의 인터럽트 시스템입니다. 기본적으로 이들은 차단 I / O를 사용합니다. 즉, 새 데이터를 기다리는 동안 절전 (차단)됩니다.
서버가 청취 소켓을 만든 다음 새 연결을 기다리는 동안 차단합니다. 이 시간 동안 커널은 프로세스를 인터럽트 가능한 휴면 상태로 만들고 다른 프로세스를 실행합니다. 프로세스 폴링을 지속적으로 수행하면 CPU가 낭비됩니다. 커널은 작업이 완료 될 때까지 프로세스를 차단하여 시스템 리소스를보다 효율적으로 사용할 수 있습니다.
네트워크에 새 데이터가 도착하면 네트워크 카드가 인터럽트를 발행합니다.
네트워크 카드에서 인터럽트가 발생하면 커널은 네트워크 카드 드라이버를 통해 네트워크 카드에서 새 데이터를 읽고 메모리에 저장합니다. (이 작업은 빠르게 수행해야하며 일반적으로 인터럽트 처리기 내부에서 처리됩니다.)
커널은 새로 도착한 데이터를 처리하여 소켓과 연결합니다. 해당 소켓에서 블로킹되는 프로세스는 실행 가능으로 표시되어 이제 실행할 수 있음을 의미합니다. 반드시 즉시 실행할 필요는 없습니다 (커널은 다른 프로세스를 계속 실행하기로 결정할 수 있습니다).
여가 시간에 커널은 차단 된 웹 서버 프로세스를 깨 웁니다. 이제는 실행할 수 있습니다.
시간이 지나지 않은 것처럼 웹 서버 프로세스가 계속 실행됩니다. 차단 시스템 호출이 리턴되고 새 데이터를 처리합니다. 그런 다음 ... 1 단계로 이동하십시오.
accept
합니다. 그들은 독립적으로, 비동기 적으로 실행되는 작업입니다 (행운스럽게도 아니면 완전히 빨려 요!). 연결이 들어 오면 연결을 accept
끌어 오는 대기열에 배치됩니다 . 없는 경우에만 차단됩니다.
"더 낮은"세부 사항이 많이 있습니다.
먼저, 커널에 프로세스 목록이 있고 주어진 시간에 이러한 프로세스 중 일부가 실행 중이고 일부는 실행 중이 아님을 고려하십시오. 커널은 각각의 실행중인 프로세스가 CPU 시간 조각을 허용 한 다음 중단하고 다음 프로세스로 이동합니다. 실행 가능한 프로세스가없는 경우 커널은 하드웨어 인터럽트가있을 때까지 CPU를 일시 중단시키는 HLT 와 같은 명령 을 CPU에 발행합니다 .
서버 어딘가에 "할 일을 줘" 라는 시스템 호출 이 있습니다. 이를 수행 할 수있는 방법에는 두 가지 범주가 있습니다. 아파치의 경우, accept
아파치가 포트 80에서 수신 대기중인 아파치가 이전에 연 소켓을 호출 합니다. 커널은 연결 시도 큐를 유지하고 TCP SYN 이 수신 될 때마다 해당 큐에 추가합니다 . 커널이 TCP SYN이 수신되었음을 알 수있는 방법은 장치 드라이버에 따라 다릅니다. 많은 NIC의 경우 네트워크 데이터가 수신 될 때 하드웨어 인터럽트가있을 수 있습니다.
accept
커널에게 다음 연결 시작으로 돌아 오도록 요청합니다. 대기열이 비어 있지 않으면 accept
즉시 반환됩니다. 큐가 비어 있으면 프로세스 (Apache)가 실행중인 프로세스 목록에서 제거됩니다. 연결이 나중에 시작되면 프로세스가 재개됩니다. 이것을 "블로킹"이라고합니다. 호출하는 프로세스 accept()
는 결과가 나올 때까지 반환되지 않는 함수처럼 보입니다. 이 시간 동안 프로세스는 다른 작업을 수행 할 수 없습니다.
일단 accept
돌아 가면 Apache는 누군가 연결을 시도하고 있음을 알고 있습니다. 그런 다음 포크 를 호출 하여 Apache 프로세스를 두 개의 동일한 프로세스로 분할합니다. 이러한 프로세스 중 하나는 계속해서 HTTP 요청을 처리하고 다른 프로세스 accept
는 다음 연결을 얻기 위해 다시 호출 합니다. 따라서 항상 accept
하위 프로세스를 호출 하고 스폰하는 것 외에는 아무것도하지 않는 마스터 프로세스가 있으며 각 요청마다 하나의 하위 프로세스가 있습니다.
이것은 단순화입니다. 프로세스 대신 스레드를 사용하여이를 fork
수행 할 수 있으며, 요청을 수신 할 때 작업자 프로세스 를 미리 준비하여 시작 오버 헤드를 줄일 수도 있습니다. Apache가 구성된 방식에 따라 다음 중 하나를 수행 할 수 있습니다.
즉, 작업을 수행하는 방법의 첫 번째 광범위한 범주이고, 그것은이라고 IO를 차단 시스템처럼 호출하기 때문에 accept
하고 read
그리고 write
그들이 돌아 뭔가를 때까지 프로세스를 일시 중단합니다 소켓에서 작동한다.
이를 수행하는 다른 광범위한 방법은 비 차단 또는 이벤트 기반 또는 비동기 IO라고 합니다. 이것은 select
또는 과 같은 시스템 호출로 구현됩니다 epoll
. 이것들은 모두 똑같은 일을합니다. 소켓 (또는 일반적으로 파일 디스크립터)의 목록과 그것들과 함께하고 싶은 일, 커널 블록은 그 중 하나를 수행 할 준비가 될 때까지 제공합니다.
이 모델을 사용하면 커널에을 사용하여 epoll
"포트 80에 새로운 연결이 있거나 내가 연 9471 개의 다른 연결에서 읽을 새 데이터가있을 때 알려주십시오" 라고 말할 수 있습니다 . epoll
그 중 하나가 준비 될 때까지 차단하면됩니다. 그런 다음 반복하십시오. 시스템 호출 같은 accept
과 read
및 write
블록, 부분적으로 당신이 그들을 호출 할 때마다 때문에, 결코 epoll
그냥 차단 할 이유가 없을 것, 그래서 그들은 준비가되어 있다는 것을, 당신은 소켓 또는 지정한 파일을 열 때 당신이 그들을 원하는 것이 있기 때문에 당신을 말해주지 비 차단 모드에서는 EWOULDBLOCK
차단 대신 통화가 실패 합니다.
이 모델의 장점은 하나의 프로세스 만 필요하다는 것입니다. 즉, 각 요청에 대해 스택 및 커널 구조를 할당 할 필요가 없습니다. Nginx 와 HAProxy 는이 모델을 사용하므로 비슷한 하드웨어에서 Apache보다 더 많은 연결을 처리 할 수있는 큰 이유입니다.