7주차 발표 - g-market/b-shop-backend GitHub Wiki
진행률 : 99%..(고도화...)
- 동시성 제어
-
Redis
를 통한thread락
기능을 적용해 재고에 대한 동시성 제어 로직을 구현하고자 함 -> DB 비관적 락을 통해 해결
-
-
상품 조회(카테고리별, 연도별)조회
추가적으로 구현 - 상품관련 CRUD 기능
테스트코드
추가 구현- 상품 옵션 관련기능 테스트 코드
- 상품 이미지 관련기능 테스트 코드
- 상품 예약 관련 테스트 코드
- 카테고리 관련 테스트 코드
- 프론트엔드 작업 및 배포
- 초기 데이터 생성 -> 조금씩 꾸미고 있는 중..
👉 !53
-
✔ DNS 서버 세팅 필요 -> 211.253.26.121
-
서비스 주소
-
sentry
-
CORS
이슈를nginx
에서 해결하려면 어떻게 해야할까? -
139.150.73.182:80
->139.150.73.182:8080
CORS!
발생 -
프론트엔드 nginx
서버에서139.15.73.182/api/URI-PATH
로 들어온 요청을 리버스 프록시 서버로 라우팅 해서 해결
upstream b-shop-proxy {
server b-shop-nginx:80;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.html;
# error_page 500 502 503 504 /50x.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
rewrite /api/(.*)$ /$1 break; // b-shop.com:80/api/ -> b-shop.com:80/
proxy_pass http://b-shop-proxy; // b-shop.com:80 -> b-shop-nginx:80
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_redirect off;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'X-Requested-With,Accept,Content-Type, Origin' always;
client_body_temp_path /tmp/;
client_body_in_file_only on;
client_body_buffer_size 128K;
client_max_body_size 100M;
}
}
- 인프라, 어플리케이션, loging, 발생된 에러에 대한 추적 관리 필요성을 느낌...
- nGrinder란
- 네이버에서 성능 측정 목적으로 개발된 성능 부하 및 스트레스 테스트 도구
- nGrinder 적용
- local Docker환경에 nGrinder Contoller, Agent 설치
3. Script 작성 - 서버 부하를 발생시킬 api 요청 스크립트 작성 - groovy Script 작성
@RunWith(GrinderRunner)
class TestRunner {
private String accessToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBY2Nlc3NUb2tlbiIsImlhdCI6MTY3ODMzNjQ2MiwiZXhwIjoxNjc4MzQwMDYyLCJpZCI6MTEsInJvbGUiOiJBRE1JTiJ9.A_9S3Nhh_UnDNCH5dnuYLpTYD0qsywXZ0p0kZBcpzwo"
...
@Test
public void test() {
headers["Authorization"] = "Bearer " + accessToken
request.setHeaders(headers)
def param = "{\"orderItemDtoList\":[{\"itemId\":1,\"itemOptionId\":1,\"orderCount\":1}]}"
HTTPResponse response = request.POST("http://b-shop.com/api/orders", param.getBytes());
if (response.statusCode == 301 || response.statusCode == 302) {
grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
} else {
assertThat(response.statusCode, is(201))
}
}
- VM 서버로 부하 테스트 수행
- Vusers : 동시 접속하는 유저의 수 ( vuser = agent * process * thread )
- TPS(Transaction per Second) : 초당 처리수, 높을 수록 성능 좋음
- Peak TPS : 초당 처리 수의 최대치
- Mean Test Time : 응답 시간
프론트엔드에서 장바구니 페이지에서 주문 페이지로 이동할 때
상품 상세 페이지에서 주문하기 버튼을 눌러 주문 페이지로 이동할 때를 구분하였습니다.
이에 전자의 경우에만 장바구니가 지워지도록 하였습니다. (`회원의 장바구니에서 주문한 itemId, itemOptionId 만 지워지도록 변경하였습니다.)
장바구니는 현재 Hashes 자료구조를 사용하고 있습니다.
key: memberId (위 그림에서 KEY)
hashKey: itemId + '-'(Delimiter) + itemOptionId ('NAME')
hashvalue: CartDto(itemId, itemOptionId, orderCount) ('GARIM')
이에 따라 장바구니페이지에서 (주문하기 버튼을 눌러)
주문 페이지로 이동할 때,
아이템 상세 페이지에서 주문 페이지로 바로 갔을 때를 구분하였습니다.
이를 해결하는 방법으로
-
/orders
API를 하나로 사용하고 있어 이를 API를 분리 - 장바구니에 대한 id를 만들어 이를 전달하는 방식
-
/orders?delete=true
API의 @RequsetParam - 장바구니에서 시작하면 장바구니 삭제 API를 추가
이에 따라 4번 방식인 장바구니페이지에서 (주문하기 버튼을 눌러)
주문 페이지로 이동할 때만 장바구니를 지우는 방식으로 구현하였습니다.
- application logging, infra status logging -> docker-compose 로깅
ing
- 성능부하테스트(nGrinder)
ing
- 코드 아키텍처 리팩토링(Clean Architecture, CQRS, 추상화)
ing
- DB I/O 줄이는 리팩토링
ing
- API 리팩토링
ing