>  기사  >  운영 및 유지보수  >  nginx가 왜 그렇게 빠른가요?

nginx가 왜 그렇게 빠른가요?

王林
王林앞으로
2020-10-20 17:25:172849검색

nginx가 왜 그렇게 빠른가요?

우선 Nginx가 다중 프로세스(단일 스레드) 및 다중 채널 IO 재사용 모델을 사용한다는 것을 알아야 합니다. I/O 다중화 기술을 사용하는 Nginx는 "동시 이벤트 중심" 서버가 됩니다.

(추천 튜토리얼: nginx 튜토리얼)

nginx가 왜 그렇게 빠른가요?

다중 프로세스 작업 모드

Nginx가 시작된 후에는 마스터 프로세스와 여러 개의 독립 작업자 프로세스가 있습니다. 마스터는 외부 세계로부터 신호를 수신하고 각 작업자 프로세스에 신호를 보냅니다. 각 프로세스는 연결을 처리할 수 있습니다. 마스터 프로세스는 작업자 프로세스의 실행 상태를 모니터링할 수 있습니다. 작업자 프로세스가 종료되면(비정상적인 상황) 새 작업자 프로세스가 자동으로 시작됩니다.

보통 머신 CPU 코어 수로 설정되는 작업자 프로세스 수에 주의하세요. 작업자가 많아지면 프로세스가 CPU를 놓고 서로 경쟁하게 되어 불필요한 컨텍스트 전환이 발생하기 때문입니다.

다중 프로세스 모드를 사용하면 동시성 비율이 향상될 뿐만 아니라 프로세스가 서로 독립적이 됩니다. 한 작업자 프로세스가 중단되더라도 다른 작업자 프로세스에는 영향을 미치지 않습니다.

Thundering Herd 현상

주 프로세스(마스터 프로세스)는 먼저 소켓()을 통해 모니터링하기 위한 sock 파일 설명자를 생성한 다음 포크하여 하위 프로세스(작업자 프로세스)를 생성합니다. 상위 프로세스(소켓 파일 디스크립터), 하위 프로세스는 accept() 이후에 연결된 디스크립터를 생성한 다음 연결된 디스크립터를 통해 클라이언트와 통신합니다.

따라서 모든 하위 프로세스는 상위 프로세스의 sockfd를 상속하므로 연결이 들어오면 모든 하위 프로세스가 알림을 받고 연결을 설정하기 위해 "경주"합니다. 이를 "천둥 떼 현상"이라고 합니다. 많은 수의 프로세스가 활성화되고 일시 중지되며 단 하나의 프로세스만 연결을 수락()할 수 있으며 이는 물론 시스템 리소스를 소비합니다.

Nginx의 천둥소리 현상 처리

Nginx는 accept에 추가된 공유 잠금인 accept_mutex를 제공합니다. 즉, 각 작업자 프로세스는 accept를 실행하기 전에 잠금을 획득해야 합니다. 잠금을 획득할 수 없으면 accept() 실행을 포기합니다. 이 잠금을 사용하면 동시에 하나의 프로세스만 accpet()을 수행하므로 Thundering Herd 문제는 발생하지 않습니다. accept_mutex는 명시적으로 끌 수 있는 제어 가능한 옵션입니다. 기본적으로 켜져 있습니다.

Nginx 프로세스에 대한 자세한 설명

Nginx가 시작되면 마스터 프로세스와 여러 작업자 프로세스가 있습니다.

마스터 프로세스

는 주로 다음을 포함하여 작업자 프로세스를 관리하는 데 사용됩니다.

외부 세계로부터 신호를 수신하고 각 작업자 프로세스에 신호를 보내 작업자 프로세스가 종료될 때(아래). 비정상적인 상황), 자동으로 새 작업자 프로세스를 다시 시작합니다

마스터 프로세스는 전체 프로세스 그룹과 사용자 간의 대화형 인터페이스 역할을 하며 프로세스를 모니터링하기도 합니다. 네트워크 이벤트를 처리할 필요가 없으며 비즈니스 실행을 담당하지 않으며 서비스 재시작, 원활한 업그레이드, 로그 파일 교체, 구성 파일 실시간 적용 등의 기능을 구현하기 위한 작업자 프로세스만 관리합니다.

nginx를 제어하려면 kill을 통해 마스터 프로세스에 신호만 보내면 됩니다. 예를 들어, kill -HUP pid는 nginx에게 nginx를 정상적으로 다시 시작하도록 지시합니다. 일반적으로 이 신호를 사용하여 nginx를 다시 시작하거나 구성을 다시 로드합니다. 정상적으로 다시 시작되므로 서비스가 중단되지 않습니다. HUP 신호를 받은 후 마스터 프로세스는 무엇을 합니까?

먼저 신호를 받은 후 마스터 프로세스는 구성 파일을 다시 로드한 다음 새 작업자 프로세스를 시작하고 모든 이전 작업자 프로세스에 신호를 보내 새 작업자가 시작된 후 시작됩니다. 새 요청 수신,

마스터로부터 신호를 받은 후 이전 작업자는 더 이상 새 요청을 받지 않으며 현재 프로세스에서 처리되지 않은 모든 요청이 처리된 후에 종료됩니다.

물론 마스터 프로세스에 직접 신호를 보내는 것은 nginx 버전 0.8 이후 관리를 용이하게 하기 위해 일련의 명령줄 매개변수를 도입한 오래된 작업 방법입니다. 예를 들어 ./nginx -s reload는 nginx를 다시 시작하는 것이고 ./nginx -s stop은 nginx 실행을 중지하는 것입니다. 어떻게? 다시 로드를 예로 들어보겠습니다. 명령을 실행할 때 새 nginx 프로세스가 시작되고 새 nginx 프로세스가 reload 매개변수를 구문 분석한 후 우리의 목적은 구성 파일을 다시 로드하도록 nginx를 제어하는 ​​것임을 알 수 있습니다. 마스터 프로세스에 신호를 보내고 다음 작업은 신호를 마스터 프로세스에 직접 보낸 것과 동일합니다.

작업자 프로세스

기본 네트워크 이벤트는 작업자 프로세스에서 처리됩니다. 여러 작업자 프로세스는 P2P 방식으로 클라이언트의 요청을 놓고 동등하게 경쟁하며 각 프로세스는 서로 독립적입니다. 요청은 하나의 작업자 프로세스에서만 처리할 수 있으며 작업자 프로세스는 다른 프로세스의 요청을 처리할 수 없습니다. 작업자 프로세스 수는 설정할 수 있으며 일반적으로 머신의 CPU 코어 수와 일치하도록 설정합니다. 그 이유는 nginx의 프로세스 모델 및 이벤트 처리 모델과 불가분의 관계입니다.

작업자 프로세스는 동일하며, 각 프로세스는 동일한 요청 처리 기회를 갖습니다. 포트 80에서 http 서비스를 제공하고 연결 요청이 오면 각 프로세스가 연결을 처리할 수 있습니다. 먼저 마스터 프로세스에서 각 작업자 프로세스가 분기됩니다. 마스터 프로세스에서는 수신해야 하는 소켓(listenfd)이 먼저 설정된 다음 여러 작업자 프로세스가 분기됩니다. 새 연결이 도착하면 모든 작업자 프로세스의 Listenfd를 읽을 수 있게 됩니다. 하나의 프로세스만 연결을 처리하도록 하기 위해 모든 작업자 프로세스는 Listenfd 읽기 이벤트를 등록하기 전에 accept_mutex를 가져옵니다. 뮤텍스를 가져오는 프로세스는 Listenfd 읽기 이벤트를 등록합니다. 연결을 수락하려면 읽기 이벤트를 수락하세요. 작업자 프로세스가 연결을 수락하면 요청 읽기, 요청 구문 분석, 요청 처리, 데이터 생성을 시작한 다음 이를 클라이언트에 반환하고 마지막으로 연결을 끊습니다. 이것이 완전한 요청의 모습입니다. 요청이 작업자 프로세스에 의해 완전히 처리되고 하나의 작업자 프로세스에서만 처리되는 것을 볼 수 있습니다.

작업자 프로세스 워크플로

작업자 프로세스가 연결을 수락()하면 요청 읽기, 요청 구문 분석, 요청 처리, 데이터 생성, 클라이언트로 반환을 시작하고 마지막으로 연결 A를 끊습니다. 요청을 완료하세요. 요청은 전적으로 작업자 프로세스에 의해 처리되며 하나의 작업자 프로세스에서만 처리될 수 있습니다.

이렇게 하면 이점:

잠금으로 인한 오버헤드가 절약됩니다. 각 작업자 프로세스는 독립적인 프로세스이며 리소스를 공유하지 않으며 잠금이 필요하지 않습니다. 동시에 프로그래밍 및 문제 해결 시 훨씬 더 편리해집니다. 독립적인 프로세스로 위험을 줄일 수 있습니다. 독립적인 프로세스를 사용하면 한 프로세스가 종료된 후에도 다른 프로세스는 계속 작동하며 마스터 프로세스는 새 작업자 프로세스를 신속하게 다시 시작합니다. 물론 작업자 프로세스가 예기치 않게 종료될 수도 있습니다.

다중 프로세스 모델에서 각 프로세스/스레드는 IO의 한 채널만 처리할 수 있습니다. 그러면 Nginx는 IO의 여러 채널을 어떻게 처리합니까?

IO 멀티플렉싱을 사용하지 않는 경우 accept() 실행과 같이 프로세스에서 동시에 하나의 요청만 처리할 수 있습니다. 연결이 없으면 계속하기 전에 연결될 때까지 프로그램이 여기에서 차단됩니다. .아래로 실행합니다.

그리고 멀티플렉싱을 사용하면 이벤트가 발생할 때만 프로그램에 제어권을 반환할 수 있으며, 다른 경우에는 커널이 프로세스를 일시 중지하고 대기 상태에 있습니다.

핵심: Nginx에서 사용하는 IO 다중화 모델 epoll

예: Nginx는 "새 클라이언트의 연결 요청이 도착하면 다시 알려주세요."라는 이벤트를 등록합니다. 요청을 수신하기 위해 서버 Accept()가 실행됩니다. 또 다른 예로, 요청을 업스트림 서버(예: PHP-FPM)로 전달하고 요청이 반환되기를 기다리는 경우 처리 작업자는 요청을 보낸 후 이벤트를 등록하지 않습니다. data, 알려주시면 다시 읽어보겠습니다." 프로세스는 유휴 상태가 되어 이벤트가 발생할 때까지 기다립니다.

위 내용은 nginx가 왜 그렇게 빠른가요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제