많은 요청 후에 'ab' 프로그램이 정지되는 이유는 무엇입니까?
-
06-07-2019 - |
문제
웹 서버를 벤치마킹하기 위해 'ab'를 사용할 때마다 많은 요청을 보낸 후 잠시 정지되고 20초 정도 후에 계속됩니다.
Ruby로 작성된 다음 HTTP 서버 시뮬레이터를 고려해보세요.
require 'socket'
RESPONSE = "HTTP/1.1 200 OK\r\n" +
"Connection: close\r\n" +
"\r\n" +
"\r\n"
buffer = ""
server = TCPServer.new("127.0.0.1", 3000) # Create TCP server at port 3000.
server.listen(1024) # Set backlog to 1024.
while true
client = server.accept # Accept new client.
client.write(RESPONSE) # Write a stock "HTTP" response.
client.close_write # Shutdown write part of the socket.
client.read(nil, buffer) # Read all data from the socket.
client.close # Close it.
end
그런 다음 다음과 같이 ab를 실행합니다.
ab -n 45000 -c 10 http://127.0.0.1:3000/
처음 몇 초 동안 ab는 예상대로 작업을 수행하고 100% CPU를 사용합니다.
Benchmarking 127.0.0.1 (be patient)
Completed 4500 requests
Completed 9000 requests
Completed 13500 requests
약 13500개의 요청 후에는 시스템 CPU 사용량이 0%로 떨어집니다.ab는 뭔가에 얼어붙은 것 같아요.현재 서버가 accept()를 호출하고 있기 때문에 문제는 서버에 있는 것이 아닙니다.약 20초 후에 ab는 아무 일도 일어나지 않은 것처럼 계속되고 CPU를 다시 100% 사용하게 되며 몇 초 후에 다시 정지됩니다.
커널의 무언가가 연결을 제한하고 있는 것 같습니다. 그런데 무엇과 그 이유는 무엇입니까?저는 OS X Leopard를 사용하고 있습니다.Linux에서도 유사한 동작을 보았지만 정지는 훨씬 더 많은 수의 요청에서 발생하고 자주 발생하지는 않습니다.
이 문제로 인해 대규모 HTTP 벤치마크를 실행할 수 없습니다.
해결책
당신이 부족한 것 같아요 임시 포트.확인하려면 netstat
명령을 내리고 수천 개의 포트를 찾으십시오. TIME_WAIT
상태.
Mac OS X에서 기본 임시 포트 범위는 49152~65535이며 총 포트 수는 16384개입니다.이 내용은 다음을 통해 확인할 수 있습니다. sysctl
명령:
$ sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last net.inet.ip.portrange.first: 49152 net.inet.ip.portrange.last: 65535
임시 포트가 부족해지면 일반적으로 다음이 나올 때까지 기다려야 합니다. TIME_WAIT
특정 포트 번호를 재사용할 수 있을 때까지 상태가 만료됩니다(2 * 최대 세그먼트 수명).Linux 및 Solaris의 기본값인 32768에서 시작하도록 범위를 변경하여 포트 수를 두 배로 늘릴 수 있습니다.(최대 포트번호는 65535 이므로 하이엔드를 늘릴 수 없습니다.)
$ sudo sysctl -w net.inet.ip.portrange.first=32768 net.inet.ip.portrange.first: 49152 -> 32768
참고 IANA가 지정한 공식 범위 49152~65535이며 일부 방화벽에서는 동적으로 할당된 포트가 해당 범위에 속한다고 가정할 수 있습니다.로컬 네트워크 외부의 더 넓은 범위를 사용하려면 방화벽을 재구성해야 할 수도 있습니다.
최대 세그먼트 수명을 줄이는 것도 가능합니다(sysctl net.inet.tcp.msl
Mac OS X의 경우), 지속 시간을 제어합니다. TIME_WAIT
그러나 이는 이전 연결이 동일한 포트 번호를 사용하는 새 연결과 혼동될 수 있으므로 위험합니다.또한 특정 포트에 바인딩하는 것과 관련된 몇 가지 트릭이 있습니다. SO_REUSEADDR
옵션 또는 SO_LINGER
옵션이지만 이전 연결과 새 연결이 혼동될 수도 있으므로 일반적으로 나쁜 생각으로 간주됩니다.
다른 팁
포트 수를 늘리는 대신 길이를 변경하십시오. TIME_WAIT
Mac OS X에서.
이것은 개발에서만 작동하지만 이제 물어볼 수 있습니다. ab
시간 초과 없이 원하는 만큼 요청을 처리할 수 있습니다.
다음과 같이 기본 시간 제한을 1000ms로 설정합니다.
$ sudo sysctl -w net.inet.tcp.msl=1000
net.inet.tcp.msl: 15000 -> 1000
다른 답변에 언급된 brianp.net 페이지는 더 이상 사용할 수 없습니다.에서 검색할 수 있습니다. 인터넷 아카이브.
문제를 해결하는 또 다른 옵션은 다음을 추가하여 HTTP KeepAlive를 활성화하는 것입니다. "-k"
옵션.이렇게 하면 ab가 TCP 연결을 재사용하게 되고 결과적으로 사용 가능한 모든 포트가 소진되지 않습니다.예를 들어:
ab -n 45000 -c 10 -k http://127.0.0.1:3000/