스트레스 테스트

스트레스 테스트 결과에는 어떤 요소가 영향을 미치나요?

  • 스트레스 테스트 머신과 서버 간 네트워크 지연 (내부 네트워크 또는 로컬 테스트를 권장)
  • 스트레스 테스트 머신과 서버 간 대역폭 (내부 네트워크 또는 로컬 테스트를 권장)
  • HTTP keep-alive 여부 (활성화 권장)
  • 충분한 동시 요청 수 (외부에서 최대한 많은 동시 요청을 활성화시키는 것이 좋음)
  • 서버 프로세스 수가 적절한지 (helloworld 비즈니스의 경우 CPU 수와 같은 프로세스 수를 권장하며, 데이터베이스 비즈니스의 경우 CPU의 네 배 이상을 권장)
  • 비즈니스 자체의 성능 (예: 외부 데이터베이스 사용 여부)

HTTP keep-alive는 무엇인가요?

HTTP Keep-Alive 메커니즘은 단일 TCP 연결을 통해 여러 HTTP 요청과 응답을 보내는 기술로, 성능 테스트 결과에 큰 영향을 미치며, keep-alive를 비활성화하면 QPS가 크게 감소할 수 있습니다.
현재 대부분의 브라우저는 기본적으로 keep-alive를 활성화하며, 즉 브라우저가 특정 http 주소에 대한 연결을 닫지 않고 유지하여 다음 요청에서 이 연결을 재사용하여 성능을 향상시킵니다.
스트레스 테스트시 keep-alive를 활성화하는 것이 좋습니다.
또한 keep-alive를 비활성화한 상태에서 스트레스 테스트를 수행하면, 클라이언트의 로컬 포트가 TIME_WAIT 상태의 연결로 인해 빠르게 소진됩니다. 이는 총 요청 수가 일정 수량(일반적으로 약 2.8만 개)을 초과하면 요청 실패가 발생하는 현상으로 나타납니다.

HTTP keep-alive를 활성화하는 방법은 무엇인가요?

ab 프로그램을 사용하여 스트레스 테스트하는 경우 -k 매개 변수를 추가해야 합니다. 예를 들면 ab -n100000 -c200 -k http://127.0.0.1:8787/와 같이 사용합니다.
apipost는 gzip 헤더를 반환해야 keep-alive를 활성화할 수 있습니다 (apipost의 버그 참조).
다른 스트레스 테스트 프로그램은 일반적으로 기본적으로 활성화되어 있습니다.

외부 네트워크로 스트레스 테스트할 때 왜 QPS가 매우 낮을까요?

외부 네트워크 지연으로 인해 QPS가 매우 낮아지는 것은 정상적인 현상입니다. 예를 들어 baidu 페이지를 스트레스 테스트하면 QPS가 몇십 개 정도일 수 있습니다.
내부 네트워크 또는 로컬 테스트를 권장하며 네트워크 지연의 영향을 배제해야 합니다.
외부 스트레스 테스트를 수행해야 하는 경우 대역폭을 충분히 확보하기 위해 동시 요청 수를 증가시키는 것이 좋습니다.

Nginx 프록시를 거친 후 왜 성능이 저하될까요?

Nginx 실행에는 시스템 리소스가 필요합니다. 동시에 Nginx와 webman 간의 통신도 일정한 리소스를 소비합니다.
그러나 시스템 리소스는 한정되어 있으므로 webman은 모든 시스템 리소스에 접근할 수 없으므로 전체 시스템의 성능이 약간 저하될 수 있습니다.
Nginx 프록시로 인한 성능 영향을 최소화하기 위해서는 Nginx 로그를 비활성화하고(access_log off;) Nginx와 webman 간의 keep-alive를 활성화하는 것이 좋습니다(nginx 프록시 참조).
또한 https는 http보다 더 많은 리소스를 사용하며 SSL/TLS 핸드셰이크, 데이터 암호화 및 패킷 크기 증가로 인해 성능이 저하됩니다. 스트레스 테스트 시 단일 연결을 사용하는 경우(keep-alive 비활성화), 매번 요청에 대해 추가적인 SSL/TLS 핸드셰이크 통신이 필요하여 성능이 크게 감소할 수 있습니다. https는 keep-alive를 활성화하는 것이 좋습니다.

시스템이 성능 한계에 도달했는지 어떻게 알 수 있나요?

일반적으로 CPU가 100%인 경우 시스템 성능이 한계에 도달했다고 볼 수 있습니다. CPU에 여유가 있다면 아직 한계에 도달하지 않은 것입니다. 이때 동시 요청 수를 증가시켜 QPS를 높일 수 있습니다.
동시 요청 수를 증가시켜도 QPS가 향상되지 않으면 webman 프로세스 수가 충분하지 않은 것일 수 있으며, 이 경우 webman 프로세스 수를 증가시킬 필요가 있습니다. 그래도 성능이 향상되지 않으면 대역폭이 충분한지 확인해야 합니다.

왜 내 스트레스 테스트 결과에서 webman의 성능이 go의 gin 프레임워크보다 낮게 나올까요?

techempower의 스트레스 테스트 결과에 따르면 webman은 플레인 텍스트, 데이터베이스 쿼리 등 모든 기준에서 gin의 대략 두 배의 성능을 보입니다.
만약 여러분의 결과가 다르다면 webman에서 ORM을 사용하여 성능 저하를 초래했을 수 있으며, webman+원시 PDO와 gin+원시 SQL을 비교해볼 수 있습니다.

ORM을 사용한 webman의 성능이 얼마나 감소할까요?

다음은 한 세트의 성능 테스트 데이터입니다.

환경
알리바바 클라우드 4코어 4G, 로컬 MySQL 데이터베이스, 10만 개의 레코드에서 무작위로 1개를 조회하여 JSON으로 반환, 로컬 스트레스 테스트.

원시 PDO를 사용하는 경우
webman의 QPS는 1.78만입니다.

laravel의 Db::table()을 사용하는 경우
webman의 QPS는 0.94만으로 감소합니다.

laravel의 Model을 사용하는 경우
webman의 QPS는 0.72만으로 감소합니다.

thinkORM의 결과는 유사하며 큰 차이가 없습니다.


ORM을 사용하면 성능이 감소하지만, 99%의 비즈니스 시나리오에서는 이미 성능이 충분 이상입니다. 나머지 1%에 해당하는 경우에도 CPU나 서버를 추가하여 쉽게 해결할 수 있습니다.
개발 효율성, 유지보수성, 성능 등 여러 지표 사이에서 균형을 찾아야 하며, 성능만을 맹목적으로 추구해서는 안 됩니다.

왜 apipost를 사용하여 스트레스 테스트하면 QPS가 매우 낮을까요?

apipost의 스트레스 테스트 모듈에 버그가 있어 서버가 gzip 헤더를 반환하지 않으면 keep-alive를 유지할 수 없어 성능이 크게 감소합니다.
해결 방법으로 데이터를 압축하여 gzip 헤더를 추가하여 반환합니다. 예를 들면 다음과 같습니다.

<?php
namespace app\controller;
class IndexController
{
    public function index()
    {
        return response(gzencode('hello webman'))->withHeader('Content-Encoding', 'gzip');
    }
}

이 외에도 특정 상황에서 apipost는 만족스러운 압력을 발휘하지 못할 수 있는데, 이는 동일한 동시 요청일 때 ab보다 약 50% 낮은 QPS가 발생합니다.
스트레스 테스트에는 apipost가 아닌 ab, wrk 또는 다른 전문적인 스트레스 테스트 소프트웨어를 사용하는 것이 좋습니다.

적절한 프로세스 수 설정

webman은 기본적으로 CPU * 4의 프로세스 수를 사용합니다. 실제로 네트워크 I/O가 없는 helloworld 비즈니스의 경우 CPU 코어 수와 동일한 프로세스 수를 사용하면 성능이 최적화되며, 프로세스 전환 비용을 줄일 수 있습니다.
데이터베이스, 레디스 등 차단 I/O 비즈니스의 경우 프로세스 수를 CPU의 3-8배로 설정할 수 있습니다. 이 경우 더 많은 프로세스가 필요하므로 동시에 요청을 처리하여 프로세스 전환 비용은 차단 I/O와 비교하여 무시할 수 있습니다.

스트레스 테스트에 대한 참고 범위

클라우드 서버 4코어 4G 16프로세스 로컬 / 내부 네트워크 스트레스 테스트

- keep-alive 활성화 keep-alive 비활성화
hello world 8-16만 QPS 1-3만 QPS
데이터베이스 단일 쿼리 1-2만 QPS 1만 QPS

제3자 techempower 스트레스 테스트 데이터

스트레스 테스트 명령어 예시

ab

# 100,000요청 200동시요청 keep-alive 활성화
ab -n100000 -c200 -k http://127.0.0.1:8787/

# 100,000요청 200동시요청 keep-alive 비활성화
ab -n100000 -c200 http://127.0.0.1:8787/

wrk

# 200 동시요청 10초간 스트레스 테스트 keep-alive(기본으로 활성화)
wrk -c 200 -d 10s http://example.com