데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [K6성능테스트 도구 - 02] Check 및 Threshold로 요청 성공 체크 및 테스트 종료하기

      KIDO 22.11.01
      4,722 5 0

      Check

      • Check는 불리언 조건을 검증한다.

      • check를 활용하여 요청의 응답이 기대에 부응하는지 확인할 수 있다.

      • 예를 들어 POST 요청에 response.status == 201이 있는지 또는 본문이 특정 크기인지 확인할 수 있다.

      • Check는 프로그래밍 언어에서 assume 과 유사하지만 실패했다고 테스트를 종료하지 않는다는 특징이 있다.

      • 대신 k6은 테스트가 계속 실행될 때 실패한 검사의 비율을 추적한다. (각 검사는 Rate 메트릭을 생성함)

      • 검사를 중단하거나 테스트에 실패하게 하려면 이를 Thresholds 와 연결하여 사용할 수 있다.


      Check for HTTP response code

      • HTTP 요청 과 응답과 관련된 검사를 코드하는데 유용하다.

      • 예를 들어 아래 코드는 HTTP 응답 코드가 200인지 확인한다.

      import { check } from 'k6';
      import http from 'k6/http';
      
      export default function () {
        const res = http.get('http://test.k6.io/');
        check(res, {
          'is status 200': (r) => r.status === 200,
        });
      }


      응답 body에서 내용 체크하기

      • 가끔 HTTP 200 응답은 에러 메시지를 포함한다.

      • 이런 상황에서 응답 body가 올바른지 검사가 필요하다.

      import { check } from 'k6';
      import http from 'k6/http';
      
      export default function () {
        const res = http.get('http://test.k6.io/');
        check(res, {
          'verify homepage text': (r) =>
            r.body.includes('Collection of simple web-pages suitable for load testing'),
        });
      }
      • 위 코드는 응답을 res에 담고, 해당 내용의 body에서 우리가 찾고자 하는 문장이 존재하는지 검사하는 코드이다.

      • 결과 내역이 존재하면 check 결과가 true가 되고, 아닌경우 false로 체크된다.


      응답 body size 체크

      • 응답 바디의 size를 검사하기 위해서 check 를 다음과 같이 이용할 수 있다.

      import { check } from 'k6';
      import http from 'k6/http';
      
      export default function () {
        const res = http.get('http://test.k6.io/');
        console.log('body size: ' + res.body.length)
        check(res, {
          'body size is 11278 bytes': (r) => r.body.length == 11278,
        });
      }
      • 위 내용은 응답 body의 크기가 11278 인지 검사한다.


      성공한 검사의 비율 확인하기

      • 스크립트가 Check를 포함하면 써머리 리포트는 테스트의 검사가 통과했는지의 비율을 나타낸다.

      k6 run script.js
      
        ...
          ✓ is status 200
      
        ...
        checks.........................: 100.00% ✓ 1        ✗ 0
        data_received..................: 11 kB   12 kB/s
      • 이 예제에서 "is status 200" 을 체크하고 100% 응답값이 맞는지 검사한다.


      여러개 Check 추가하기

      • 복수 체크역시 수행할 수 있다.

      import { check } from 'k6';
      import http from 'k6/http';
      
      export default function () {
        const res = http.get('http://test.k6.io/');
        check(res, {
          'is status 200': (r) => r.status === 200,
          'body size is 11,105 bytes': (r) => r.body.length == 11105,
        });
      }
      • 위 코드는 응답코드가 200인지 검사하고 동시에 body의 크기가 11105인지 검사한다.

      • 두 조건을 만족한경우 검사 결과는 true이며, 아닌경우 false가 집계된다.

      • 테스트 수행이 되면 결과는 다음과 같다.

      k6 run checks.js
      
        ...
          ✓ is status 200
          ✓ body size is 11,105 bytes
      
        ...
        checks.........................: 100.00% ✓ 2        ✗ 0
        data_received..................: 11 kB   20 kB/s
      • 즉 보는바와 같이 checks 가 100% 이며, 이는 2개의 체크가 모두 성공했음을 의미한다.

      • 상단 "is status"와 "body size is" 는 check의 이름 태그이다.

      from: https://k6.io/docs/using-k6/checks/

      Thresholds

      • Threshold 는 pass/fail 조건으로 테스트 메트릭에 대한 검사를 수행하고 계속진행할지 종료할지 결정한다.

      • 테스트 중인 시스템(SUT)의 성능 임계값 조건을 충족하지 않으면 테스트가 실패 상태로 종료된다.

      • 종종 테스터는 임계값을 사용하여 SLO(Service Level Objectives)를 체계화 한다.

      • 예를 들어 다음 기대치를 조합하여 임계값을 생성할 수 있다.

        • 요청에 대한 에러가 1% 미만인경우

        • 요청의 95%의 응답이 200ms 이하인경우

        • 요청에 99%의 응답이 400ms 이하인경우

        • 특정 엔드포인트가 항상 응답이 300ms 이하인경우

        • 커스템 메트릭에 대한 조건 검사

      • Threshold들은 로드 테스팅 자동화의 핵심이다. https://k6.io/docs/testing-guides/automated-performance-testing

      • 테스트의 Threshold 를 준다.

      • 실행을 자동화 한다.

      • 테스트 실패에 대해 alert 를 설정한다.

      • 그 후에는 SUT가 성능 기대치를 충족하지 못한 후에만 테스트에 대해 고민하고 시스템을 개선해야한다.


      예: HTTP errors and response duration

      • 이 샘플 스크립트는 2개 Thresholds를 지정했다.

      • 하나는 HTTP 에러에 대한 비율을 검증한다. (http_req_failed 메트릭이용)

      • 다른 하나는 특정 기간동안 응답의 95%가 발생했는지 검증한다. (http_req_duration 메트릭)

      import http from 'k6/http';
      
      export const options = {
        thresholds: {
          http_req_failed: ['rate<0.01'], // http errors 가 1% 이하이어야함
          http_req_duration: ['p(95)<200'], // 요청의 95% 가 200ms 이하 이어야함
        },
      };
      
      export default function () {
        http.get('https://test-api.k6.io/public/crocodiles/1/');
      }
      • 즉, pass 조건에 대한 특정 표션식을 지정하면, 만약 금정 결과가 실패하였을때 k6는 전체 테스트를 실패로 간주한다.

      • 테스트가 끝날때 해당 조건식이 false로 평가되면 k6는 전체 실패로 간주한다.

      • 이후 k6 출력은 다음과 같다.

         ✓ http_req_duration..............: avg=151.06ms min=151.06ms med=151.06ms max=151.06ms p(90)=151.06ms p(95)=151.06ms
             { expected_response:true }...: avg=151.06ms min=151.06ms med=151.06ms max=151.06ms p(90)=151.06ms p(95)=151.06ms
         ✓ http_req_failed................: 0.00%  ✓ 0 ✗ 1
      • 이 케이스에서, 두 임계값에 대한 기준을 충족했다.

      • k6는 테스트를 통과한 것으로 간주하고 실패값은 0으로 출력하며 종료한다.

      • 만약 스레시 홀드가 실패했다면 녹색마크가 붉은색 x로 표시되고 0이아닌 종료 코드로 출력된다.


      Copy-paste threshold 예제

      import http from 'k6/http';
      import { sleep } from 'k6';
      
      export const options = {
        thresholds: {
          // 요청의 90% 가 400ms 이하인지 검사
          http_req_duration: ['p(90) < 400'],
        },
      };
      
      export default function () {
        http.get('https://test-api.k6.io/public/crocodiles/1/');
        sleep(1);
      }
      • 다음은 에러율이 1퍼센트 이하인지 확인한다.

      import http from 'k6/http';
      import { sleep } from 'k6';
      
      export const options = {
        thresholds: {
          // 에러 비율이 1% 이하인지 검사
          http_req_failed: ['rate<0.01'],
        },
      };
      
      export default function () {
        http.get('https://test-api.k6.io/public/crocodiles/1/');
        sleep(1);
      }
      • 단일 메트릭에 대해서 복수 threshold 역시 가능하다.

        • 하나의 메트릭에 대해 여러 임계값을 적용할 수도 있다.

        • 서로다른 백분위수 임계값을 가진다.

      import http from 'k6/http';
      import { sleep } from 'k6';
      
      export const options = {
        thresholds: {
          // 요청 결과로 90%가 400ms이하, 95%가 800ms이하, 99.9%가 초 이하 2s.
          http_req_duration: ['p(90) < 400', 'p(95) < 800', 'p(99.9) < 2000'],
        },
      };
      
      export default function () {
        const res1 = http.get('https://test-api.k6.io/public/crocodiles/1/');
        sleep(1);
      }
      • 그룹 duration 스레시홀드 지정

        • 각 그룹에 스레시홀드를 지정할 수 있다.

        • 이 코드에는 개별 요청 및 일괄 요청에 대한 그룹이 있다. 각 그룹에는 서로다른 임계값이 있다.

        • 위 처리는 요청 결과로 90%가 400 이하로 응답했고, 95%가 800 이하로 응답했으며, 99.9 가 2000 이내에 응답했음을 체크한다.

      • 아래 예제는 그룹별로 Threshold 를 검사한다.

      import http from 'k6/http';
      import { group, sleep } from 'k6';
      
      export const options = {
        thresholds: {
          'group_duration{group:::individualRequests}': ['avg < 400'],
          'group_duration{group:::batchRequests}': ['avg < 200'],
        },
        vus: 1,
        duration: '10s',
      };
      
      export default function () {
        group('individualRequests', function () {
          http.get('https://test-api.k6.io/public/crocodiles/1/');
          http.get('https://test-api.k6.io/public/crocodiles/2/');
          http.get('https://test-api.k6.io/public/crocodiles/3/');
        });
      
        group('batchRequests', function () {
          http.batch([
            ['GET', `https://test-api.k6.io/public/crocodiles/1/`],
            ['GET', `https://test-api.k6.io/public/crocodiles/2/`],
            ['GET', `https://test-api.k6.io/public/crocodiles/3/`],
          ]);
        });
      
        sleep(1);
      }
      • 위 코드 결과는 individualRequests 요청 그룹에서 평균 응답시간이 400 이상인경우 테스트를 종료한다.

      • 그리고 batchRequests 요청 그룹에서 평균 응답 시간이 200 이상인경우 테스트를 종료한다.

      • Threshold 신택스

        • 임계값을 사용하려면 하나 이상의 threshold_expression을 정의해야한다.

      export const options = {
        thresholds: {
          metric_name1: ['threshold_expression', `...`], // 간단한 형식
          metric_name2: [
            {
              threshold: 'threshold_expression',
              abortOnFail: true, // boolean
              delayAbortEval: '10s', // string
            },
          ], // 완전한 형식
        },
      };
      • 이 선언은 metric_name1 및 metric_name2 메트릭에 대한 임계값을 구성한다.

      • 임계값 통과 또는 실패 여부를 결정하기 위해 스크립트는 'threshold_expression' 을 평가한다.

      • 'threshold_expression' 은 반드시 다음 형식이어야한다.

      • aggregation_method 오퍼레이터 값

      • 예

        • avg < 200 // 평균 duration은 200ms 이하

        • count >= 500 // count는 500 이상

        • p(90) < 300 // 90%의 샘플값은 300 미만

      • threshold 표현식은 true/false 로 평가된다.

      • k6에 포함된 메트릭 타입의 각각은 임계값 표현식에서 사용할 수 있는 집계 방법 세트를 제공한다.

      Metric type

      Aggregation Methods

      Counter

      count/rate

      Gauge

      value

      Rate

      rate

      Trend

      avg/min/max/med 그리고 p(N) 이며 N은 0.0에서 100.0이고 백분위는 p(99.99) 이다. 이 값의 유닛은 밀리초이다

      • 다음은 모든 다른 유형의 메트릭을 사용하고 각각에 대해 다른 유형의 임계값을 설정하는 샘플이다.

      import http from 'k6/http';
      import { Trend, Rate, Counter, Gauge } from 'k6/metrics';
      import { sleep } from 'k6';
      
      export const TrendRTT = new Trend('RTT');
      export const RateContentOK = new Rate('Content OK');
      export const GaugeContentSize = new Gauge('ContentSize');
      export const CounterErrors = new Counter('Errors');
      export const options = {
        thresholds: {
          'Errors': ['count<100'],
          'ContentSize': ['value<4000'],
          'Content OK': ['rate>0.95'],
          'RTT': ['p(99)<300', 'p(70)<250', 'avg<200', 'med<150', 'min<100'],
        },
      };
      
      export default function () {
        const res = http.get('https://test-api.k6.io/public/crocodiles/1/');
        const contentOK = res.json('name') === 'Bert';
      
        TrendRTT.add(res.timings.duration);
        RateContentOK.add(contentOK);
        GaugeContentSize.add(res.body.length);
        CounterErrors.add(!contentOK);
      
        sleep(1);
      }
      • 다음 threshold가 있다.

        • counter 메트릭은 컨텐츠 응답이 정상이지 않은 총 횟수를 추적하고 있다.

          • 여기서 성공 기준은 컨텐츠가 99번 이상 나쁠수 없다는 것이다.

        • gauge 메트릭은 반환된 컨텐츠의 최신 크기를 포함한다.

          • 이 메트릭의 성공 기준은 반환된 컨텐츠가 4000 바이트보다 작은것이다.

        • 컨텐츠가 얼마나 자주 반환되었는지 추적하는 비율 측정항목은 OK이다.

          • 이 측정항목에는 하나의 성공 기준이 있다. 컨텐츠가 95% 이상이 정상이다.

        • 트렌드 메트릭은 응답시간 샘플이 제공되고 다음 임계값 기준이 있는 추세 메트릭이다.

          • 99번째 백분위수 응답 시간은 300ms 미만이어야한다.

          • 70번째 백분위수 응답 시간은 250ms 미만이어야한다.

          • 평균 응답시간은 200ms 미만이어야한다.

          • 중간 응답 시간은 150ms 미만이어야한다.

          • 최소 응답 시간은 100ms 미만이어야한다.

      • 공통 실수

        • 동일한 객체 키에 반복으로 동일한 메트릭으로 여러개의 Threshold 를 지정하지 마라.

      export const options = {
        thresholds: {
          // avoid using the same metric more than once here
          // metric_name: [ 'count<100' ],
          // metric_name: [ 'rate<50' ],
        },
      };
      • 임계값은 JavaScript 객체의 속성으로 정의되는 동일한 속성 이름으로 여러 개를 지정할 수 있다.

      • 마지막 하나만 남게 된다.

      • 나머지는 조용히 무시된다. 대신 동일한 키에 대한 배열로 저장하면 된다.


      태그를 기준으로 threshold 검사하기

      • 단일 URL또는 특정 태그에 임계값을 지정하는 것이 가끔 필요하다.

      • k6에서 태그가 지정된 요청은 임계값에서 사용할 수 있는 하위 지표를 생성한다.

      export const options = {
        thresholds: {
          'metric_name{tag_name:tag_value}': ['threshold_expression'],
        },
      };
      • 완전한 예제는 다음과 같다.

      import http from 'k6/http';
      import { sleep } from 'k6';
      import { Rate } from 'k6/metrics';
      
      export const options = {
        thresholds: {
          'http_req_duration{type:API}': ['p(95)<500'], // threshold on API requests only
          'http_req_duration{type:staticContent}': ['p(95)<200'], // threshold on static content only
        },
      };
      
      export default function () {
        const res1 = http.get('https://test-api.k6.io/public/crocodiles/1/', {
          tags: { type: 'API' },
        });
        const res2 = http.get('https://test-api.k6.io/public/crocodiles/2/', {
          tags: { type: 'API' },
        });
      
        const responses = http.batch([
          ['GET', 'https://test-api.k6.io/static/favicon.ico', null, { tags: { type: 'staticContent' } }],
          [
            'GET',
            'https://test-api.k6.io/static/css/site.css',
            null,
            { tags: { type: 'staticContent' } },
          ],
        ]);
      
        sleep(1);
      }


      Threshold 를 벗어나면 테스트 중지하기

      • 스레시홀드를 넘어서는 경우 테스트를 중지하고자 한다면 abortOnFail 속성을 true로 둔다.

      • abortOnFail 를 지정하면 threshold 가 실패하면 바로 종료한다.

      • 가끔 임계값을 넘어 테스트가 중요한 데이터를 생성하기 전에 중단될 수 있다.

      • 이러한 현상을 막기 위해서 delayAbortEval을 사용하여 abortOnFail 을 지연할 수 있다.

      • 이 스크립트에서 abortOnFail 은 10초 지연된다.

      • 10초후 테스트가 p(99) < 10 임계값을 실패하면 테스트가 중단되는 예제이다.

      export const options = {
        thresholds: {
          metric_name: [
            {
              threshold: 'p(99) < 10', // string
              abortOnFail: true, // boolean
              delayAbortEval: '10s', // string
              /*...*/
            },
          ],
        },
      };

      Name

      Type

      Description

      threshold

      string

      임계값 표현식이다. 검증할 식을 기술한다.

      abortOnFail

      boolean

      테스트중에 임계값을 넘어서면 abort 할지 여부 true인경우 동작한다.

      delayAboutEval

      string

      만약 종료하기 전에 특정 메트릭 샘플을 수집해야하는경우 종료 시점을 딜레이 할 수 있다.

      • 다음은 샘플 예제이다.

      import http from 'k6/http';
      
      export const options = {
        vus: 30,
        duration: '2m',
        thresholds: {
          http_req_duration: [{ threshold: 'p(99) < 10', abortOnFail: true }],
        },
      };
      
      export default function () {
        http.get('https://test-api.k6.io/public/crocodiles/1/');
      }
      • k6가 k6클라우드에서 실행될 때 임계값은 60초마다 평가된다.

      • 따라서 abortOnFail 기능은 최대 60초까지 지연될 수 있다.


      Checks 를 이용하여 로드 테스트 실패하기

      • check는 검증을 코드로 수행하기 좋은 도구이다.

      • check는 thresholds와는 다르게 종료조건으로 사용되지 않는다.

      • 만약 checks만 이용하여 검증을 하면, 전체 테스트를 종료할 수 없다.

      • checks와 thresholds를 조합하여 사용한다.

      import http from 'k6/http';
      import { check, sleep } from 'k6';
      
      export const options = {
        vus: 50,
        duration: '10s',
        thresholds: {
          // the rate of successful checks should be higher than 90%
          checks: ['rate>0.9'],
        },
      };
      
      export default function () {
        const res = http.get('http://httpbin.test.k6.io');
      
        check(res, {
          'status is 500': (r) => r.status == 500,
        });
      
        sleep(1);
      }
      • 이 예제에서 threshold는 checks 메트릭에 설정된다.

      • 성공율이 90% 이상인경우로 설정했다.

      • 추가적으로 tags를 체크에 이용할 수 있다. 만약 특정 체크나 체크그룹에 임계를 지정할 수 있다.

      import http from 'k6/http';
      import { check, sleep } from 'k6';
      
      export const options = {
        vus: 50,
        duration: '10s',
        thresholds: {
          'checks{myTag:hola}': ['rate>0.9'],
        },
      };
      
      export default function () {
        let res;
      
        res = http.get('http://httpbin.test.k6.io');
        check(res, {
          'status is 500': (r) => r.status == 500,
        });
      
        res = http.get('http://httpbin.test.k6.io');
        check(
          res,
          {
            'status is 200': (r) => r.status == 200,
          },
          { myTag: 'hola' }
        );
      
        sleep(1);
      }

      from: https://k6.io/docs/using-k6/thresholds/


      Wrap Up

      • 지금까지 check와 thresholds 를 알아보았다.

      • check는 검증이 성공했는지 / 실패했는지를 검사하고, 실패했다고 해서 테스트가 바로 종료되지는 않는다.

      • thresholds 는 검증을 성공하면 계속해서 테스트가 수행되며, 실패하면 테스트를 바로 종료한다.

      • check와 thresholds를 함께 이용하여 검증을 수행할 수 있다.

      • 또한 threshold 에서 실패인경우에도 계속해서 테스트할지 여부도 설정할 수 있다는 것을 알게 되었다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      KIDO 님의 최신 블로그

      더보기
      동영상 기고하기