Skip to content

Commit

Permalink
Merge pull request #69 from f-lab-edu/feature/56-v1-profile
Browse files Browse the repository at this point in the history
[#56] v1 부하 테스트와 프로파일링
  • Loading branch information
yanggwangseong authored Jan 7, 2025
2 parents ee98e3a + a9d0769 commit db12e26
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ README.md

# docker
docker-compose-dev.yml

.clinic
20 changes: 17 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: auto deploy
on:
push:
branches:
- feature/55-load-test
- feature/56-v1-profile

jobs:
push_to_registry:
Expand Down Expand Up @@ -32,6 +32,18 @@ jobs:
secrets: |
GIT_AUTH_TOKEN=${{ secrets.GIT_TOKEN }}
- name: Build and push backend-flame
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile.clinic-flame
push: true
tags: ${{ secrets.NCP_CONTAINER_REGISTRY }}/backend-flame:latest
cache-from: type=registry,ref=${{ secrets.NCP_CONTAINER_REGISTRY }}/prv-backend-flame:latest
cache-to: type=inline
secrets: |
GIT_AUTH_TOKEN=${{ secrets.GIT_TOKEN }}
pull_from_registry:
name: Connect server ssh and pull from container registry
needs: push_to_registry
Expand Down Expand Up @@ -78,9 +90,11 @@ jobs:
echo "MYSQL_OUTBOUND_PORT=${{ secrets.MYSQL_OUTBOUND_PORT }}" >> .env
echo "MYSQL_INBOUND_PORT=${{ secrets.MYSQL_INBOUND_PORT }}" >> .env
echo "MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }}" >> .env
echo "JWT_ACCESS_TOKEN_EXPIRATION=${{ secrets.JWT_ACCESS_TOKEN_EXPIRATION }}" >> .env
echo "JWT_REFRESH_TOKEN_EXPIRATION=${{ secrets.JWT_REFRESH_TOKEN_EXPIRATION }}" >> .env
docker-compose down
docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/backend:latest
docker-compose up -d
docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/backend-flame:latest
docker-compose up -d backend mysql-prod
docker image prune -f
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ docker-compose.dev-bak.yml
grafana
prometheus

.clinic

clinic-report/**
backup2.sql
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ mysql-data
grafana/**
prometheus/prometheus.yml
docker-compose.dev-bak.yml
clinic-report/**
.clinic

backup2.sql
19 changes: 19 additions & 0 deletions Dockerfile.clinic-flame
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM node:22-alpine

WORKDIR /app

COPY package*.json ./


RUN npm install -g clinic

RUN npm install

COPY . .

RUN npm run build

RUN mkdir -p uploads/members uploads/articles

ENTRYPOINT ["tail", "-f", "/dev/null"]

30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,33 @@
## 📖 프로젝트 개요

개요에대해서 작성 할 예정입니다.

## 🚀 부하 테스트와 성능 개선

### 📈 부하 테스트와 성능 개선 단계

#### V1

-**[게시물 리스트 가져오기](https://github.com/f-lab-edu/Mokakbab/wiki/%EA%B2%8C%EC%8B%9C%EB%AC%BC%EB%A6%AC%EC%8A%A4%ED%8A%B8%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0)**

-[k6 부하 테스트 결과](https://github.com/f-lab-edu/Mokakbab/wiki/%EA%B2%8C%EC%8B%9C%EB%AC%BC%EB%A6%AC%EC%8A%A4%ED%8A%B8%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0#k6-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC)
-[프로파일링 결과 및 개선 사항](https://github.com/f-lab-edu/Mokakbab/wiki/%5B%EA%B2%8C%EC%8B%9C%EB%AC%BC%EB%A6%AC%EC%8A%A4%ED%8A%B8%5D%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81-%EA%B2%B0%EA%B3%BC-%EB%B0%8F-%EA%B0%9C%EC%84%A0-%EC%82%AC%ED%95%AD)

-**[특정 게시물의 모각밥 참여 리스트 가져오기](https://github.com/f-lab-edu/Mokakbab/wiki/%ED%8A%B9%EC%A0%95-%EA%B2%8C%EC%8B%9C%EB%AC%BC%EC%9D%98-%EB%AA%A8%EA%B0%81%EB%B0%A5-%EC%B0%B8%EC%97%AC-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0)**

-[k6 부하 테스트 결과](https://github.com/f-lab-edu/Mokakbab/wiki/%ED%8A%B9%EC%A0%95-%EA%B2%8C%EC%8B%9C%EB%AC%BC%EC%9D%98-%EB%AA%A8%EA%B0%81%EB%B0%A5-%EC%B0%B8%EC%97%AC-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0#k6-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC)
-[프로파일링 결과 및 개선 사항](https://github.com/f-lab-edu/Mokakbab/wiki/%5B%EB%AA%A8%EA%B0%81%EB%B0%A5%EC%B0%B8%EC%97%AC%EB%A6%AC%EC%8A%A4%ED%8A%B8%5D%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81-%EA%B2%B0%EA%B3%BC-%EB%B0%8F-%EA%B0%9C%EC%84%A0-%EC%82%AC%ED%95%AD)

-**[회원가입](https://github.com/f-lab-edu/Mokakbab/wiki/%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85)**
-[k6 부하 테스트 결과](https://github.com/f-lab-edu/Mokakbab/wiki/%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85#k6-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC)
-[프로파일링 결과 및 개선 사항](https://github.com/f-lab-edu/Mokakbab/wiki/%5B%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85%5D%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81-%EA%B2%B0%EA%B3%BC-%EB%B0%8F-%EA%B0%9C%EC%84%A0-%EC%82%AC%ED%95%AD)

#### V2

- 🔄 **[추가 개선 작업](#)**
- k6 부하 테스트 결과
- 프로파일링 결과 및 개선 사항

## 🛠 트러블 슈팅 (Troubleshooting)

- [TypeORM Seeding 성능 문제 해결 (#67)](https://github.com/f-lab-edu/Mokakbab/pull/67)
32 changes: 31 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "3.8"
version: "3.9"
services:
backend:
image: ${NCP_CONTAINER_REGISTRY}/backend:latest
Expand All @@ -14,6 +14,8 @@ services:
- DB_DATABASE=${DB_DATABASE}
- DB_SYNCHRONIZE=${DB_SYNCHRONIZE}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- JWT_ACCESS_TOKEN_EXPIRATION=${JWT_ACCESS_TOKEN_EXPIRATION}
- JWT_REFRESH_TOKEN_EXPIRATION=${JWT_REFRESH_TOKEN_EXPIRATION}
- MAIL_HOST=${MAIL_HOST}
- MAIL_PORT=${MAIL_PORT}
- MAIL_USER=${MAIL_USER}
Expand All @@ -23,6 +25,34 @@ services:
extra_hosts:
- "host.docker.internal:host-gateway"

backend-flame:
image: ${NCP_CONTAINER_REGISTRY}/backend-flame:latest
container_name: backend_flame
ports:
- "${BACKEND_OUTBOUND_PORT}:${BACKEND_INBOUND_PORT}"
environment:
- DB_TYPE=${DB_TYPE}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
- DB_DATABASE=${DB_DATABASE}
- DB_SYNCHRONIZE=${DB_SYNCHRONIZE}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- JWT_ACCESS_TOKEN_EXPIRATION=${JWT_ACCESS_TOKEN_EXPIRATION}
- JWT_REFRESH_TOKEN_EXPIRATION=${JWT_REFRESH_TOKEN_EXPIRATION}
- MAIL_HOST=${MAIL_HOST}
- MAIL_PORT=${MAIL_PORT}
- MAIL_USER=${MAIL_USER}
- MAIL_PWD=${MAIL_PWD}
- API_BASE_URL=${API_BASE_URL}
- SERVER_PORT=${SERVER_PORT}
volumes:
- ./clinic-flame:/app/.clinic
- ./clinic-flame:/tmp # Doctor 실행을 위한 TMPDIR 경로와 동일하게 설정
extra_hosts:
- "host.docker.internal:host-gateway"

mysql-prod:
image: mysql:8.0
restart: always
Expand Down
10 changes: 5 additions & 5 deletions k6/scripts/articles-performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ export const options = {
/* 일정한 RPS(Request Per Second)를 유지하는 실행기 타입 */
executor: "constant-arrival-rate",
/* 초당 실행할 반복 횟수 */
rate: 4,
rate: 1,
/* rate의 시간 단위 (1s, 1m, 1h 등) */
timeUnit: "1s",
/* 전체 테스트 실행 시간 */
duration: "1m",
duration: "3m",
/* 테스트 시작 시 미리 할당할 가상 사용자 수 */
preAllocatedVUs: 10,
preAllocatedVUs: 30,
/* 최대 가상 사용자 수 (필요시 추가 할당) */
maxVUs: 30,
maxVUs: 50,
},
},
// 태그 추가
tags: {
testName: "articles-api-test",
testName: "v1-articles-frame",
testType: "performance",
component: "articles",
version: "1.0",
Expand Down
10 changes: 5 additions & 5 deletions k6/scripts/participations-performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ export const options = {
scenarios: {
simple_rps_test: {
executor: "constant-arrival-rate",
rate: 450, // 초당 10개의 요청 (RPS)
rate: 120, // 초당 10개의 요청 (RPS)
timeUnit: "1s", // RPS 단위 설정
duration: "1m", // 테스트 지속 시간: 5분
preAllocatedVUs: 1000, // 미리 할당할 VU 수
maxVUs: 2000, // 최대 VU 수
duration: "3m", // 테스트 지속 시간: 5분
preAllocatedVUs: 300, // 미리 할당할 VU 수
maxVUs: 500, // 최대 VU 수
},
},
// 태그 추가
tags: {
testName: "participations-api-test",
testName: "v1-participations-result3",
testType: "performance",
component: "participations",
version: "1.0",
Expand Down
15 changes: 11 additions & 4 deletions k6/scripts/signup-performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ export const options = {
scenarios: {
simple_rps_test: {
executor: "constant-arrival-rate",
rate: 1,
rate: 5,
timeUnit: "1s",
duration: "1m",
preAllocatedVUs: 5,
maxVUs: 10,
duration: "3m",
preAllocatedVUs: 15,
maxVUs: 30,
},
},
// 태그 추가
tags: {
testName: "v1-signup-result",
testType: "performance",
component: "signup",
version: "1.0",
},
thresholds: {
http_req_failed: [{ threshold: "rate<0.05", abortOnFail: true }],
dropped_iterations: [{ threshold: "rate<0.05", abortOnFail: true }],
Expand Down
4 changes: 4 additions & 0 deletions src/common/constants/env-keys.const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export const ENV_API_BASE_URL = "API_BASE_URL" as const;

// jwt
export const ENV_JWT_SECRET_KEY = "JWT_SECRET_KEY" as const;
export const ENV_JWT_ACCESS_TOKEN_EXPIRATION =
"JWT_ACCESS_TOKEN_EXPIRATION" as const;
export const ENV_JWT_REFRESH_TOKEN_EXPIRATION =
"JWT_REFRESH_TOKEN_EXPIRATION" as const;

// server
export const ENV_SERVER_PORT = "SERVER_PORT" as const;
Expand Down
14 changes: 12 additions & 2 deletions src/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { JwtService } from "@nestjs/jwt";
import * as bcrypt from "bcrypt";
import * as crypto from "crypto";

import { ENV_JWT_SECRET_KEY } from "@APP/common/constants/env-keys.const";
import {
ENV_JWT_ACCESS_TOKEN_EXPIRATION,
ENV_JWT_REFRESH_TOKEN_EXPIRATION,
ENV_JWT_SECRET_KEY,
} from "@APP/common/constants/env-keys.const";
import { BusinessErrorException } from "@APP/common/exception/business-error.exception";
import { MemberErrorCode } from "@APP/common/exception/error-code";
import { RegisterMemberDto } from "@APP/dtos/register-member.dto";
Expand Down Expand Up @@ -138,7 +142,13 @@ export class AuthService {
return this.jwtService.sign(payload, {
secret:
this.configService.get<string>(ENV_JWT_SECRET_KEY) || "secret",
expiresIn: isRefreshToken ? 3600 : 300,
expiresIn: isRefreshToken
? this.configService.get<string>(
ENV_JWT_REFRESH_TOKEN_EXPIRATION,
)
: this.configService.get<string>(
ENV_JWT_ACCESS_TOKEN_EXPIRATION,
),
});
}

Expand Down

0 comments on commit db12e26

Please sign in to comment.