백엔드 개발 PHP 튜토리얼 Nginx 스레드 풀 및 성능 분석

Nginx 스레드 풀 및 성능 분석

Aug 08, 2016 am 09:19 AM
nbsp nginx

아시다시피 NGINX는 연결을 처리하기 위해 비동기식 이벤트 기반 접근 방식을 사용합니다. 이 접근 방식을 사용하면 기존 서버와 마찬가지로 각 요청에 대해 추가 전용 프로세스나 스레드를 만들 필요가 없으며 대신 단일 작업자 프로세스에서 여러 연결과 요청이 처리됩니다. 이를 위해 NGINX는 비차단 소켓 모드에서 작동하며 epoll 및 kqueue와 같은 효과적인 방법을 사용합니다. 완전히 로드된 프로세스 수가 적고(일반적으로 CPU 코어당 하나만) 일정하기 때문에 작업 전환은 메모리를 거의 소비하지 않으며 CPU 주기를 낭비하지 않습니다. 이 접근 방식의 장점은 NGINX 자체를 사용하여 이미 잘 알려져 있습니다. NGINX는 수백만 개의 동시 요청을 매우 잘 처리할 수 있습니다.
각 프로세스는 추가 메모리를 소비하고 프로세스 간 전환은 CPU주기를 소비합니다. CPU 캐시의 데이터를 삭제합니다.
그러나 비동기식 이벤트 중심 접근 방식에는 여전히 문제가 있습니다. 혹은 제가 즐겨 부르는 문제는 적군, 적군의 이름이 블로킹입니다. 불행하게도 많은 타사 모듈이 차단 호출을 사용하지만 사용자(때로는 모듈 개발자조차)가 차단의 단점을 인식하지 못합니다. 차단 작업은 NGINX 성능을 저하시킬 수 있으므로 어떤 대가를 치르더라도 피해야 합니다. 현재 공식 NGINX 코드에서도 모든 시나리오에서 차단 사용을 방지하는 것은 여전히 ​​불가능합니다. NGINX1.7.11에 구현된 스레드 풀 메커니즘은 이 문제를 해결합니다. 이 스레드 풀이 무엇인지, 어떻게 사용하는지 나중에 설명하겠습니다. 이제 우리의 "적군"과 정면충돌을 해보자. 2. 질문 먼저 이 문제를 더 잘 이해하기 위해 NGINX가 어떻게 작동하는지 몇 문장으로 설명하겠습니다. 일반적으로 NGINX는 이벤트 핸들러, 즉 커널에서 모든 연결 이벤트에 대한 정보를 수신한 다음 운영 체제에 수행할 작업에 대한 지침을 보내는 컨트롤러입니다. 실제로 NGINX는 바이트를 읽고 보내는 일상적인 작업을 수행하는 운영 체제를 조정하는 모든 더러운 작업을 수행합니다. 따라서 NGINX의 경우 빠르고 시기적절한 대응이 매우 중요합니다.
작업자 프로세스는 커널의 이벤트를 수신하고 처리합니다.
이벤트는 시간 초과될 수 있습니다. , 소켓이 읽고 쓸 준비가 되었거나 오류가 발생했다는 알림입니다. NGINX는 수많은 이벤트를 수신한 후 이를 차례로 처리하고 필요한 작업을 수행합니다. 따라서 모든 처리는 스레드의 대기열을 통해 간단한 루프로 수행됩니다. NGINX는 대기열에서 이벤트를 가져와 소켓 읽기 및 쓰기와 같이 이에 응답합니다. 대부분의 경우 이 접근 방식은 매우 빠르며(일부 데이터를 메모리에 복사하는 데 약간의 CPU 주기만 필요할 수도 있음) NGINX는 대기열의 모든 이벤트를 플래시로 처리할 수 있습니다.

모든 처리는 스레드 에 의해 간단한 루프로 이루어집니다. 완료
그런데 NGINX에서 처리할 작업이 길고 무거운 작업이라면 어떻게 될까요? 전체 이벤트 처리 루프는 이 작업이 완료되기를 기다리는 동안 중단됩니다. 따라서 "차단 작업"은 이벤트 처리 루프를 일정 기간 동안 크게 중지시키는 작업을 의미합니다. 다양한 이유로 작업이 차단 작업이 될 수 있습니다. 예를 들어, NGINX는 오랜 시간 동안 CPU를 많이 사용하는 처리로 인해 바쁘거나 리소스(예: 하드 디스크 또는 뮤텍스)에 액세스하거나 동기 모드로 데이터베이스에서 해당 라이브러리 함수 호출을 얻기 위해 대기 중일 수 있습니다. 등.). 요점은 이러한 작업을 처리하는 동안 대기열의 일부 이벤트에서 활용할 수 있는 사용 가능한 시스템 리소스가 더 있더라도 작업자 프로세스가 다른 작업을 수행하거나 다른 이벤트를 처리할 수 없다는 것입니다. 비유를 들어보겠습니다. 점원은 앞에 길게 늘어선 고객을 상대해야 합니다. 줄의 첫 번째 고객은 매장이 아닌 창고에 있는 품목을 원했습니다. 판매원은 물건을 가지러 창고로 달려갔습니다. 이제 팀 전체는 이런 종류의 배포를 위해 몇 시간을 기다려야 하고 팀 구성원 모두가 불만스러워합니다. 사람들의 반응을 상상할 수 있겠죠? 이 시간은 구매하려는 품목이 매장에 있지 않는 한 줄을 선 모든 사람의 대기 시간에 추가됩니다.
모두 줄을 서서 먼저 구매하는 사람을 기다려야 했습니다
NGINX에서도 거의 같은 상황이 발생합니다. 예를 들어 파일을 읽을 때 파일이 메모리에 캐시되어 있지 않으면 디스크에서 읽어야 합니다. 디스크(특히 회전하는 디스크)에서 읽는 속도가 느리고 대기열에 대기 중인 다른 요청은 디스크에 액세스할 필요가 없을 때 강제로 대기하게 됩니다. 결과적으로 대기 시간이 증가하고 시스템 리소스가 제대로 활용되지 않습니다.

한 번의 차단 작업으로 인해 모든 후속 작업이 상당히 지연될 수 있습니다.
일부 운영 체제에서는 파일 읽기 및 쓰기를 위한 비동기 인터페이스인 NGINX를 제공합니다. 이러한 인터페이스를 사용할 수 있습니다(AIO 지침 참조). FreeBSD가 좋은 예입니다. 불행히도 Linux에서는 동일한 이점을 얻을 수 없습니다. Linux는 파일 읽기를 위한 비동기 인터페이스를 제공하지만 분명한 단점도 있습니다. 그 중 하나는 파일 액세스와 버퍼링을 정렬해야 하는데 NGINX가 이를 매우 잘 처리한다는 것입니다. 그러나 다른 단점은 더욱 심각합니다. 비동기 인터페이스에서는 파일 설명자에 O_DIRECT 플래그를 설정해야 합니다. 즉, 파일에 대한 모든 액세스가 메모리 내 캐시를 우회하여 디스크의 로드가 증가한다는 의미입니다. 이것이 최선의 선택이 아닌 경우가 많이 있습니다. 이 문제를 타겟 방식으로 해결하기 위해 NGINX 1.7.11에서 스레드 풀이 도입되었습니다. 기본적으로 NGINX+에는 아직 스레드 풀이 포함되어 있지 않지만 사용해 보고 싶다면 영업팀에 문의하세요. NGINX+ R6은 스레드 풀이 활성화된 빌드입니다. 이제 스레드 풀에 들어가서 이것이 무엇인지, 어떻게 작동하는지 살펴보겠습니다. 3. Thread Pool 물건을 배급하기 위해 창고부터 먼 곳까지 가야 하는 불쌍한 판매원의 이야기로 돌아가자. 이번에 그는 더 똑똑해졌고(혹은 화가 난 고객들의 강의를 듣고 더 똑똑해졌을 수도?) 주문 처리 서비스 팀을 고용했습니다. 이제 멀리 떨어진 창고에 있는 물건을 사고 싶은 사람은 더 이상 창고에 직접 갈 필요 없이 주문을 주문 처리 서비스에 맡기면 주문이 처리됩니다. 동시에 우리 영업사원은 계속해서 다른 고객에게 서비스를 제공할 수 있습니다. 따라서 창고에서 상품을 구매하려는 고객만 배송을 기다리면 되고, 다른 고객은 즉시 서비스를 받을 수 있습니다.
주문을 처리 서비스로 전달해도 대기열이 차단되지 않습니다.
Yes NGINX의 경우 스레드 풀은 배포 서비스 기능을 수행합니다. 이는 작업 대기열과 이 대기열을 처리하는 스레드 집합으로 구성됩니다. 작업자 프로세스가 잠재적으로 긴 작업을 수행해야 하는 경우 작업자 프로세스는 더 이상 작업 자체를 수행하지 않고 작업을 스레드 풀 대기열에 넣습니다. 그러면 유휴 스레드는 대기열에서 제거될 수 있습니다. queue 이 작업을 가져와 실행합니다.

작업자 프로세스는 차단 작업을 스레드 풀로 오프로드합니다

그래서 대기열이 하나 더 있는 것과 같습니다. 예. 하지만 이 시나리오에서는 대기열이 특수 리소스로 제한됩니다. 디스크가 데이터를 생성할 수 있는 것보다 더 빠르게 디스크를 읽을 수는 없습니다. 어쨌든, 적어도 이제 디스크는 더 이상 다른 이벤트를 지연시키지 않으며 파일 액세스 요청만 기다려야 합니다. 일반적으로 "디스크에서 읽기" 작업은 차단 작업의 가장 일반적인 예이지만 실제로 NGINX에 구현된 스레드 풀을 사용하면 메인 루프에 맞지 않는 모든 작업을 처리할 수 있습니다. 현재 스레드 풀에 오프로드된 두 가지 기본 작업은 대부분의 운영 체제에서 read() 시스템 호출이고 Linux에서는 sendfile()입니다. 다음으로 스레드 풀을 테스트하고 벤치마킹할 것입니다. 향후 버전에서는 확실한 이점이 있는 경우 다른 작업을 스레드 풀로 오프로드할 수 있습니다. 4. 벤치마킹 이제 이론에서 실습으로 넘어가겠습니다. 차단 작업과 비차단 작업이 혼합된 최악의 상황에서 스레드 풀을 사용할 때의 효과를 시뮬레이션하는 합성 벤치마크를 수행합니다. 또한 메모리에 전혀 맞지 않는 데이터 세트가 필요합니다. 48GB RAM이 있는 시스템에서 각각 4MB의 파일 크기로 총 256GB의 임의 데이터를 생성한 다음 버전 1.9.0으로 NGINX를 구성했습니다. 구성은 간단합니다. worker_processes 16; events {     accept_mutex off; } http {     include mime.types;     default_type application/octet-stream;     access_log off;     sendfile on;     sendfile_max_chunk 512k;     server {         listen 8000;         location / {             root /storage;         }     } }위에 표시된 것처럼 더 나은 성능을 달성하기 위해 여러 매개변수를 조정했습니다. 로깅과 accept_mutex를 동시에 비활성화하고 sendfile을 활성화하고 설정했습니다. sendfile_max_chunk의 크기입니다. 이 마지막 지시문은 NGINX가 전체 파일을 한 번에 전송하려고 시도하지 않고 대신 매번 512KB의 청크로 데이터를 전송하기 때문에 sendfile() 호출을 차단하는 데 소요되는 최대 시간을 줄입니다. 이 테스트 서버에는 Intel Xeon E5645 프로세서 2개(총 코어 12개, 하이퍼 스레드 24개)와 10Gbps 네트워크 인터페이스가 있습니다. 디스크 하위 시스템은 Western Digital WD1003FBYX 4개로 구성됩니다. RAID10 디스크 배열. 이 모든 하드웨어는 Ubuntu Server 14.04.1 LTS로 구동됩니다.

벤치마킹을 위한 로드 생성기 및 NGINX 구성

2개의 클라이언트 서버가 있습니다. 동일한 사양을 가지고 있습니다. 그 중 하나에서는 wrk의 Lua 스크립트를 사용하여 로드 프로그램을 만들었습니다. 스크립트는 200개의 병렬 연결을 사용하여 서버에 파일을 요청하며, 각 요청은 캐시를 놓치고 디스크에서 읽기를 차단할 수 있습니다. 우리는 이 로드를 무작위 로드라고 부릅니다. 在另一台客户端机器上,我们将运行wrk的另一个副本,使用50个并行连接多次请求同一个文件。因为这个文件将被频繁地访问,所以它会一直驻留在内存中。在正常情况下,NGINX能够非常快速地服务这些请求,但是如果工作进程被其他请求阻塞的话,性能将会下降。我们将这种负载称作恒定负载。性能将由服务器上ifstat监测的吞吐率(throughput)和从第二台客户端获取的wrk结果来度量。现在,没有使用线程池的第一次运行将不会带给我们非常振奋的结果:% ifstat -bi eth2 eth2 Kbps in  Kbps out 5531.24  1.03e+06 4855.23  812922.7 5994.66  1.07e+06 5476.27  981529.3 6353.62  1.12e+06 5166.17  892770.3 5522.81  978540.8 6208.10  985466.7 6370.79  1.12e+06 6123.33  1.07e+06如上所示,使用这种配置,服务器产生的总流量约为1Gbps。从下面所示的top输出,我们可以看到,工作进程的大部分时间花在阻塞I/O上(它们处于top的D状态):top - 10:40:47 up 11 days,  1:32,  1 user,  load average: 49.61, 45.77 62.89 Tasks: 375 total,  2 running, 373 sleeping,  0 stopped,  0 zombie %Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 67.7 id, 31.9 wa,  0.0 hi,  0.0 si,  0.0 st KiB Mem:  49453440 total, 49149308 used,   304132 free,    98780 buffers KiB Swap: 10474236 total,    20124 used, 10454112 free, 46903412 cached Mem   PID USER     PR  NI    VIRT    RES     SHR S  %CPU %MEM    TIME+ COMMAND  4639 vbart    20   0   47180  28152     496 D   0.7  0.1  0:00.17 nginx  4632 vbart    20   0   47180  28196     536 D   0.3  0.1  0:00.11 nginx  4633 vbart    20   0   47180  28324     540 D   0.3  0.1  0:00.11 nginx  4635 vbart    20   0   47180  28136     480 D   0.3  0.1  0:00.12 nginx  4636 vbart    20   0   47180  28208     536 D   0.3  0.1  0:00.14 nginx  4637 vbart    20   0   47180  28208     536 D   0.3  0.1  0:00.10 nginx  4638 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.12 nginx  4640 vbart    20   0   47180  28324     540 D   0.3  0.1  0:00.13 nginx  4641 vbart    20   0   47180  28324     540 D   0.3  0.1  0:00.13 nginx  4642 vbart    20   0   47180  28208     536 D   0.3  0.1  0:00.11 nginx  4643 vbart    20   0   47180  28276     536 D   0.3  0.1  0:00.29 nginx  4644 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.11 nginx  4645 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.17 nginx  4646 vbart    20   0   47180  28204     536 D   0.3  0.1  0:00.12 nginx  4647 vbart    20   0   47180  28208     532 D   0.3  0.1  0:00.17 nginx  4631 vbart    20   0   47180    756     252 S   0.0  0.1  0:00.00 nginx  4634 vbart    20   0   47180  28208     536 D   0.0  0.1  0:00.11 nginx  4648 vbart    20   0   25232   1956    1160 R   0.0  0.0  0:00.08 top 25921 vbart    20   0  121956   2232    1056 S   0.0  0.0  0:01.97 sshd 25923 vbart    20   0   40304   4160    2208 S   0.0  0.0  0:00.53 zsh在这种情况下,吞吐率受限于磁盘子系统,而CPU在大部分时间里是空闲的。从wrk获得的结果也非常低:Running 1m test @ http://192.0.2.1:8000/1/1/1   12 threads and 50 connections   Thread Stats   Avg    Stdev     Max  +/- Stdev     Latency     7.42s  5.31s   24.41s   74.73%     Req/Sec     0.15    0.36     1.00    84.62%   488 requests in 1.01m, 2.01GB read Requests/sec:      8.08 Transfer/sec:     34.07MB请记住,文件是从内存送达的!第一个客户端的200个连接创建的随机负载,使服务器端的全部的工作进程忙于从磁盘读取文件,因此产生了过大的延迟,并且无法在合理的时间内处理我们的请求。现在,我们的线程池要登场了。为此,我们只需在location块中添加aio threads指令:location / {     root /storage;     aio threads; }接着,执行NGINX reload重新加载配置。然后,我们重复上述的测试:% ifstat -bi eth2 eth2 Kbps in  Kbps out 60915.19  9.51e+06 59978.89  9.51e+06 60122.38  9.51e+06 61179.06  9.51e+06 61798.40  9.51e+06 57072.97  9.50e+06 56072.61  9.51e+06 61279.63  9.51e+06 61243.54  9.51e+06 59632.50  9.50e+06现在,我们的服务器产生的流量是9.5Gbps,相比之下,没有使用线程池时只有约1Gbps!理论上还可以产生更多的流量,但是这已经达到了机器的最大网络吞吐能力,所以在这次NGINX的测试中,NGINX受限于网络接口。工作进程的大部分时间只是休眠和等待新的时间(它们处于top的S状态):top - 10:43:17 up 11 days,  1:35,  1 user,  load average: 172.71, 93.84, 77.90 Tasks: 376 total,  1 running, 375 sleeping,  0 stopped,  0 zombie %Cpu(s):  0.2 us,  1.2 sy,  0.0 ni, 34.8 id, 61.5 wa,  0.0 hi,  2.3 si,  0.0 st KiB Mem:  49453440 total, 49096836 used,   356604 free,    97236 buffers KiB Swap: 10474236 total,    22860 used, 10451376 free, 46836580 cached Mem   PID USER     PR  NI    VIRT    RES     SHR S  %CPU %MEM    TIME+ COMMAND  4654 vbart    20   0  309708  28844     596 S   9.0  0.1  0:08.65 nginx  4660 vbart    20   0  309748  28920     596 S   6.6  0.1  0:14.82 nginx  4658 vbart    20   0  309452  28424     520 S   4.3  0.1  0:01.40 nginx  4663 vbart    20   0  309452  28476     572 S   4.3  0.1  0:01.32 nginx  4667 vbart    20   0  309584  28712     588 S   3.7  0.1  0:05.19 nginx  4656 vbart    20   0  309452  28476     572 S   3.3  0.1  0:01.84 nginx  4664 vbart    20   0  309452  28428     524 S   3.3  0.1  0:01.29 nginx  4652 vbart    20   0  309452  28476     572 S   3.0  0.1  0:01.46 nginx  4662 vbart    20   0  309552  28700     596 S   2.7  0.1  0:05.92 nginx  4661 vbart    20   0  309464  28636     596 S   2.3  0.1  0:01.59 nginx  4653 vbart    20   0  309452  28476     572 S   1.7  0.1  0:01.70 nginx  4666 vbart    20   0  309452  28428     524 S   1.3  0.1  0:01.63 nginx  4657 vbart    20   0  309584  28696     592 S   1.0  0.1  0:00.64 nginx  4655 vbart    20   0  30958   28476     572 S   0.7  0.1  0:02.81 nginx  4659 vbart    20   0  309452  28468     564 S   0.3  0.1  0:01.20 nginx  4665 vbart    20   0  309452  28476     572 S   0.3  0.1  0:00.71 nginx  5180 vbart    20   0   25232   1952    1156 R   0.0  0.0  0:00.45 top  4651 vbart    20   0   20032    752     252 S   0.0  0.0  0:00.00 nginx 25921 vbart    20   0  121956   2176    1000 S   0.0  0.0  0:01.98 sshd 25923 vbart    20   0   40304   3840    2208 S   0.0  0.0  0:00.54 zsh如上所示,基准测试中还有大量的CPU资源剩余。wrk的结果如下:Running 1m test @ http://192.0.2.1:8000/1/1/1   12 threads and 50 connections   Thread Stats   Avg      Stdev     Max  +/- Stdev     Latency   226.32ms  392.76ms   1.72s   93.48%     Req/Sec    20.02     10.84    59.00    65.91%   15045 requests in 1.00m, 58.86GB read Requests/sec:    250.57 Transfer/sec:      0.98GB服务器处理4MB文件的平均时间从7.42秒降到226.32毫秒(减少了33倍),每秒请求处理数提升了31倍(250 vs 8)!对此,我们的解释是请求不再因为工作进程被阻塞在读文件,而滞留在事件队列中,等待处理,它们可以被空闲的进程处理掉。只要磁盘子系统能做到最好,就能服务好第一个客户端上的随机负载,NGINX可以使用剩余的CPU资源和网络容量,从内存中读取,以服务于上述的第二个客户端的请求。5. 依然没有银弹在抛出我们对阻塞操作的担忧并给出一些令人振奋的结果后,可能大部分人已经打算在你的服务器上配置线程池了。先别着急。实际上,最幸运的情况是,读取和发送文件操作不去处理缓慢的硬盘驱动器。如果我们有足够多的内存来存储数据集,那么操作系统将会足够聪明地在被称作“页面缓存”的地方,缓存频繁使用的文件。“页面缓存”的效果很好,可以让NGINX在几乎所有常见的用例中展示优异的性能。从页面缓存中读取比较快,没有人会说这种操作是“阻塞”。而另一方面,卸载任务到一个线程池是有一定开销的。因此,如果内存有合理的大小并且待处理的数据集不是很大的话,那么无需使用线程池,NGINX已经工作在最优化的方式下。卸载读操作到线程池是一种适用于非常特殊任务的技术。只有当经常请求的内容的大小,不适合操作系统的虚拟机缓存时,这种技术才是最有用的。至于可能适用的场景,比如,基于NGINX的高负载流媒体服务器。这正是我们已经模拟的基准测试的场景。我们如果可以改进卸载读操作到线程池,将会非常有意义。我们只需要知道所需的文件数据是否在内存中,只有不在内存中时,读操作才应该卸载到一个单独的线程中。再回到售货员那个比喻的场景中,这回,售货员不知道要买的商品是否在店里,他必须要么总是将所有的订单提交给配货服务,要么总是亲自处理它们。人艰不拆,操作系统缺少这样的功能。第一次尝试是在2010年,人们试图将这一功能添加到Linux作为fincore()系统调用,但是没有成功。后来还有一些尝试,是使用RWF_NONBLOCK标记作为preadv2()系统调用来实现这一功能(详情见LWN.net上的非阻塞缓冲文件读取操作和异步缓冲读操作)。但所有这些补丁的命运目前还不明朗。悲催的是,这些补丁尚没有被内核接受的主要原因,貌似是因为旷日持久的撕逼大战(bikeshedding)。另一方面,FreeBSD的用户完全不必担心。FreeBSD已经具备足够好的读文件取异步接口,我们应该用这个接口而不是线程池。6. 配置线程池所以,如果你确信在你的场景中使用线程池可以带来好处,那么现在是时候深入了解线程池的配置了。线程池的配置非常简单、灵活。首先,获取NGINX 1.7.11或更高版本的源代码,使用–with-threads配置参数编译。在最简单的场景中,配置看起来很朴实。我们只需要在http、 server,或者location上下文中包含aio threads指令即可:aio threads;这是线程池的最简配置。实际上的精简版本示例如下:thread_pool default threads=32 max_queue=65536; aio threads=default;这里定义了一个名为“default”,包含32个线程,任务队列最多支持65536个请求的线程池。如果任务队列过载,NGINX将输出如下错误日志并拒绝请求:thread pool "NAME" queue overflow: N tasks waiting错误输出意味着线程处理作业的速度有可能低于任务入队的速度了。你可以尝试增加队列的最大值,但是如果这无济于事,那么这说明你的系统没有能力处理如此多的请求了。正如你已经注意到的,你可以使用thread_pool指令,配置线程的数量、队列的最大值,以及线程池的名称。最后要说明的是,可以配置多个独立的线程池,将它们置于不同的配置文件中,用做不同的目的:http {     thread_pool one threads=128 max_queue=0;     thread_pool two threads=32;     server {         location /one {             aio threads=one;         }         location /two {             aio threads=two;         }     } … }如果没有指定max_queue参数的值,默认使用的值是65536。如上所示,可以设置max_queue为0。在这种情况下,线程池将使用配置中全部数量的线程,尽可能地同时处理多个任务;队列中不会有等待的任务。现在,假设我们有一台服务器,挂了3块硬盘,我们希望把该服务器用作“缓存代理”,缓存后端服务器的全部响应信息。预期的缓存数据量远大于可用的内存。它实际上是我们个人CDN的一个缓存节点。毫无疑问,在这种情况下,最重要的事情是发挥硬盘的最大性能。我们的选择之一是配置一个RAID阵列。这种方法毁誉参半,现在,有了NGINX,我们可以有其他的选择:# 我们假设每块硬盘挂载在相应的目录中:/mnt/disk1、/mnt/disk2、/mnt/disk3 proxy_cache_path /mnt/disk1 levels=1:2 keys_z                  use_temp_path=off; proxy_cache_path /mnt/disk2 levels=1:2 keys_z                  use_temp_path=off; proxy_cache_path /mnt/disk3 levels=1:2 keys_z                  use_temp_path=off; thread_pool pool_1 threads=16; thread_pool pool_2 threads=16; thread_pool pool_3 threads=16; split_clients $request_uri $disk {     33.3%     1;     33.3%     2;     *         3; } location / {     proxy_pass http://backend;     proxy_cache_key $request_uri;     proxy_cache cache_$disk;     aio threads=pool_$disk;     sendfile on; }在这份配置中,使用了3个独立的缓存,每个缓存专用一块硬盘,另外,3个独立的线程池也各自专用一块硬盘。缓存之间(其结果就是磁盘之间)的负载均衡使用split_clients模块,split_clients非常适用于这个任务。在 proxy_cache_path指令中设置use_temp_path=off,表示NGINX会将临时文件保存在缓存数据的同一目录中。这是为了避免在更新缓存时,磁盘之间互相复制响应数据。这些调优将带给我们磁盘子系统的最大性能,因为NGINX通过单独的线程池并行且独立地与每块磁盘交互。每块磁盘由16个独立线程和读取和发送文件专用任务队列提供服务。我敢打赌,你的客户喜欢这种量身定制的方法。请确保你的磁盘也持有同样的观点。이 예는 NGINX가 하드웨어에 맞게 특별히 조정할 수 있는 유연성을 보여주는 훌륭한 예입니다. 머신과 데이터가 최선의 자세를 사용하여 기본을 수행하도록 NGINX에 명령을 내린 것과 같습니다. 또한 사용자 공간에서 NGINX의 세밀한 조정을 통해 소프트웨어, 운영 체제 및 하드웨어가 최적의 모드에서 작동하고 시스템 리소스를 최대한 효율적으로 활용할 수 있습니다. 7. 요약결론적으로 스레드 풀은 NGINX의 성능을 새로운 수준으로 끌어올리고 잘 알려진 장기 위험 차단 기능을 제거하는 훌륭한 기능입니다. —특히 우리가 실제로 많은 콘텐츠를 다룰 때는 더욱 그렇습니다. 그래도 놀라움은 더 있습니다. 앞서 언급했듯이 이 새로운 인터페이스를 사용하면 성능 저하 없이 장기 차단 작업을 오프로드할 수 있습니다. NGINX는 수많은 새로운 모듈과 새로운 기능으로 새로운 세계를 열어줍니다. 많은 인기 라이브러리는 여전히 비동기 비차단 인터페이스를 제공하지 않으며, 이로 인해 이전에는 NGINX와 호환되지 않았습니다. 자체적인 비차단 프로토타입 라이브러리를 개발하는 데 많은 시간과 자원을 투자할 수 있지만 항상 그만한 가치가 있습니까? 이제 스레드 풀을 사용하면 이러한 모듈의 성능에 영향을 주지 않고 이러한 라이브러리를 비교적 쉽게 사용할 수 있습니다.





이상으로 Nginx의 스레드 풀과 성능 분석을 소개했으며, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Tomcat 서버에 대한 외부 네트워크 액세스를 허용하는 방법 Tomcat 서버에 대한 외부 네트워크 액세스를 허용하는 방법 Apr 21, 2024 am 07:22 AM

Tomcat 서버가 외부 네트워크에 액세스하도록 허용하려면 다음을 수행해야 합니다. 외부 연결을 허용하도록 Tomcat 구성 파일을 수정합니다. Tomcat 서버 포트에 대한 액세스를 허용하는 방화벽 규칙을 추가합니다. Tomcat 서버 공용 IP에 대한 도메인 이름을 가리키는 DNS 레코드를 만듭니다. 선택 사항: 역방향 프록시를 사용하여 보안 및 성능을 향상합니다. 선택 사항: 보안 강화를 위해 HTTPS를 설정합니다.

nginx 시작 및 중지 명령은 무엇입니까? nginx 시작 및 중지 명령은 무엇입니까? Apr 02, 2024 pm 08:45 PM

Nginx의 시작 및 중지 명령은 각각 nginx 및 nginx -s quit입니다. start 명령은 서버를 직접 시작하는 반면 stop 명령은 서버를 정상적으로 종료하여 모든 현재 요청이 처리되도록 합니다. 사용 가능한 기타 정지 신호에는 정지 및 재장전이 포함됩니다.

thinkphp를 실행하는 방법 thinkphp를 실행하는 방법 Apr 09, 2024 pm 05:39 PM

ThinkPHP Framework를 로컬에서 실행하는 단계: ThinkPHP Framework를 로컬 디렉터리에 다운로드하고 압축을 풉니다. ThinkPHP 루트 디렉터리를 가리키는 가상 호스트(선택 사항)를 만듭니다. 데이터베이스 연결 매개변수를 구성합니다. 웹 서버를 시작합니다. ThinkPHP 애플리케이션을 초기화합니다. ThinkPHP 애플리케이션 URL에 접속하여 실행하세요.

phpmyadmin을 등록하는 방법 phpmyadmin을 등록하는 방법 Apr 07, 2024 pm 02:45 PM

phpMyAdmin을 등록하려면 먼저 MySQL 사용자를 생성하고 권한을 부여한 다음 phpMyAdmin을 다운로드, 설치 및 구성하고 마지막으로 phpMyAdmin에 로그인하여 데이터베이스를 관리해야 합니다.

nodejs 프로젝트를 서버에 배포하는 방법 nodejs 프로젝트를 서버에 배포하는 방법 Apr 21, 2024 am 04:40 AM

Node.js 프로젝트의 서버 배포 단계: 배포 환경 준비: 서버 액세스 권한 획득, Node.js 설치, Git 저장소 설정. 애플리케이션 빌드: npm run build를 사용하여 배포 가능한 코드와 종속성을 생성합니다. Git 또는 파일 전송 프로토콜을 통해 서버에 코드를 업로드합니다. 종속성 설치: SSH를 서버에 연결하고 npm install을 사용하여 애플리케이션 종속성을 설치합니다. 애플리케이션 시작: node index.js와 같은 명령을 사용하여 애플리케이션을 시작하거나 pm2와 같은 프로세스 관리자를 사용합니다. 역방향 프록시 구성(선택 사항): Nginx 또는 Apache와 같은 역방향 프록시를 사용하여 트래픽을 애플리케이션으로 라우팅합니다.

nginx에 오신 것을 환영합니다! 어떻게 해결하나요? nginx에 오신 것을 환영합니다! 어떻게 해결하나요? Apr 17, 2024 am 05:12 AM

"Welcome to nginx!" 오류를 해결하려면 가상 호스트 구성을 확인하고, 가상 호스트를 활성화하고, Nginx를 다시 로드하고, 가상 호스트 구성 파일을 찾을 수 없으면 기본 페이지를 만들고, Nginx를 다시 로드해야 합니다. 그러면 오류 메시지가 나타납니다. 사라지고 웹사이트는 정상적으로 표시됩니다.

웹사이트에 접속할 때 nginx 문제를 해결하는 방법 웹사이트에 접속할 때 nginx 문제를 해결하는 방법 Apr 02, 2024 pm 08:39 PM

웹사이트에 접속할 때 nginx가 나타날 수 있습니다. 서버 유지 관리, 바쁜 서버, 브라우저 캐시, DNS 문제, 방화벽 차단, 웹사이트 구성 오류, 네트워크 연결 문제 또는 웹사이트 다운이 원인일 수 있습니다. 다음 해결 방법을 시도해 보십시오. 유지 관리가 끝날 때까지 기다리기, 사용량이 적은 시간에 방문하기, 브라우저 캐시 지우기, DNS 캐시 플러시하기, 방화벽 또는 바이러스 백신 소프트웨어 비활성화하기, 사이트 관리자에게 문의하기, 네트워크 연결 확인하기, 검색 엔진 사용하기 또는 사이트의 다른 사본을 찾으려면 웹 아카이브를 방문하세요. 문제가 지속되면 사이트 관리자에게 문의하세요.

도커 컨테이너 간 통신 방법 도커 컨테이너 간 통신 방법 Apr 07, 2024 pm 06:24 PM

Docker 환경에는 공유 네트워크, Docker Compose, 네트워크 프록시, 공유 볼륨 및 메시지 큐의 5가지 컨테이너 통신 방법이 있습니다. 격리 및 보안 요구 사항에 따라 Docker Compose를 활용하여 연결을 단순화하거나 네트워크 프록시를 사용하여 격리를 높이는 등 가장 적절한 통신 방법을 선택하세요.

See all articles