ãã®èšäºã¯ããªã¬ãŒããã°äŒç»ã24æ°åãªã¬ãŒããã°ãã®èšäºã§ãã ã¯ããã« ããã«ã¡ã¯ã åããŸããŠãæ°å1幎ç®ã®ãã«ã§ãã çŸåšOJTæé㧠課éã·ã¹ãã ããŒã ã«æå±ããŠããã瀟å
åãã®APIã®éçºã«æºãã£ãŠããŸãããã®APIã«å¯ŸããŠè² è·ãã¹ããè¡ãã«ããããããŒã å
ã§è² è·ãã¹ãããŒã«ãšããŠk6ãæ¡çšãããšãã話ã«ãªããŸããã k6ã¯ç°¡åã«ãã¹ãã·ããªãªãæžããããŒã«ã§ãããªãããéåžžã«åŒ·åãªè² è·ãã¹ããå®è¡ããããšãã§ããŸããæ¬èšäºã§ã¯ããã®k6ã«ã€ããŠåºæ¬çãªäœ¿ãæ¹ããinfluxDBãšGrafanaãçšããçµæã®å¯èŠåæ¹æ³ãŸã§ã調ã¹ãå
容ã«ã€ããŠèªåã®çè§£ã®æŽçãå«ããŠèšäºã«ããããšæããŸãã è² è·ãã¹ããè¡ãçç± çŸåšã®APIéçºã«ãããŠããŠãŒã¶ãŒæ°ã®æ¥æ¿ãªå¢å ãäºæããªããã©ãã£ãã¯ã®éäžãèµ·ããããšãæ³å®ãããããç¶æ³äžã«ãããŠãã·ã¹ãã ãå®å®ããŠæ©èœããããšãæ±ããããŸãããã®ãããããã©ãŒãã³ã¹ã®æ€èšŒãéçå€ã®æž¬å®ããªãœãŒã¹äœ¿çšç¶æ³ã®ææ¡ãªã©ã察象ã®ã·ã¹ãã ã®å質ãä¿¡é Œæ§ããªãœãŒã¹ã®æé©åãªã©ãç®çãšããè² è·ãã¹ãã¯éåžžã«éèŠãªåœ¹å²ãæã¡ãŸãã ä»åç§éã®ããŒã ã§ã¯ãéçºããAPIãå®çšã«èãããæ§æãšãªã£ãŠããã®ãã«ã€ããŠå®éã®ã¢ã¯ã»ã¹æ°ãå
ã«ç¢ºèªããããšãäž»ãªç®çãšããŠãã¹ãã€ã¯ãã¹ããšã¹ãã¬ã¹ãã¹ããè¡ããŸããã æ³å®ãããç¯å²ã§æ¥æ¿ãªè² è·ã®äžæãèµ·ãããšããŠãæ³å®éãã®é床ãåºããã æ³å®ããã以äžã®é«è² è·ãããã£ãå Žåã§ãAPIã¯æ£åžžã«åãååãªã¬ã¹ãã³ã¹é床ãåºãããšãã§ããã é·æéè² è·ãããã£ãå Žåã«ã©ã®ãããªæåãããã®ã ãªã©ã§ãããŸããè² è·ãã¹ããå®è¡ããéã« CPUãã¡ã¢ãªãªã©ã®ãªãœãŒã¹ã¯çŸåšã®æ§æã§é©åãªãã®ã«ãªã£ãŠããã API / ãµãŒããŒã®èšå®ã¯é©åãªãã®ã«ãªã£ãŠããã ã«ã€ããŠã確èªãè¡ããŸããã ãããã«ãããã·ã¹ãã ã®éçå€ãæœåšçãªåé¡ç¹ãäºåã«ææ¡ãå¿
èŠãªå¯Ÿçãè¬ããããšã§ãã·ã¹ãã ã®å質ãšä¿¡é Œæ§ãåäžãããŠãŒã¶ãŒæºè¶³åºŠãé«ããããšã«ç¹ãããŸãã ããŒã«ã®éžå® è² è·ãã¹ããè¡ãããšãã§ããããŒã«ã¯æ§ã
ãããŸãã ãããã®ãã¡ãç¡æã§å©çšã§ãã7ã€ãæ¯èŒããŠã¿ãŸãã ããŒã«å å
¬åŒ ã·ããªãªèšè¿°èšèª çµæç¢ºèª æ¹æ³ 詳现 k6 k6.io , github JavaScript grafana / CUI / Cloud Golangã§éçºãããé«è² è·ç°å¢ã§ãã¹ã ãŒãºã«åäœãæ¡åŒµæ§ãé«ã Apache Bench apache.org CLI CUI åäžã®URLãžã®ãªã¯ãšã¹ããçæããããŒã«ã®ãããã·ããªãªããŒã¹ã§Webã¢ããªã±ãŒã·ã§ã³ããã¹ãããããšã«ã¯åããŠããªã Apache JMeter jmeter.apache.org , github GUI / Java GUI æ¡åŒµæ§ãé«ããçµæå¯èŠåæ¹æ³ãè±å¯ Tsung tsung , github XML tsung-recorder Erlangèšèªã§éçºãããããŒã¿ããŒã¹ãã¡ãã»ãŒãžã³ã°ã·ã¹ãã ã®ãã¹ããè¡ãã Gatling gatling.io , github Scala .html JavaVMäžã§åäœ Vegeta vegeta , github Golang .html / plotã³ãã³ã åææ¥ç¶æ°ããªã¯ãšã¹ãã¬ãŒãã®è©³çްãªå¶åŸ¡ãå¯èœ Locust locust.io , github Python webãµãŒã ã¹ã±ãŒã©ãã«ã§ã忣å®è¡ãå¯èœ è² è·ãã¹ãããŒã«ã®æ¯èŒ ç§éã®ããŒã ã§ã¯ã䞻㫠Python ã䜿çšããŠããããšãã Locust ãšãä»åŸããŒã å
ã«å°å
¥ããã«ããã£ãŠåŠç¿ã³ã¹ããäœã JavaScript ã§èšè¿°ã§ããçŸåšãçãã«éçºãè¡ãããŠãã k6 ãéžæè¢ã«äžãããŸããããããã®å
ãOSSã§ã¢ããããŒããçãã«è¡ãããŠããããæ°ããæè¡ã«å¯Ÿå¿å¯èœã§ããç¹ããã k6 ãæ¡çšããããšã«ããŸããã å®è¡ç°å¢ æºå ä»åã¯ä»¥äžã®GrafanaãçšæããŠãã k6ã®ãªããžã㪠ã䜿çšããŸãã k6ã§è¡ã£ãè² è·ãã¹ãçµæãinfluxDBã«ä¿åããGrafanaãçšããŠå¯èŠåããŸãã # clone git clone https://github.com/grafana/xk6-output-influxdb.git ãšã³ããã€ã³ãã«ã€ããŠã¯ãä»å㯠ãã¡ã ã䜿ããŸãã ããã¯ã k6 ã®å®éšçšHTTPã WebSocket API ã®ã³ã¬ã¯ã·ã§ã³ãšãªã£ãŠããŸãã ãã®ãã¡ https://test-api.k6.io/public/crocodiles/{id} ã«å¯ŸããŠè² è·ãã¹ããè¡ããŸãã æ³šæç¹ãšããŠãããã¯å
±æãã¹ãç°å¢ã§ããããé«è² è·ãã¹ãã¯é¿ããå¿
èŠããããŸãã APIã®æå curlã³ãã³ããçšããŠäžåºŠAPIãå©ããŠã¿ãŸãã å©ãããšãã§ããidã®äžèЧã¯ä»¥äžã®çµæã®ãšããã§ãã curl https://test-api.k6.io/public/crocodiles/ [ { "id": 1, "name": "Bert", "sex": "M", "date_of_birth": "2010-06-27", "age": 14 }, { "id": 2, "name": "Ed", "sex": "M", "date_of_birth": "1995-02-27", "age": 29 }, { "id": 3, "name": "Lyle the Crocodile", "sex": "M", "date_of_birth": "1985-03-03", "age": 39 }, { "id": 4, "name": "Solomon", "sex": "M", "date_of_birth": "1993-12-25", "age": 30 }, { "id": 5, "name": "The gharial", "sex": "F", "date_of_birth": "2004-06-28", "age": 20 }, { "id": 6, "name": "Sang Buaya", "sex": "F", "date_of_birth": "2006-01-28", "age": 18 }, { "id": 7, "name": "Sobek", "sex": "F", "date_of_birth": "1854-09-02", "age": 169 }, { "id": 8, "name": "Curious George", "sex": "M", "date_of_birth": "1981-01-03", "age": 43 } ] ãããå
ã«å¯Ÿè±¡ã®APIãå©ããŠã¿ãŸããè¿åŽå€ã¯ä»¥äžã®ããã«ãªã£ãŠããŸãã curl https://test-api.k6.io/public/crocodiles/1/ { "id": 1, "name": "Bert", "sex": "M", "date_of_birth": "2010-06-27", "age": 14 } ãããã·èšå®ã®å€æŽ æ¬ãªããžããªã§ã¯ã k6 â influxdb â grafana ã®é ã«ããŒã¿ãéãããŸãã ã³ã³ããéã®éä¿¡ãçºçããããã ~/.docker/config.json ã«proxyãèšå®ãããŠãããš503ãšã©ãŒãšãªãå¯èœæ§ããããŸãããã®ãããèšå®ãããŠãã人ã¯ä¿®æ£ãå¿
èŠã«ãªããŸãã ã·ããªãª ã·ããªãªã®éžå® æ¡ä»¶æ¯ã«ãå¿
èŠãªã·ããªãªã«å¿ããŠãã¿ãŒã³ãèããå¿
èŠããããŸãã ç¹ã«Grafanaã§ã¯ãè² è·ãã¹ãã®çš®é¡ã6ã€æããŠããŸãã( åè ãã¹ãå æé å
容 Smoke test æ°åãæ°ç§ããã æå°éã®è² è·ã§ã·ã¹ãã ã®æ©èœãæ€èšŒããåºæºãšãªãããã©ãŒãã³ã¹å€ãåéãããã¹ã Average-load test äžïŒ5ã60åïŒ æšæºçãªè² è·äžã§ã·ã¹ãã ãã©ã®ããã«åäœããããè©äŸ¡ãããã¹ã Stress test äžïŒ5ã60åïŒ ãã©ãã£ãã¯ã®ããŒã¯æã®è² è·ã§ã·ã¹ãã ãã©ã®ããã«æ©èœãããã調ã¹ããã¹ã Spike test é·æé çªç¶ã®äœ¿çšç¶æ³ã®æ¥å¢ã«å¯ŸããŠã·ã¹ãã ãèããŠæ©èœãããã©ãããæ€èšŒãããã¹ã Breakpoint test æ°å ã·ã¹ãã ã®éçãèšæž¬ããããã«è¡ããã¹ã Soak test å¿
èŠãªéã æ°æéããæ°æ¥ã®é·æéè¡ãå¹³åè² è·ãã¹ã è² è·ãã¹ãã®ã·ããªãªäŸ ã·ããªãªã®å®è£
k6 ãã¹ã ã¹ã¯ãªããã§ã¯ã load_test.js å
ã® options ãªããžã§ã¯ãã䜿çšããŠã·ããªãªãæ§æã§ããŸãã åã·ããªãªã«ã¯äžæã®ååãä»ãã executor ã¿ã€ããšãã®æ§æãæå®ããå¿
èŠããããŸãã export const options = { scenarios: { spike: { executor: "ramping-vus", startVUs: 0, stages: [ { duration: "5m", target: 100 }, { duration: "2m", target: 0 }, ], }, stress: { executor: "constant-vus", vus: 50, duration: "10m", }, }, }; äžèšã¯ãã¹ãã€ã¯ãã¹ããšã¹ãã¬ã¹ãã¹ãã®äŸã§ãã ã¹ãã€ã¯ãã¹ã ramping-vus executor ãäœ¿çš ä»®æ³ãŠãŒã¶ãŒã®ç§éã¢ã¯ã»ã¹æ°ã5åæã㊠0 ãã 100 ãŸã§åŸã
ã«å¢ããã2åæã㊠0 ãŸã§æžãããŠãã ã¹ãã¬ã¹ãã¹ã constant-vus executor ãäœ¿çš 10 åéãç§é50åã®ä»®æ³ãŠãŒã¶ãŒããã®ã¢ã¯ã»ã¹ãä¿ã£ãŠãã ã·ããªãªãè€æ°æå®ããŠããå Žåãäžããé ã«å®è¡ãããŸãã executorã«ã¯ä»ã«ãçš®é¡ããããããããèšè¿°æ¹æ³ãç°ãªããŸãã åèïŒ https://k6.io/docs/using-k6/scenarios/executors/#all-executors è² è·ãã¹ãã®å®è¡ ä»åã¯äžèšã®ãã¡ãã¹ãã¬ã¹ãã¹ããšã¹ãã€ã¯ãã¹ããè¡ã£ãŠã¿ãŸãã å®è¡ã³ãŒã import http from 'k6/http'; // ã¹ãã€ã¯ãã¹ãã®èšå® export const options = { scenarios: { // ã¹ãã€ã¯ãã¹ã // çæéã§äžæ°ã«è² è·ãäžæããå Žåã®è² è·ãã¹ã spike: { executor: 'ramping-vus', startVUs: 0, stages: [ { duration: '2s', target: 10 }, { duration: '1m', target: 0 }, ], }, // ã¹ãã¬ã¹ãã¹ã // çæéã§äžæ°ã«è² è·ãäžæããå Žåã®è² è·ãã¹ã stress: { executor: "constant-vus", vus: 50, duration: "10m", }, }, }; export default function () { // APIãªã¯ãšã¹ããéä¿¡ const id = Math.floor(Math.random() * 8); const response = http.get(`https://test-api.k6.io/public/crocodiles/${id}`, { tags: { "id": id, "all": "all" }ã// Grafana衚瀺çšã«ã¿ã°ãèšå® }); // ã¬ã¹ãã³ã¹ããã§ã㯠console.log(`VU: ${__VU}, Iteration: ${__ITER}, ID: ${id}, Status: ${response.status}`); } # ã³ã³ããã®èµ·å ## k6以å€ãç«ã¡äžãã docker compose up influxdb grafana -d # ãã¹ãå®è¡ docker compose run --rm -T k6 run - < samples/load_test.js èµ·åç»é¢ çµæã®ç¢ºèª 1. k6 å®è¡çµæ 確èªã§ããã¡ããªã¯ã¹ã¯ä»¥äžã®éãã«ãªããŸãã ã¡ããªã¯ã¹å 説æ data_received åä¿¡ããããŒã¿é data_sent éä¿¡ãããããŒã¿é http_req_blocked ãªã¯ãšã¹ããéå§ãããŸã§ã«ãããã¯ãããæé http_req_connecting ãªã¢ãŒããã¹ããšã®TCPã³ãã¯ã·ã§ã³ã®ç¢ºç«ã«ããã£ãæé http_req_duration ãªã¯ãšã¹ããéã£ãŠããåž°ã£ãŠãããŸã§ã®æé ( http_req_sending + http_req_waiting + http_req_receiving ) http_req_failed ãªã¯ãšã¹ãã«å€±æããæ° http_req_receiving ãªã¢ãŒããã¹ãããã®å¿çããŒã¿åä¿¡ã«ããã£ãæé http_req_sending ãªã¢ãŒããã¹ããžã®ããŒã¿éä¿¡ã«ããã£ãæé http_req_tls_handshaking ãªã¢ãŒããã¹ããšã®TLSã»ãã·ã§ã³ã®ãã³ãã·ã§ã€ã¯ã«ããã£ãæé http_req_waiting ãªã¢ãŒããã¹ãããã®å¿çåŸ
ã¡æé http_reqs çæãã HTTP ãªã¯ãšã¹ãã®åèšæ° iteration_duration ïŒåã®ã€ãã¬ãŒã·ã§ã³ã®å®è¡ã«èŠããæé iterations virtual usersãå®è¡ããããã©ã«ã颿°ã®åæ° vus virtual usersãåæã«ã¢ã¯ã»ã¹ããä»®æ³ãŠãŒã¶ãŒæ° vus_max ä»®æ³ãŠãŒã¶ãŒã®æå€§å¯èœæ° 確èªã§ããã¡ããªã¯ã¹ã®äžèЧ ç¹ã«ç¢ºèªããå¿
èŠãããã®ã¯ http_req_duration , http_reqs , http_req_failed ã®3ã€ã§ãã ãªã¯ãšã¹ãã«ããã£ãæéããªã¯ãšã¹ãã®æ°ã倱æããæ°ã§ãã ãã®çµæããããã®APIã®ã¬ã¹ãã³ã¹é床ã¯çŽ200msçšåºŠã§ãããã»ãšãã©ã®å Žåã«æŒããŠãã®é床ãåºããŠããããšãããããŸãã å¹³åå€ æå°å€ äžå€®å€ æå€§å€ 90ããŒã»ã³ ã¿ã€ã« 95ããŒã»ã³ ã¿ã€ã« æåæ° å€±ææ° 203.49ms 176.55ms 200.83ms 1.21s 216.69ms 223.42ms 3112å 0å å®è¡çµæ 2. grafana ã³ã³ãããç«ã¡äžããéã«ç«ã¡äžãã£ãŠããããããã¡ãã«ã¢ã¯ã»ã¹ããŸãã ã¢ã¯ã»ã¹å
ïŒ http://localhost:3000/dashboards ããã§ã¯çµæãåããã«ãããããå¡äŸãšã¯ãšãªãä¿®æ£ããŸãã ä¿®æ£å
ïŒ grafana/dashboards/xk6-output-influxdb-dashboard.json ïž ä¿®æ£ã³ãŒã { "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "target": { "limit": 100, "matchAny": false, "tags": [], "type": "dashboard" }, "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "gnetId": null, "graphTooltip": 1, "iteration": 1677877089957, "links": [], "liveNow": false, "panels": [ { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 0, "y": 0 }, "id": 2, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "8.2.6", "targets": [ { "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)n |> filter(fn: (r) => r["_measurement"] == "http_reqs")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r["_field"] == "value")n |> group(columns: ["_measurement"])n |> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: false)n |> yield(name: "sum")", "refId": "EACH" } ], "title": "Requests Made", "type": "stat" }, { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 1 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 4, "y": 0 }, "id": 12, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "8.2.6", "targets": [ { "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)n |> filter(fn: (r) => r["_measurement"] == "http_req_failed")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r["_field"] == "value")n |> group(columns: ["_measurement"])n |> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: false)n |> yield(name: "sum")", "refId": "EACH" } ], "title": "HTTP Failures", "type": "stat" }, { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 8, "y": 0 }, "id": 13, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "max" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "8.2.6", "targets": [ { "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)n |> filter(fn: (r) => r["_measurement"] == "http_reqs")n |> filter(fn: (r) => r["_field"] == "value")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> group()n |> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: false)", "refId": "EACH" } ], "title": "Peak RPS", "type": "stat" }, { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 12, "y": 0 }, "id": 14, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "8.2.6", "targets": [ { "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)n |> filter(fn: (r) => r._measurement == "http_req_duration")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r._field == "value")n |> group()n |> quantile(q: 0.95, method: "exact_mean")", "refId": "EACH" } ], "title": "P95 Response Time", "type": "stat" }, { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 16, "y": 0 }, "id": 15, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "8.2.6", "targets": [ { "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)n |> filter(fn: (r) => r._measurement == "data_received")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r._field == "value")n |> group()n |> sum()", "refId": "EACH" } ], "title": "Data Received", "type": "stat" }, { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 20, "y": 0 }, "id": 16, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "8.2.6", "targets": [ { "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)n |> filter(fn: (r) => r._measurement == "data_sent")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r._field == "value")n |> group()n |> sum()", "refId": "EACH" } ], "title": "Data Sent", "type": "stat" }, { "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisLabel": "", "axisPlacement": "left", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "EACH", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "displayName": "${__field.labels.id}", "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "VUS" }, "properties": [ { "id": "displayName", "value": "Active VUs" }, { "id": "custom.lineStyle", "value": { "dash": [ 10, 10 ], "fill": "dash" } }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "RPS" }, "properties": [ { "id": "displayName", "value": "RPS" } ] }, { "matcher": { "id": "byFrameRefID", "options": "EACH" }, "properties": [ { "id": "unit", "value": "ms" }, { "id": "custom.axisPlacement", "value": "right" } ] }, { "matcher": { "id": "byFrameRefID", "options": "ALL" }, "properties": [ { "id": "unit", "value": "ms" }, { "id": "displayName", "value": "ALL" } ] } ] }, "gridPos": { "h": 11, "w": 24, "x": 0, "y": 4 }, "id": 11, "options": { "legend": { "calcs": [ "min", "mean", "max", "lastNotNull" ], "displayMode": "table", "placement": "bottom" }, "tooltip": { "mode": "multi" } }, "pluginVersion": "8.3.1", "targets": [ { "hide": false, "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)n |> filter(fn: (r) => r._measurement == "http_req_duration")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r._field == "value")n |> filter(fn: (r) => r.status == "200")n |> group(columns: ["all"], mode:"by")n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)n |> yield(name: "mean")n", "refId": "ALL" }, { "hide": false, "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)n |> filter(fn: (r) => r._measurement == "http_req_duration")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r._field == "value")n |> filter(fn: (r) => r.status == "200")n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)n |> yield(name: "mean")", "refId": "EACH" }, { "hide": false, "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)n |> filter(fn: (r) => r["_measurement"] == "vus")", "refId": "VUS" }, { "hide": false, "query": "from(bucket: v.defaultBucket)n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)n |> filter(fn: (r) => r["_measurement"] == "http_reqs")n |> filter(fn: (r) => r["testid"] =~ /${testid:regex}/)n |> filter(fn: (r) => r["_field"] == "value")n |> group(columns: ["_measurement"])n |> aggregateWindow(every: 1s, fn: sum, createEmpty: false)n |> yield(name: "sum")", "refId": "RPS" } ], "type": "timeseries" } ], "refresh": false, "schemaVersion": 32, "style": "dark", "tags": [], "templating": { "list": [ { "allValue": null, "current": { "selected": false, "text": "All", "value": "$__all" }, "datasource": null, "definition": "import "influxdata/influxdb/schema"nschema.tagValues(bucket: v.defaultBucket, tag: "testid")", "description": null, "error": null, "hide": 0, "includeAll": true, "label": null, "multi": false, "name": "testid", "options": [], "query": "import "influxdata/influxdb/schema"nschema.tagValues(bucket: v.defaultBucket, tag: "testid")", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "K6 Test Results", "uid": "4sk8QaJVx", "version": 1 } ä¿®æ£åŸçµæ å¡äŸãIDæ¯ã«èšå®ããããšã§ãåIDã®ã¬ã¹ãã³ã¹é床ãå¯èŠåã§ããããã«ãªããŸããã å¡äŸå æŠèŠ ALL å
šIDå¹³åã®çµ±èšå€ (ã¯ãšãªã远å ) åID (ã¿ã°ã§å€æŽå¯èœ) (å¡äŸãä¿®æ£) 察象IDã®çµ±èšå€ Active VUs (Virtual Users) åããVirtual Users ã®æ° RPS (Requests Per Second) 1ç§ãããã®ãªã¯ãšã¹ãæ° èšå®ããå¡äŸ ä¿®æ£å ä¿®æ£åŸ å
šAPIã®ã¬ã¹ãã³ã¹ã®å¹³åé床 å¥éã¯ãšãªãäœæã衚瀺ããŠããŸãã æ¯ç§æ¯ã«å¹³åãç®åºããããšã§ãå
šIDã®å¹³åå€ã®æšç§»ãå¯èŠåããããã«ããŸããã ãã®APIã§ã¯ãã¬ã¹ãã³ã¹é床ã®å¹³åã197msã§ããããšãããããã»ãŒäžå®ã®é床ãåºããŠããããšãããããŸãã VUs (Virtual Users) ãã®ã°ã©ãã¯äžç§éã«äœåã®ã¢ã¯ã»ã¹ããã£ããã衚ããŠããŸãã ã·ããªãªã®éããéå§2ç§ã§ã¢ã¯ã»ã¹æ°ã20ãŸã§è·³ãäžããããã®åŸ2åããããŠåŸã
ã«æ°ãæžã£ãŠããæ§çžãèŠãŠåããŸãã RPS (response per second) çŽåã®äžç§éã«åž°ã£ãŠãããªã¯ãšã¹ãã®æ°ãè¿ããŠããŸãã æéçµéã§åŸã
ã«æžå°ããŠããããšãèŠãŠåããæ³å®éãã®æåãããŠããããšãããããŸãã 3. ããŒã¿ã®ã€ã³ããŒã ã³ã³ãããç«ã¡äžããéã«ç«ã¡äžãã£ãŠããããããã¡ãã«ã¢ã¯ã»ã¹ããŸãã csv圢åŒã§ããŒã¿ãä¿åããå Žåã®æé ã¯ä»¥äžã®éãã§ãã influxDB ( http://localhost:8086/ ) ã«ã¢ã¯ã»ã¹ãã Data â Buckets â demo ã«é·ç§»ãã ãã£ã«ã¿ãŒèšå®ããã ( demo / http_req_duration ãéžæ) (ãã®ä»ãã£ã«ã¿ãŒã¯å Žåã«ããèšå®) submit ãæŒã äžå³èµ€æ ã®ãã¿ã³ãæŒã ãããã« ä»åã¯influxdb, grafanaãçšããk6ã®äœ¿ãæ¹ã«ã€ããŠãŸãšããŠã¿ãŸãããk6ã¯ç°¡åã«äœ¿ããããŒã«ã§ãããªãããéåžžã«åŒ·åãªè² è·ãã¹ããå®è¡ããããšãã§ããŸããinfluxDBãšGrafanaãçµã¿åãããããšã§ããã¹ãçµæãèŠèŠçã«åæããããšãå¯èœã«ãªããŸãã ä»ã«ãã䜿çšããŠãããµãŒããŒã®CPU䜿çšçãRAM䜿çšçã®èšæž¬ããçºçãããšã©ãŒã®èª¿æ»ãªã©ã®ã¢ãããŒããå¿
èŠã«ãªããŸãã ã¯ããã«ãè§ŠããŠããéãããããã£ãæé ãå質ãä¿¡é Œæ§ã®æ
ä¿ã«ç¹ãããŸããã·ã¹ãã ã®ããã©ãŒãã³ã¹ãææ¡ããæœåšçãªåé¡ãæ©æã«çºèŠããããã«éåžžã«éèŠã§ãããã®ããè² è·ãã¹ãã¯åãªãæè¡çãªäœæ¥ã§ã¯ãªãããŠãŒã¶ãŒäœéšã®åäžãããžãã¹ã®æåã«çŽçµããåãçµã¿ãšãªããŸãã ä»å玹ä»ããææ³ãåèã«ãçããã®ãããžã§ã¯ãã§ããå®å®ããã·ã¹ãã éçšã«ã€ãªããŠããã ããã°å¹žãã§ãã æ¬¡åã¯ãåŸè€ããã§ããã©ããªèšäºã«ãªããæ¥œãã¿ã§ããïŒ ãããã£ã§ã¯ã ããŸããŸãªãããã¯ããžææŠãã ãšã³ãžãã¢ãçµ¶è³åéäžã§ãïŒ ãèå³ã®ããæ¹ã¯ä»¥äžã®æ¡çšãµã€ããã ãæ°è»œã«ãé£çµ¡ãã ããïŒ ãããã£æ ªåŒäŒç€Ÿæ¡çšæ
å ± Tech TalkãMeetUpãéå¬ããŠãããŸãïŒ ãã¡ãããæ°è»œã«ãå¿åãã ããïŒ Event – NIFTY engineering connpassã§ãããã£ã°ã«ãŒãã« åå ããã ããš ã€ãã³ãã® ãç¥ãããå±ããŸãïŒ connpassã§ ãããã£ã°ã«ãŒãã«åå ãã