> 백엔드 개발 > PHP 튜토리얼 > Nginx 작동 원리, 최적화 및 취약점.

Nginx 작동 원리, 최적화 및 취약점.

WBOY
풀어 주다: 2016-08-08 09:32:37
원래의
950명이 탐색했습니다.


1. Nginx 모듈 및 작동 원리

Nginx는 그 중 커널과 모듈로 구성됩니다. 매우 작고 간결하며 수행되는 작업도 매우 간단합니다. 구성 파일을 검색하여 클라이언트 요청을 위치 블록에 매핑하기만 하면 됩니다(위치는 URL 일치에 사용되는 Nginx 구성의 지시문입니다). , 그리고 이 위치의 구성 각 명령은 해당 작업을 완료하기 위해 다른 모듈을 시작합니다.

Nginx 모듈은 구조적으로 핵심 모듈, 기본 모듈, 타사 모듈로 구분됩니다.

핵심 모듈: HTTP 모듈, EVENT 모듈, MAIL 모듈

기본 모듈: HTTP 액세스 모듈, HTTP FastCGI 모듈, HTTP 프록시 모듈 및 HTTP 재작성 모듈,

타사 모듈: HTTP 업스트림 요청 해시 모듈, 공지 모듈 및 HTTP 액세스 키 모듈.

사용자가 필요에 따라 개발한 모듈은 타사 모듈입니다. Nginx의 기능이 그토록 강력한 것은 바로 수많은 모듈의 지원 덕분입니다.

Nginx 모듈은 기능적으로 다음 세 가지 범주로 나뉩니다.

핸들러(프로세서 모듈). 이러한 유형의 모듈은 요청을 직접 처리하고 콘텐츠 출력, 헤더 정보 수정 등의 작업을 수행합니다. 일반적으로 핸들러 프로세서 모듈은 하나만 있습니다.

필터(필터 모듈). 이 유형의 모듈은 주로 다른 프로세서 모듈의 콘텐츠 출력을 수정하고 최종적으로 Nginx에 의해 출력됩니다.

프록시(프록시 클래스 모듈). 이러한 모듈은 Nginx의 HTTP 업스트림과 같은 모듈입니다. 이러한 모듈은 주로 FastCGI와 같은 일부 백엔드 서비스와 상호 작용하여 서비스 프록시 및 로드 밸런싱과 같은 기능을 구현합니다.

그림 1-1은 Nginx 모듈의 일반적인 HTTP 요청 및 응답 프로세스를 보여줍니다. 그림 1-1은 Nginx 모듈의 일반적인 HTTP 요청 및 응답 프로세스를 보여줍니다.

Nginx 자체는 실제로 HTTP 요청을 받으면 구성 파일을 검색하여 요청을 위치 블록에 매핑하고 이 위치의 구성이 실제로 거의 수행되지 않습니다. 작업을 완료하기 위해 다양한 모듈이 있으므로 모듈은 Nginx의 실제 노동자로 간주될 수 있습니다. 일반적으로 한 위치의 명령에는 처리기 모듈과 여러 필터 모듈이 포함됩니다(물론 여러 위치에서 동일한 모듈을 재사용할 수 있음). 핸들러 모듈은 요청을 처리하고 응답 콘텐츠 생성을 완료하는 역할을 담당하고, 필터 모듈은 응답 콘텐츠를 처리합니다.

Nginx 모듈은 Nginx로 직접 컴파일되므로 정적 컴파일 방식입니다. Nginx를 시작하면 Nginx 모듈이 자동으로 로드됩니다. Apache와 달리 먼저 모듈을 so 파일로 컴파일한 다음 로드 여부를 구성 파일에 지정합니다. 구성 파일을 구문 분석할 때 Nginx의 각 모듈은 특정 요청을 처리할 수 있지만 동일한 처리 요청은 하나의 모듈에서만 완료할 수 있습니다.

작업 모드 측면에서 Nginx는 단일 작업자 프로세스와 다중 작업자 프로세스의 두 가지 모드로 구분됩니다. 단일 작업자 프로세스 모드에는 기본 프로세스 외에 단일 스레드인 작업자 프로세스도 있습니다. 다중 작업자 프로세스 모드에서는 각 작업자 프로세스에 여러 스레드가 포함됩니다. Nginx는 기본적으로 단일 작업자 프로세스 모드를 사용합니다.

2. Nginx+FastCGI 작동 원리

1. >FastCGI는 HTTP 서버와 동적 스크립팅 언어 간의 통신을 위한 확장 가능한 고속 인터페이스입니다. 가장 널리 사용되는 HTTP 서버는 Apache, Nginx, lighttpd 등을 포함한 FastCGI를 지원합니다. 동시에 FastCGI는 PHP를 포함한 많은 스크립팅 언어에서도 지원됩니다.

FastCGI는 CGI를 기반으로 개발 및 개선되었습니다. 전통적인 CGI 인터페이스 방법의 가장 큰 단점은 성능이 좋지 않다는 것입니다. 왜냐하면 HTTP 서버가 동적 프로그램을 만날 때마다 구문 분석을 수행하기 위해 스크립트 파서를 다시 시작해야 하고 결과가 HTTP 서버로 반환되기 때문입니다. 이는 높은 동시 액세스를 처리할 때 거의 사용할 수 없습니다. 또한 기존의 CGI 인터페이스 방식은 보안성이 취약하여 현재는 거의 사용되지 않습니다.

FastCGI 인터페이스 모드는 C/S 구조를 채택하여 HTTP 서버와 스크립트 파싱 서버를 분리하고 스크립트 파싱 서버에서 하나 이상의 스크립트 파싱 데몬을 시작할 수 있습니다. HTTP 서버가 동적 프로그램을 만날 때마다 실행을 위해 FastCGI 프로세스로 직접 전달된 다음 결과가 브라우저로 반환됩니다. 이 방법을 사용하면 HTTP 서버가 정적 요청을 독점적으로 처리하거나 동적 스크립트 서버의 결과를 클라이언트에 반환할 수 있으므로 전체 응용 프로그램 시스템의 성능이 크게 향상됩니다.

2. Nginx+FastCGI 작동 원리

Nginx는 외부 프로그램의 직접 호출이나 구문 분석을 지원하지 않습니다(PHP 포함). 부르다. FastCGI 인터페이스는 Linux의 소켓입니다(이 소켓은 파일 소켓 또는 IP 소켓일 수 있습니다).

래퍼: CGI 프로그램을 호출하려면 FastCGI 래퍼도 필요합니다(래퍼는 다른 프로그램을 시작하는 데 사용되는 프로그램으로 이해될 수 있음). 이 래퍼는 포트나 파일과 같은 고정 소켓에 바인딩됩니다. 소켓. Nginx가 이 소켓에 CGI 요청을 보내면 래퍼는 FastCGI 인터페이스를 통해 요청을 받은 다음 새 스레드를 포크(파생)하여 스크립트를 처리하고 반환 데이터를 읽습니다. 그런 다음 래퍼는 FastCGI 인터페이스와 고정 소켓을 통해 반환된 데이터를 Nginx에 전달합니다. 마지막으로 Nginx는 반환된 데이터(html 페이지 또는 그림)를 클라이언트에 보냅니다. 이는 그림 1-3과 같이 Nginx+FastCGI의 전체 동작 과정이다. 따라서 먼저 이 래퍼가 완료하는 데 필요한 작업인 래퍼가 필요합니다.

fastcgi(라이브러리)의 함수를 호출하여 소켓을 통해 ningx와 통신합니다(소켓 읽기 및 쓰기는 내부적으로 구현되는 함수입니다. fastcgi이며 래퍼에 투명하지 않음)스레드 예약, 포크 및 종료애플리케이션과 통신(php)

spawn- fcgi 및 PHP-FPM FastCGI 인터페이스 메소드는 스크립트 구문 분석 서버에서 하나 이상의 데몬 프로세스를 시작하여 동적 스크립트를 구문 분석합니다. 이러한 프로세스는 FastCGI 프로세스 관리자 또는 FastCGI 엔진입니다. spawn-fcgi 및 PHP-FPM은 PHP를 지원하는 두 가지 FastCGI 프로세스 관리자입니다.

따라서 HTTPServer는 완전히 해방되었으며 더 나은 응답과 동시성을 더 잘 처리할 수 있습니다.

    spawn-fcgi와 PHP-FPM의 유사점과 차이점:
  1. 1)spawn-fcgi는 HTTP 서버 lighttpd의 일부가 되었으며 일반적으로 사용됩니다. lighttpd와 함께 PHP가 지원됩니다. 그러나 ligttpd의 spwan-fcgi는 메모리 누수를 일으키거나 동시 액세스가 많은 동안 FastCGI를 자동으로 다시 시작할 수도 있습니다. 즉, 이때 사용자가 PHP 스크립트 프로세서에 접근하면 흰색 페이지가 나타날 수 있습니다(즉, PHP를 구문 분석할 수 없거나 오류가 발생함).
  2. 2) Nginx는 PHP를 구문 분석하기 위해 타사 FastCGI 프로세서를 사용해야 합니다. 따라서 실제로 nginx는 매우 유연하며 타사에서 제공할 수 있는 것 같습니다. 구문 분석 프로세서는 PHP를 구문 분석하기 위한 연결을 구현합니다(nginx.conf에서 설정하기 쉽습니다). nginx는 spwan-fcgi를 사용할 수도 있습니다(lighthttpd는 함께 설치해야 하지만 nginx의 경우 포트를 피해야 합니다. 일부 오래된 블로그에는 이와 관련된 설치 튜토리얼이 있습니다). 위에서 언급했듯이 이제 nginx+spawn-fcgi 조합의 사용을 점차 줄이고 있습니다.
spawn-fcgi의 결함으로 인해 이제 제3자(현재 PHP 코어에 추가됨) PHP FastCGI 프로세서 PHP-FPM이 있는데, 이는spawn-fcgi와 비교됩니다.

PHP 패치로 개발되었기 때문에 설치 시 PHP 소스코드와 함께 컴파일해야 하는데, 이는 PHP 코어로 컴파일된다는 의미이므로, in 성능면에서는 더 좋습니다.


동시에 높은 동시성을 처리하는 데에는spawn-fcgi보다 낫습니다. 적어도 fastcgi 프로세서를 자동으로 다시 시작하지는 않습니다. 따라서 PHP를 구문 분석하려면 Nginx+PHP/PHP-FPM 조합을 사용하는 것이 좋습니다.

Spawn-FCGI에 비해 PHP-FPM은 CPU 및 메모리 제어 능력이 뛰어나고 전자는 충돌하기 쉽고 crontab으로 모니터링해야 하지만 PHP-FPM은 그렇지 않습니다. .

FastCGI의 가장 큰 장점은 HTTP 서버에서 동적 언어를 분리하는 것입니다. 따라서 Nginx와 PHP/PHP-FPM은 프런트엔드 Nginx 서버에 대한 압력을 공유하고 Nginx가 다음을 수행할 수 있도록 서로 다른 서버에 배포되는 경우가 많습니다. 정적 요청을 독점적으로 처리하고 동적 요청을 전달하는 반면, PHP/PHP-FPM 서버는 PHP 동적 요청을 독점적으로 구문 분석합니다.

4. Nginx+PHP-FPM

PHP-FPM은 PHP용 플러그인으로 존재합니다. PHP 설치 시 - FPM을 사용할 경우에는 이전 버전의 PHP(php5.3.3 이전)에 패치 형태로 PHP에 PHP-FPM을 설치해야 하며, PHP는 PHP-FPM 버전과 일치해야 합니다. 필수)

PHP-FPM은 실제로 FastCGI 프로세스 관리를 PHP 패키지에 통합하는 것을 목표로 하는 PHP 소스 코드 패치입니다. PHP 소스 코드에 패치해야 하며 PHP를 컴파일하고 설치한 후에 사용할 수 있습니다.
PHP5.3.3에는 php-fpm이 통합되어 있으며 더 이상 타사 패키지가 아닙니다. PHP-FPM은 더 나은 PHP 프로세스 관리 방법을 제공하고, 메모리와 프로세스를 효과적으로 제어할 수 있으며, PHP 구성을 원활하게 다시 로드할 수 있습니다. 이는spawn-fcgi보다 더 많은 장점을 가지고 있어 공식적으로 PHP에 포함됩니다. ./configure에 –enable-fpm 매개변수를 전달하여 PHP-FPM을 활성화할 수 있습니다.

Fastcgi는 이미 php5.3.5의 핵심에 있습니다. 구성 시 --enable-fastcgi를 추가할 필요가 없습니다. php5.2와 같은 이전 버전에는 이 항목을 추가해야 합니다. Nginx와 PHP-FPM을 설치할 때 구성 정보는 다음과 같습니다.


PHP-FPM의 기본 구성php-fpm.conf:

Listen_address 127.0.0.1:9000 #이것은 PHP의 fastcgi 프로세스 수신 IP 주소를 나타냅니다. 및 포트

start_servers

min_spare_servers

max_spare_servers

Nginx 실행 중인 PHP 구성: 편집 nginx.conf에 다음 문을 추가합니다.

              pass 127.0.0.1:9000 은 fastcgi 프로세스가 수신하는 포트를 지정합니다. nginx는 PHP
fastcgi_index index.php;
include fastcgi_params; fastcgi _param SCRIPT_FILENAME /usr /local/nginx/html$fastcgi_script_name;
}



Nginx
location 명령을 통해 접미사가 php인 모든 파일은 모두 127.0.0.1:9000으로 처리되며, 여기서 IP 주소와 포트는 IP 주소와 FastCGI 프로세스가 수신하는 포트입니다. 전체 작업 흐름:

1) FastCGI 프로세스 관리자 php-fpm은 자체적으로 초기화되고 기본 프로세스 php-fpm을 시작하며 start_servers를 시작합니다. CGI 하위 프로세스.

메인 프로세스인 php-fpm은 주로 fastcgi 하위 프로세스를 관리하고 포트 9000을 수신합니다.

fastcgi 하위 프로세스는 웹 서버로부터의 연결을 기다립니다.

2) 클라이언트 요청이 웹 서버 Nginx에 도달하면

Nginx

에서는 location 명령을 통해 접미사로 php가 붙은 모든 파일을 전달합니다. 127.0.0.1:9000 처리를 위해, 즉 Nginx는 위치 명령을 사용하여 처리를 위해 접미사로 php가 포함된 모든 파일을 127.0.0.1:9000으로 넘겨줍니다. 3) FastCGI 프로세스 관리자 PHP-FPM은 하위 프로세스 CGI 인터프리터를 선택하고 연결합니다. 웹 서버는 CGI 환경 변수와 표준 입력을 FastCGI 하위 프로세스로 보냅니다. 4) FastCGI 하위 프로세스는 처리가 완료된 후 동일한 연결에서 표준 출력 및 오류 정보를 웹 서버로 반환합니다. FastCGI 하위 프로세스가 연결을 닫으면 요청이 처리됩니다.

5) 그런 다음 FastCGI 하위 프로세스는 FastCGI 프로세스 관리자(WebServer에서 실행)의 다음 연결을 기다리고 처리합니다.

3. Nginx IO 모델

먼저 nginx에서 지원하는 이벤트 모델은 다음과 같습니다(nginx wiki).

Nginx는 연결 처리를 위해 다음 방법(I/O 다중화 방법)을 지원합니다. 이러한 방법은 use 지시문을 통해 지정할 수 있습니다.

  • select – 표준 방법. 현재 플랫폼에 더 효율적인 방법이 없는 경우 컴파일 타임 기본값입니다. 구성 매개변수 –with-select_module 및 –without-select_module을 사용하여 이 모듈을 활성화하거나 비활성화할 수 있습니다.
  • 설문조사 – 표준 방법입니다. 현재 플랫폼에 더 효율적인 방법이 없는 경우 컴파일 타임 기본값입니다. 구성 매개변수 –with-poll_module 및 –without-poll_module을 사용하여 이 모듈을 활성화하거나 비활성화할 수 있습니다.
  • kqueue – FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 및 MacOS X에서 사용되는 효율적인 방법입니다. 이중 프로세서 MacOS X 시스템에서 kqueue를 사용하면 커널 패닉이 발생할 수 있습니다.
  • epoll – Linux 커널 버전 2.6 이상의 시스템에서 사용되는 효율적인 방법입니다. SuSE 8.2와 같은 일부 배포판에는 2.4 커널에서 epoll을 지원하는 패치가 있습니다.
  • rtsig – Linux 커널 버전 2.2.19 이상이 설치된 시스템에서 사용되는 실행 가능한 실시간 신호입니다. 기본적으로 전체 시스템에는 1024개 이하의 POSIX 실시간(대기열) 신호가 나타날 수 있습니다. 이 상황은 로드가 많은 서버에는 비효율적이므로 커널 매개변수 /proc/sys/kernel/rtsig-max를 조정하여 대기열 크기를 늘려야 합니다. 그러나 Linux 커널 버전 2.6.6-mm2부터 이 매개변수는 더 이상 사용되지 않으며 각 프로세스마다 독립적인 신호 큐가 사용 가능합니다. RLIMIT_SIGPENDING 매개변수 조정. 이 대기열이 너무 혼잡해지면 nginx는 이를 포기하고 정상 상태가 돌아올 때까지 연결을 처리하기 위해 poll 메서드를 사용하기 시작합니다.
  • /dev/poll – 효율적인 방법, Solaris 7 11/99+, HP/UX 11.22+(이벤트 포트), IRIX 6.5.15+ 및 Tru64 UNIX 5.1A+에서 사용됩니다. 🎜>
  • eventport – Solaris 10에서 사용되는 효율적인 방법입니다. 커널 충돌을 방지하려면 보안 패치를 설치해야 합니다. .

Linux에서는 epoll만이 효율적인 방법입니다

epoll이 얼마나 효율적인지 살펴보겠습니다 Epoll은
Linux 커널이 대량의 핸들 폴링을 처리하도록 개선되었습니다. epoll을 사용하려면 epoll_create(2), epoll_ctl(2), epoll_wait(2)의 세 가지 시스템 호출만 필요합니다. 이는 2.5.44 커널(epoll(4)은 Linux 커널 2.5.44에 도입된 새로운 API)에 도입되었으며 2.6 커널에서 널리 사용됩니다.

epoll의 장점

  • 많은 수의 소켓을 하나의 프로세스로 오픈할 수 있도록 지원 설명자(FD)

select 가장 견딜 수 없는 점은 프로세스에 의해 열린 FD에 FD_SETSIZE에 의해 설정된 특정 제한이 있다는 것입니다. 기본값은 2048입니다. 수만 개의 연결을 지원해야 하는 IM 서버에는 분명히 너무 적습니다. 이때 먼저 이 매크로를 수정하고 커널을 다시 컴파일하도록 선택할 수 있지만, 데이터에 따르면 이로 인해 네트워크 효율성이 저하된다는 점도 지적되어 있습니다. 둘째, 다중 프로세스 솔루션(기존 Apache 솔루션)을 선택할 수 있습니다. 하지만 Linux에서 생성된다고 하더라도 프로세스 비용은 상대적으로 적지만 여전히 무시할 수 없습니다. 또한, 프로세스 간 데이터 동기화는 스레드 간 동기화보다 효율성이 훨씬 떨어지므로 완벽한 방법은 아닙니다. 아름다운 계획. 그러나 epoll에는 이러한 제한이 없습니다. 지원하는 FD의 상한은 열 수 있는 최대 파일 수입니다. 이 수는 일반적으로 2048보다 훨씬 큽니다. 예를 들어, 1GB 메모리가 있는 시스템에서는 약 100,000입니다. 구체적인 숫자는 다음과 같습니다. cat /proc /sys/fs/file-max를 확인하세요. 일반적으로 이 숫자는 시스템 메모리와 관련이 많습니다.

  • FD 수가 증가해도 IO 효율성이 선형적으로 감소하지 않습니다

기존 선택/폴링의 또 다른 치명적인 약점 큰 소켓 컬렉션이 있지만 네트워크 대기 시간으로 인해 언제든지 소켓 중 일부만 "활성" 상태가 됩니다. 그러나 선택/폴링에 대한 각 호출은 전체 컬렉션을 선형적으로 스캔하므로 결과적으로 소켓 수가 선형적으로 감소합니다. 능률. 그러나 epoll에는 이 문제가 없으며 "활성" 소켓에서만 작동합니다. 이는 커널 구현에서 epoll이 각 fd의 콜백 함수를 기반으로 구현되기 때문입니다. 그런 다음 "활성" 소켓만 콜백 함수를 적극적으로 호출하고 다른 유휴 상태 소켓은 호출하지 않습니다. 이 시점에서 epoll은 "의사" AIO를 구현합니다. 왜냐하면 이 시점에서 구동력은 os 커널에 있기 때문입니다. 일부에서는 벤치마크에서는 고속 LAN 환경과 같이 모든 소켓이 기본적으로 활성화된 경우 epoll이 select/poll보다 효율적이지 않습니다. 반대로 epoll_ctl을 너무 많이 사용하면 효율성이 약간 떨어집니다. 그러나 유휴 연결을 사용하여 WAN 환경을 시뮬레이션하면 epoll의 효율성이 선택/폴링보다 훨씬 높습니다.

  • 커널과 사용자 공간 사이의 메시지 전달 속도를 높이려면 mmap을 사용하세요.

이 점은 실제로 epoll의 구체적인 구현과 관련이 있습니다. select이든 poll이든 epoll이든 커널은 FD 메시지를 사용자 공간에 알려야 하는데, 불필요한 메모리 복사를 방지하는 방법이 매우 중요합니다. 이때 epoll은 사용자 공간에서 동일한 메모리를 mmap하여 구현합니다. 핵심. 그리고 저처럼 2.5 커널부터 epoll을 따라오셨다면 수동 mmap 단계를 절대 잊지 않으실 것입니다.

  • 커널 미세 조정

이는 사실 epoll의 장점이 아니라 Linux 전체의 장점입니다. 플랫폼. Linux 플랫폼이 의심스러울 수도 있지만 Linux 플랫폼이 제공하는 커널 미세 조정 기능을 피할 수는 없습니다. 예를 들어 커널TCP/IP 프로토콜 스택은 메모리 풀을 사용하여 sk_buff 구조를 관리하므로 이 메모리 풀(skb_head_pool)의 크기는 런타임 중에 동적으로 조정될 수 있습니다. 이는 echo XXXX>/proc/sys/net/core/hot_list_length를 통해 수행됩니다. 또 다른 예는 청취 기능의 두 번째 매개변수(TCP가 3방향 핸드셰이크를 완료한 후 패킷 큐의 길이)이며, 이는 플랫폼의 메모리 크기에 따라 동적으로 조정될 수도 있습니다. 데이터 패킷 수는 많지만 각 패킷 자체의 크기는 매우 작은 특수 시스템에서 최신 NAPI 네트워크 카드 드라이버 아키텍처도 시도했습니다.

(epoll 내용, epoll_interactive 백과사전 참조)

4. 🎜>

1. 컴파일 및 설치 프로세스를 최적화합니다

1) 컴파일 후 Nginx 파일 크기를 줄입니다

Nginx 컴파일 시 기본적으로 디버그 모드로 수행되는데, 디버그 모드에서는 컴파일이 완료된 후 많은 양의 추적 및 ASSERT 정보가 삽입됩니다. 하나의 Nginx 크기는 수 메가바이트가 됩니다. 컴파일하기 전에 Nginx의 디버그 모드를 취소하면 Nginx는 컴파일 후 수백 킬로바이트만 갖게 됩니다. 따라서 컴파일하기 전에 해당 소스 코드를 수정하고 디버그 모드를 취소할 수 있습니다. 구체적인 방법은 다음과 같습니다.

Nginx 소스코드 파일의 압축을 푼 후 소스코드 디렉터리에서 auto/cc/gcc 파일을 찾아 그 안에 다음 라인을 찾습니다.

  1. # debug  
  2. CFLAGS=”$CFLAGS -g” 
주석 처리 또는 삭제 디버그 모드를 취소하려면 이 두 줄을 삭제하세요.

2. 특정 CPU에 대한 CPU 유형 컴파일 최적화 지정

Nginx 컴파일 시 기본 GCC 컴파일 매개변수는 "-O"입니다. 다음 두 매개변수를 사용할 수 있습니다.


  1. --with-cc-opt='-O3' 
  2. --with-cpu-opt=CPU  #为特定的 CPU 编译,有效的值包括:
    pentium, pentiumpro, pentium3, # pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64 
CPU 유형을 확인하려면 다음 명령을 사용할 수 있습니다.

  1. [root@localhost home]#cat /proc/cpuinfo | grep "model name" 

2 TCMalloc을 사용하여 최적화합니다. Nginx의 성능

TCMalloc의 정식 이름은 Thread-Caching Malloc이며 Google에서 개발한 오픈 소스 도구인 google-perftools의 구성원입니다. 표준 glibc 라이브러리의 Malloc과 비교하여 TCMalloc 라이브러리는 메모리 할당이 훨씬 더 효율적이고 빠릅니다. 이는 동시성이 높은 상황에서 서버 성능을 크게 향상시켜 시스템의 부하를 줄입니다. 다음은 Nginx에 TCMalloc 라이브러리 지원을 추가하는 방법에 대한 간략한 소개입니다.

TCMalloc 라이브러리를 설치하려면 libunwind(32비트 운영 체제를 설치할 필요가 없음)와 google-perftools 두 가지 소프트웨어 패키지를 설치해야 합니다. libunwind 라이브러리는 프로그램에 대한 기본 함수 호출 체인을 제공합니다. 64비트 CPU와 운영 체제 및 함수 호출 레지스터 기능을 기반으로 합니다. 다음은 Nginx를 최적화하기 위해 TCMalloc을 사용하는 구체적인 작업 프로세스를 설명합니다.

1) libunwind 라이브러리를 설치합니다

http://download.savannah.gnu.org/releases/libunwind에서 해당 libunwind 버전을 다운로드할 수 있습니다. 여기는 libunwind-0.99-alpha.tar.gz입니다. 설치 과정은 다음과 같습니다:


  1. [root@localhost home]#tar zxvf libunwind-0.99-alpha.tar.gz  
  2. [root@localhost home]# cd libunwind-0.99-alpha/  
  3. [root@localhost libunwind-0.99-alpha]#CFLAGS=-fPIC ./configure  
  4. [root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC  
  5. [root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC install 

2) google-perftools

를 설치하려면 http://google에서 해당 도구를 다운로드할 수 있습니다. -perftools.googlecode.com 여기서 다운로드한 google-perftools 버전은 google-perftools-1.8.tar.gz입니다. 설치 과정은 다음과 같습니다.

  1. [root@localhost home]#tar zxvf google-perftools-1.8.tar.gz  
  2. [root@localhost home]#cd google-perftools-1.8/  
  3. [root@localhost google-perftools-1.8]# ./configure  
  4. [root@localhost google-perftools-1.8]#make && make install  
  5. [root@localhost google-perftools-1.8]#echo "/usr/
    local/lib" 
    > /etc/ld.so.conf.d/usr_local_lib.conf  
  6. [root@localhost google-perftools-1.8]# ldconfig 
이제 google-perftools 설치가 완료됩니다.

3) Nginx 재컴파일

Nginx가 google-perftools를 지원하려면 설치 과정에서 "-with-google_perftools_module" 옵션을 추가해야 합니다. Nginx를 다시 컴파일하십시오. 설치 코드는 다음과 같습니다.

  1. [root@localhostnginx-0.7.65]#./configure \  
  2. >--with-google_perftools_module --with-http_stub_status_module  --prefix=/opt/nginx  
  3. [root@localhost nginx-0.7.65]#make  
  4. [root@localhost nginx-0.7.65]#make install 
여기서 Nginx 설치가 완료되었습니다.

4) google-perftools용 스레드 디렉터리를 추가합니다.

스레드 디렉터리를 만들고 /tmp/tcmalloc 아래에 파일을 넣습니다. 작업은 다음과 같습니다.

  1. [root@localhost home]#mkdir /tmp/tcmalloc  
  2. [root@localhost home]#chmod 0777 /tmp/tcmalloc 

5) Nginx 기본 구성 파일을 수정합니다

nginx.conf 파일을 수정하고 pid 아래에 다음 코드를 추가합니다. 줄:

  1. #pid        logs/nginx.pid;  
  2. google_perftools_profiles /tmp/tcmalloc; 
그런 다음 Nginx를 다시 시작하여 google-perftools 로드를 완료합니다.

6) 실행 상태를 확인합니다

google-perftools가 정상적으로 로드되었는지 확인하려면 다음 명령을 통해 확인할 수 있습니다.

  1. [root@ localhost home]# lsof -n | grep tcmalloc  
  2. nginx      2395 nobody   9w  REG    8,8       0    1599440 /tmp/tcmalloc.2395  
  3. nginx      2396 nobody   11w REG   8,8       0    1599443 /tmp/tcmalloc.2396  
  4. nginx      2397 nobody   13w REG  8,8        0    1599441  /tmp/tcmalloc.2397  
  5. nginx     2398 nobody    15w REG  8,8     0    1599442 /tmp/tcmalloc.2398 
Nginx 구성 파일에서 Worker_processes의 값이 4로 설정되어 있으므로 4개의 Nginx 스레드가 열리고 각 스레드는 한 행의 레코드를 갖게 됩니다. 각 스레드 파일 뒤의 숫자 값은 시작된 Nginx의 pid 값입니다.

이제 TCMalloc을 사용하여 Nginx를 최적화하는 작업이 완료되었습니다.

3. Nginx 커널 매개변수 최적화

커널 매개변수 최적화는 주로 Linux 시스템의 Nginx 애플리케이션에 대한 시스템 커널 매개변수 최적화입니다.

아래에 참고용으로 최적화 예시가 나와 있습니다.

  1. net.ipv4.tcp_max_tw_buckets = 6000 
  2. net.ipv4.ip_local_port_range = 1024 65000  
  3. net.ipv4.tcp_tw_recycle = 1 
  4. net.ipv4.tcp_tw_reuse = 1 
  5. net.ipv4.tcp_syncookies = 1 
  6. net.core.somaxconn = 262144 
  7. net.core.netdev_max_backlog = 262144 
  8. net.ipv4.tcp_max_orphans = 262144 
  9. net.ipv4.tcp_max_syn_backlog = 262144 
  10. net.ipv4.tcp_synack_retries = 1 
  11. net.ipv4.tcp_syn_retries = 1 
  12. net.ipv4.tcp_fin_timeout = 1 
  13. net.ipv4.tcp_keepalive_time = 30 

위의 커널 매개변수 값을 /etc/sysctl.conf 파일에 추가한 후 다음 명령을 실행하여 적용합니다.

  1. [root@ localhost home]#/sbin/sysctl -p 

下面对实例中选项的含义进行介绍:

net.ipv4.tcp_max_tw_buckets选项用来设定timewait的数量,默认是180 000,这里设为6000。

net.ipv4.ip_local_port_range选项用来设定允许系统打开的端口范围。

net.ipv4.tcp_tw_recycle选项用于设置启用timewait快速回收。

net.ipv4.tcp_tw_reuse选项用于设置开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接。

net.ipv4.tcp_syncookies选项用于设置开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies进行处理。

net.core.somaxconn选项的默认值是128, 这个参数用于调节系统同时发起的tcp连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此,需要结合并发请求数来调节此值。

net.core.netdev_max_backlog选项表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目。

net.ipv4.tcp_max_orphans选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤立连接将立即被复位并打印出警告信息。这个限制只是为了防止简单的DoS攻击。不能过分依靠这个限制甚至人为减小这个值,更多的情况下应该增加这个值。

net.ipv4.tcp_max_syn_backlog选项用于记录那些尚未收到客户端确认信息的连接请求的最大值。对于有128MB内存的系统而言,此参数的默认值是1024,对小内存的系统则是128。

net.ipv4.tcp_synack_retries参数的值决定了内核放弃连接之前发送SYN+ACK包的数量。

net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。

net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。默认值是60秒。正确设置这个值非常重要,有时即使一个负载很小的Web服务器,也会出现大量的死套接字而产生内存溢出的风险。

net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。

如果发送端要求关闭套接字,net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。接收端可以出错并永远不关闭连接,甚至意外宕机。

net.ipv4.tcp_fin_timeout的默认值是60秒。需要注意的是,即使一个负载很小的Web服务器,也会出现因为大量的死套接字而产生内存溢出的风险。FIN-WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能消耗1.5KB的内存,但是其生存期长些。

net.ipv4.tcp_keepalive_time选项表示当keepalive启用的时候,TCP发送keepalive消息的频度。默认值是2(单位是小时)。

4. PHP-FPM的优化

如果您高负载网站使用PHP-FPMFastCGI,这些技巧也许对您有用:

1)增加FastCGI进程数

PHP FastCGI子进程数调到100或以上,4G内存的服务器上200就可以建议通过压力测试获取最佳值。

2)增加 PHP-FPM打开文件描述符的限制

标签rlimit_files用于设置PHP-FPM对打开文件描述符的限制,默认值为1024。这个标签的值必须和Linux内核打开文件数关联起来,例如,要将此值设置为65 535,就必须在Linux命令行执行“ulimit -HSn 65536”。

       然后 增加 PHP-FPM打开文件描述符的限制:
     # vi /path/to/php-fpm.conf
    找到
1024”
1024更改为 4096或者更高
.
重启 PHP-FPM.

         3)适当增加max_requests

    标签max_requests指明了每个children最多处理多少个请求后便会被关闭,默认的设置是500。

     500

   

5.   Nginx的php漏洞

취약점 소개: nginx는 널리 사용되는 고성능 웹 서버로 역방향 프록시로 자주 사용될 뿐만 아니라 PHP 작동도 매우 잘 지원할 수 있습니다. 80sec에서는 기본적으로 서버가 PHP의 모든 유형의 파일을 잘못 구문 분석할 수 있으며 이로 인해 악의적인 공격자가 PHP 서버를 지원하는 nginx를 손상시킬 수 있음을 발견했습니다.


취약점 분석: nginx는 기본적으로 cgi 모드에서 실행되는 PHP를 지원합니다. 예를 들어 구성 파일에서

위치 ~ .php$ {<code><br>location ~ .php$ {<br>root html;<br>fastcgi_pass 127.0.0.1:9000;<br>fastcgi_index index.php;<br>fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;<br>include fastcgi_params;<br>}<br>루트 html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;include fastcgi_params;

}

는 php의 구문 분석을 지원합니다. 위치가 요청을 선택하면 백엔드 Fastcgi에 전달된 키 변수 SCRIPT_FILENAME이 nginx에서 생성된 $fastcgi_script_name에 의해 결정됩니다. 분석을 통해 $fastcgi_script_name이 URI 환경 변수에 의해 직접적으로 제어되는 것을 알 수 있는데, 여기서 문제가 발생합니다. PATH_INFO 추출을 더 잘 지원하기 위해 cgi.fix_pathinfo 옵션이 PHP 구성 옵션에 존재합니다. 그 목적은 SCRIPT_FILENAME에서 실제 스크립트 이름을 추출하는 것입니다.

그러므로 http://www.80sec.com/80sec.jpg가 있다고 가정하면 다음과 같은 방법으로



<br>/80sec.jpg/80sec.php<br>http://www.80sec에 액세스합니다. com/80sec.jpg/80sec.php

<br>/scripts/80sec.jpg/80sec.php<br>
는 URI를 얻습니다
<code><br>/scripts/80sec.jpg<br>/80sec.jpg/80sec.php

위치 명령 후 요청은 처리를 위해 백엔드 fastcgi로 전달되고 nginx는 이에 대한 환경 변수 SCRIPT_FILENAME을
<code><br>/scripts/80sec.jpg和80sec.php<br>/scripts/80sec의 내용으로 설정합니다. jpg/80sec.php

lighttpd와 같은 다른 웹서버에서는 SCRIPT_FILENAME이

/scripts/80sec.jpg

로 올바르게 설정되어 있음을 발견했습니다. code>
그래서 그런 문제는 없습니다. <br>HTTP/1.1 200 OK<br>Server: nginx/0.6.32<br>Date: Thu, 20 May 2010 10:05:30 GMT<br>Content-Type: text/plain<br>Content-Length: 18<br>Last-Modified: Thu, 20 May 2010 06:26:34 GMT<br>Connection: keep-alive<br>Keep-Alive: timeout=20<br>Accept-Ranges: bytes<br>백엔드 fastcgi가 이 옵션을 받으면 fix_pathinfo 구성을 기반으로 SCRIPT_FILENAME에 대한 추가 처리를 수행할지 여부를 결정합니다. 일반적으로 fix_pathinfo가 설정되지 않으면 라우팅 선택에 PATH_INFO를 사용하는 애플리케이션에 영향을 미치므로 이는 옵션은 일반적으로 켜져 있도록 구성됩니다. 이 옵션을 전달하면 Php는 실제 스크립트 파일 이름을 검색합니다. 이때, SCRIPT_FILENAME과 PATH_INFO는
<br>/scripts/로 구분됩니다. 80sec.jpg 및 80sec.php<code><br>HTTP/1.1 200 OK<br>Server: nginx/0.6.32<br>Date: Thu, 20 May 2010 10:06:49 GMT<br>Content-Type: text/html<br>Transfer-Encoding: chunked<br>Connection: keep-alive<br>Keep-Alive: timeout=20<br>X-Powered-By: PHP/5.2.6<br>
마지막으로 이 요청에 대해 실행해야 하는 스크립트로 /scripts/80sec.jpg를 사용하면 공격자는 nginx가 PHP를 사용하여 모든 내용을 구문 분석하도록 할 수 있습니다. 파일 유형.

POC: nginx가 PHP를 지원하는 사이트를 방문하여 robots.txt와 같은 리소스 파일 뒤에 /80sec.php를 추가하면 다음과 같은 차이점을 확인할 수 있습니다.

방문하세요. http://www.80sec.com/robots.txt

<p>HTTP/1.1 200 OK<br>서버: nginx/0.6.32<code><br>关闭cgi.fix_pathinfo为0<br>날짜: 2010년 5월 20일 목요일 10:05 :30 GMT
콘텐츠 유형: 텍스트/일반
콘텐츠 길이: 18<br>if ( $fastcgi_script_name ~ ..*/.*php ) {<br>return 403;<br>}<br>최종 수정: 2010년 5월 20일 목요일 06:26:34 GMT

연결: 연결 유지

Keep-Alive: timeout=20

Accept-Ranges: bytes

http://www.80sec.com/robots.txt/80sec.php

HTTP/1.1 200 OK

서버: nginx/0.6.32날짜: 2010년 5월 20일 목요일 10:06:49 GMT콘텐츠 유형: text/html전송 -인코딩: 청크연결: keep-aliveKeep-Alive: timeout=20X-Powered-By: PHP/5.2.6콘텐츠- 유형 변경은 변경을 나타냅니다. 백엔드의 구문 분석 책임이 있으며 사이트에 취약점이 있을 수 있습니다. 취약점 공급업체: http://www.nginx.org해결책: 공식적으로 연락을 시도했으나 그 전에 다음을 통해 손실을 줄일 수 있습니다. 방법 cgi.fix_pathinfo를 0으로 닫습니다또는 if ( $fastcgi_script_name ~ ..*/.*php ) { return 403;}PS: 분석 과정에서 도움을 준 laruence Daniel에게 감사드립니다 위 내용은 Nginx의 작동 원리, 최적화 및 허점을 소개합니다. , 관련 내용을 포함하여 PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.
관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿