import http from 'k6/http'; import { check } from 'k6'; // RTGS 부하 스크립트 - pacs.008(ISO 20022, pacs.008.001.08) 실시간 생성 -> Chanel 접수. // 참가기관(Dbtr/Cdtr Agent MmbId) 무작위 선정, 이체금액 1~200원(개요/PoC 기준). // 프로세스 (0) 사전확인(개인계좌 잔액/수신계좌)은 참가기관 몫이므로 여기(부하생성기=송신기관)가 담당. // // ※ Chanel은 pacs.008.001.08 XSD로 원전문을 검증한다. 반드시 정식 구조여야 // 접수(TxSts=RCVD)된다. 구식 간이 포맷은 XSD 검증 실패로 RJCT. // 핵심 추출 필드: EndToEndId(BMI), DbtrAgt/CdtrAgt MmbId(송/수신), Dbtr/CdtrAcct Othr Id, IntrBkSttlmAmt. // // 실행 예: // steady : k6 run -e RATE=50 -e DURATION=20s loadtest/pacs008.k6.js // spike : k6 run -e MODE=spike loadtest/pacs008.k6.js // 대시보드: k6 run --out influxdb=http://localhost:8096/k6 ... (관측 프로필) const BASE = __ENV.CHANEL || 'http://localhost:8091'; const DATE = __ENV.BIZDATE || '20260709'; const ORGS = ['1001','1002','1003','1004','1005','1006','1007','1008','1009','1010', '1011','1012','1013','1014','1015','1016','1017','1018','1019']; function scenarios() { if (__ENV.MODE === 'spike') { // 스파이크(peak) 산정: 도착률을 단계적으로 올려 최대 접수 처리건수 측정(리뷰어2 B). return { spike: { executor: 'ramping-arrival-rate', startRate: Number(__ENV.START || 100), timeUnit: '1s', preAllocatedVUs: 100, maxVUs: 2000, stages: [ { target: Number(__ENV.PEAK || 1000), duration: __ENV.RAMP || '30s' }, { target: Number(__ENV.PEAK || 1000), duration: '20s' }, { target: 0, duration: '10s' }, ], }, }; } return { steady: { executor: 'constant-arrival-rate', rate: Number(__ENV.RATE || 50), timeUnit: '1s', duration: __ENV.DURATION || '20s', preAllocatedVUs: 50, maxVUs: 500, }, }; } export const options = { scenarios: scenarios() }; function pad(n, len) { return String(n).padStart(len, '0'); } export default function () { const s = ORGS[Math.floor(Math.random() * ORGS.length)]; let r = ORGS[Math.floor(Math.random() * ORGS.length)]; while (r === s) r = ORGS[Math.floor(Math.random() * ORGS.length)]; const amount = 1 + Math.floor(Math.random() * 200); const serial = pad((__VU * 1000000 + __ITER) % 10000000000, 10); const bmi = DATE + s + serial; // 22자리 EndToEndId = 8+4+10 const creDtTm = new Date().toISOString().slice(0, 19); // pacs.008 ISODateTime (초 단위, TZ 생략) // pacs.008.001.08 정식 전문 (요소 순서는 XSD 시퀀스 준수 - 정상 샘플과 동일 구조). const xml = `` + `` + `` + `` + `${bmi}` + `${creDtTm}` + `1` + `CLRG` + `` + `` + `${bmi}` + `${amount}` + `SLEV` + `BANK-${s}` + `ACC-${s}` + `${s}` + `${r}` + `BANK-${r}` + `ACC-${r}` + `` + `` + ``; const res = http.post(`${BASE}/pay/customer`, xml, { headers: { 'Content-Type': 'application/xml' } }); check(res, { 'status 200': (x) => x.status === 200, 'accepted (RCVD)': (x) => x.body && x.body.includes('RCVD'), }); }