Grafana K6는 성능 테스트를 위해 설계된 오픈 소스 도구입니다. 대규모 API, 마이크로서비스 및 웹사이트를 테스트하고 개발자와 테스터에게 시스템 성능에 대한 통찰력을 제공하는 데 적합합니다. 이 치트 시트에서는 모든 성능 엔지니어가 Grafana K6을 시작하기 위해 알아야 할 주요 측면을 다룹니다.
Grafana K6는 성능 테스트를 간단하고 확장 가능하며 CI 파이프라인에 쉽게 통합할 수 있게 해주는 개발자와 테스터를 위한 최신 로드 테스트 도구입니다.
Homebrew 또는 Docker를 통해 Grafana K6 설치:
brew install k6 # Or with Docker docker run -i grafana/k6 run - <script.js
공개 REST API를 사용하여 간단한 테스트를 실행하는 방법은 다음과 같습니다.
import http from "k6/http"; import { check, sleep } from "k6"; // Define the API endpoint and expected response export default function () { const res = http.get("https://jsonplaceholder.typicode.com/posts/1"); // Define the expected response const expectedResponse = { userId: 1, id: 1, title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto", }; // Assert the response is as expected check(res, { "status is 200": (r) => r.status === 200, "response is correct": (r) => JSON.stringify(JSON.parse(r.body)) === JSON.stringify(expectedResponse), }); sleep(1); }
테스트를 실행하고 웹 대시보드에서 결과를 보려면 다음 명령을 사용할 수 있습니다.
K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=html-report.html k6 run ./src/rest/jsonplaceholder-api-rest.js
이렇게 하면 보고서 폴더에 html-report.html이라는 이름의 보고서가 생성됩니다.
그러나 다음 URL에 액세스하여 웹 대시보드에서 결과를 볼 수도 있습니다.
http://127.0.0.1:5665/
URL에 접속하면 웹 대시보드에서 실시간으로 테스트 결과를 확인할 수 있습니다.
공개 GraphQL API를 사용한 예
GraphQL API가 무엇인지 모르는 경우 다음 URL을 방문하세요: GraphQL이란 무엇입니까?
우리가 사용할 GraphQL API에 대한 자세한 내용은 다음 URL의 설명서를 참조하세요: GraphQL Pokémon.
GraphQL API를 테스트하는 방법에 대한 자세한 내용을 보려면 GraphQL 테스트 URL을 방문하세요.
포켓몬 이름을 불러와 반응 성공 여부를 확인하는 간단한 테스트입니다.
import http from "k6/http"; import { check } from "k6"; // Define the query and variables const query = ` query getPokemon($name: String!) { pokemon(name: $name) { id name types } }`; const variables = { name: "pikachu", }; // Define the test function export default function () { const url = "https://graphql-pokemon2.vercel.app/"; const payload = JSON.stringify({ query: query, variables: variables, }); // Define the headers const headers = { "Content-Type": "application/json", }; // Make the request const res = http.post(url, payload, { headers: headers }); // Define the expected response const expectedResponse = { data: { pokemon: { id: "UG9rZW1vbjowMjU=", name: "Pikachu", types: ["Electric"], }, }, }; // Assert the response is as expected check(res, { "status is 200": (r) => r.status === 200, "response is correct": (r) => JSON.stringify(JSON.parse(r.body)) === JSON.stringify(expectedResponse), }); }
성능 임계값, 가상 사용자(VU) 수, 기간 등의 전역 구성 옵션을 한곳에서 정의하여 쉽게 수정할 수 있습니다.
brew install k6 # Or with Docker docker run -i grafana/k6 run - <script.js
코드를 재사용 가능한 모듈로 분리합니다. 예를 들어 테스트 로직에서 상수와 요청을 분리합니다.
REST API 예에서는 상수.js 파일을 생성하여 API의 기본 URL을 저장하고, request-jsonplaceholder.js 파일을 생성하여 API와 상호작용하는 함수를 저장할 수 있습니다.
import http from "k6/http"; import { check, sleep } from "k6"; // Define the API endpoint and expected response export default function () { const res = http.get("https://jsonplaceholder.typicode.com/posts/1"); // Define the expected response const expectedResponse = { userId: 1, id: 1, title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto", }; // Assert the response is as expected check(res, { "status is 200": (r) => r.status === 200, "response is correct": (r) => JSON.stringify(JSON.parse(r.body)) === JSON.stringify(expectedResponse), }); sleep(1); }
이제 API와 상호작용하기 위한 함수를 저장하는 요청-jsonplaceholder.js 파일을 생성할 수 있습니다.
K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=html-report.html k6 run ./src/rest/jsonplaceholder-api-rest.js
마지막으로 테스트 스크립트 jsonplaceholder-api-rest.js를 생성하여 request-jsonplaceholder.js 파일에서 생성한 함수를 사용할 수 있습니다.
http://127.0.0.1:5665/
이제 스크립트 코드는 이해하기가 훨씬 더 간단해졌으며, URL, 매개변수에 변경사항이 있거나 새로운 메소드를 추가해야 하는 경우 변경이 필요한 위치가 중앙 집중화되어 솔루션 확장이 더 간단해졌습니다. 시간이 지나면서.
필요한 경우 나중에 더 복잡한 시나리오를 만들기 위해 재사용할 수 있는 더 많은 원자 함수를 생성하여 스크립트를 더욱 개선할 수 있으며, 테스트 스크립트의 기능을 이해하는 것이 점점 더 간단해지고 있습니다. 예를 들어 게시물의 존재를 테스트하려는 경우 게시물을 가져오고 응답을 반환하는 함수를 만든 다음 테스트 스크립트 jsonplaceholder-api-rest.js에서 이 함수를 사용할 수 있습니다.
import http from "k6/http"; import { check } from "k6"; // Define the query and variables const query = ` query getPokemon($name: String!) { pokemon(name: $name) { id name types } }`; const variables = { name: "pikachu", }; // Define the test function export default function () { const url = "https://graphql-pokemon2.vercel.app/"; const payload = JSON.stringify({ query: query, variables: variables, }); // Define the headers const headers = { "Content-Type": "application/json", }; // Make the request const res = http.post(url, payload, { headers: headers }); // Define the expected response const expectedResponse = { data: { pokemon: { id: "UG9rZW1vbjowMjU=", name: "Pikachu", types: ["Electric"], }, }, }; // Assert the response is as expected check(res, { "status is 200": (r) => r.status === 200, "response is correct": (r) => JSON.stringify(JSON.parse(r.body)) === JSON.stringify(expectedResponse), }); }
constants.js 파일을 수정하여 GraphQL API의 기본 URL과 사용해야 하는 헤더를 추가할 수 있습니다.
// ./src/config/options.js export const options = { stages: [ { duration: '1m', target: 100 }, // ramp up to 100 VUs { duration: '5m', target: 100 }, // stay at 100 VUs for 5 mins { duration: '1m', target: 0 }, // ramp down ], thresholds: { http_req_duration: ['p(95)<500'], // 95% of requests should complete in under 500ms }, };
이제 GraphQL API와 상호작용하기 위한 함수를 저장하기 위해 request-graphql-pokemon.js 파일을 생성할 수 있습니다.
// ./src/utils/constants.js export const BASE_URLS = { REST_API: 'https://jsonplaceholder.typicode.com', };
이제 request-graphql-pokemon.js 파일에서 생성한 함수를 사용하는 테스트 스크립트를 생성할 수 있습니다. 포켓몬의 데이터를 가져와서 응답이 성공적인지 확인하는 간단한 테스트 스크립트를 만들어 보겠습니다.
// ./src/utils/requests-jsonplaceholder.js import { BASE_URLS } from './constants.js'; import http from 'k6/http'; export function getPosts() { return http.get(`${BASE_URLS.REST_API}/posts`); } export function getPost(id) { return http.get(`${BASE_URLS.REST_API}/posts/${id}`); } export function createPost(post) { return http.post(`${BASE_URLS.REST_API}/posts`, post); } export function updatePost(id, post) { return http.put(`${BASE_URLS.REST_API}/posts/${id}`, post); } export function deletePost(id) { return http.del(`${BASE_URLS.REST_API}/posts/${id}`); }
API Rest의 예와 마찬가지로, 필요한 경우 나중에 더 복잡한 시나리오를 생성하기 위해 재사용할 수 있는 더 많은 원자 함수를 생성하여 스크립트를 개선할 수 있습니다. 테스트 스크립트가 무엇인지 이해하는 것이 점점 더 쉬워지고 있습니다. 그렇습니다.
응답과 요청 결과를 최적화하고 더 나은 매개변수화할 수 있는 더 나은 방법이 아직 남아 있습니다. 우리가 무엇을 할 수 있다고 생각하시나요?
동적 데이터를 사용하여 보다 현실적인 시나리오를 시뮬레이션하고 다양한 데이터 세트를 로드하세요. K6을 사용하면 공유 배열을 사용하여 파일에서 데이터를 로드할 수 있습니다. 공유 어레이는 모든 VU에서 액세스할 수 있는 데이터를 저장하는 방법입니다.
users-config.js 파일을 생성하여 JSON 파일 users.json에서 사용자 데이터를 로드할 수 있습니다.
brew install k6 # Or with Docker docker run -i grafana/k6 run - <script.js
import http from "k6/http"; import { check, sleep } from "k6"; // Define the API endpoint and expected response export default function () { const res = http.get("https://jsonplaceholder.typicode.com/posts/1"); // Define the expected response const expectedResponse = { userId: 1, id: 1, title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto", }; // Assert the response is as expected check(res, { "status is 200": (r) => r.status === 200, "response is correct": (r) => JSON.stringify(JSON.parse(r.body)) === JSON.stringify(expectedResponse), }); sleep(1); }
그런 다음 테스트 스크립트 jsonplaceholder-api-rest.js에서 사용할 수 있습니다.
K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=html-report.html k6 run ./src/rest/jsonplaceholder-api-rest.js
잘 구성된 프로젝트 구조는 테스트를 유지 관리하고 확장하는 데 도움이 됩니다. 권장되는 폴더 구조는 다음과 같습니다.
http://127.0.0.1:5665/
이 구조는 프로젝트 루트를 복잡하게 만들지 않고 프로젝트를 정리하고 확장 가능하며 유지 관리하기 쉽게 유지하는 데 도움이 됩니다.
또 다른 옵션은 테스트 스크립트를 기능별로 폴더로 그룹화하는 것입니다. 그러면 상황에 가장 적합한 것을 테스트하고 비교할 수 있습니다. 예를 들어, 거래를 수행하는 지갑에 관한 프로젝트의 경우 각 거래 유형(예금, 출금, 이체 등)에 대한 폴더를 가질 수 있으며 각 폴더 안에 해당 특정 거래에 대한 테스트 스크립트를 가질 수 있습니다.
import http from "k6/http"; import { check } from "k6"; // Define the query and variables const query = ` query getPokemon($name: String!) { pokemon(name: $name) { id name types } }`; const variables = { name: "pikachu", }; // Define the test function export default function () { const url = "https://graphql-pokemon2.vercel.app/"; const payload = JSON.stringify({ query: query, variables: variables, }); // Define the headers const headers = { "Content-Type": "application/json", }; // Make the request const res = http.post(url, payload, { headers: headers }); // Define the expected response const expectedResponse = { data: { pokemon: { id: "UG9rZW1vbjowMjU=", name: "Pikachu", types: ["Electric"], }, }, }; // Assert the response is as expected check(res, { "status is 200": (r) => r.status === 200, "response is correct": (r) => JSON.stringify(JSON.parse(r.body)) === JSON.stringify(expectedResponse), }); }
이 두 번째 예에서는 데이터 구조가 더 복잡하지만 첫 번째 예에서 생성한 것과 동일한 요청 함수를 계속 재사용할 수 있습니다.
K6을 사용한 성능 테스트는 병목 현상을 식별하고 애플리케이션 확장성을 보장하는 데 매우 중요합니다. 코드 모듈화, 구성 중앙 집중화, 동적 데이터 사용 등의 모범 사례를 따르면 엔지니어는 유지 관리 및 확장이 가능한 성능 테스트 스크립트를 만들 수 있습니다.
큰 포옹.
찰리 오토마티자
위 내용은 Grafana Kheat 시트: 성능 엔지니어가 알아야 할 모든 것의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!