반응형

톰캣으로 스프링 프로젝트를 개발하면서 은근 시간을 많이 잡아먹는 톰캣 재부팅.. JAVA 소스 한글자만 수정해도 반영되려면 톰캣을 재부팅 해야반영된다. 새로운 기능 개발을 하면서 이것저것 테스트할 때 수십법 재부팅을 해야하는데..

이게 개인 프로젝트 급이면 재부팅 머 10~30초 이내라지만, 기업급 프로젝트는 재부팅도 꽤나 많은 시간을 차지한다..재부팅 눌러놓고 커피나 뽑으러 가거나 했었지만 이게 은근 흐름을 끊고 그 몇분을 다 모아보면 꽤나 많은 시간이 허비 된다는 것을 느꼈다 ㅋㅋ...

그래서 java파일 변경 후 톰캣 재부팅이 필요없는 Spring Loaded 적용하는 법을 알아보자.

1. Spring Loaded 설치

https://mvnrepository.com/artifact/org.springframework/springloaded

가장 최신버전은 1.2.8이다. 2017년 이후로 새로운 버전은 없는 것 같다.

<!-- https://mvnrepository.com/artifact/org.springframework/springloaded -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>springloaded</artifactId>
    <version>1.2.8.RELEASE</version>
</dependency>

난 Maven을 쓰기 때문에 pom.xml의 dependency에 추가해주자!

짜잔~ 적당한 위치에 추가해주면 된다.

2. 톰캣 설정 변경

자 내 톰캣 서버 설정으로 와서 몇가지 설정을 바꿔주자.

1. Server Options 쪽을 보면 모든 체크박스를 해제해주자.

2. Publishing 쪽에 두번 째인 Automatically publish when resources change 를 선택해주자.

1. 하단 Modules 클릭

2. Path 클릭

3. Edit 클릭

4. Auto reloading enabled 선택 해제

5. OK

마지막으로 Ctrl+S를 눌러 톰캣 설정을 저장해주자.

그리고 톰캣 부팅 후 JAVA 파일을 바꾸면 재부팅없이 반영되는 것을 볼 수 있다.

#스프링 #Spring #톰캣 #tomcat #재시작 #재부팅 #종료 #다시시작 #JAVA #파일 #변경 #저장 #적용 #SpringLoaded #메이븐 #블챌 #오늘일기

반응형
반응형

이번에 아마존 EC2 인스턴스를 12개월 동안 무료로 사용할 수 있는 프리티어 기간이 끝난다는 메일을 받았다.

아무생각 없이 영원히 이용할 수 있을 것 같았던 EC2가.. 끝이라니..! 무료 사용 종료는 2020년 4월 30일.. 이번달이 지나고 나서 온디멘드 요금으로 전환된다.

그래서 그냥 유료로 기존 EC2 서버를 운용 할 것인가. 아님 그냥 서비스를 종료할까, 아니면 다른 서버로 이주해서 계속 서비스를 할 것인가 고민을 많이 했다.

고민끝에 서버를 이전하기로 했고, 기존 EC2 서버는 더 이상 요금이 발생하지 않도록 삭제하기로 했다.

1. EC2 인스턴스 종료 및 삭제

 

인스턴스 중지

EC2 인스턴스를 삭제하기 전에 실행중이라면 인스턴스를 종료해주자.

1. EC2 대시보드에서 인스턴스를 눌러주자.

2. 삭제하려는 인스턴스 선택

3. 인스턴스 상태 클릭

4. 인스턴스 중지 선택

정지할꺼냐고 물어보는데 중지를 눌러줍시다.

상단에 성공적으로 중지됐다고 나오고, 인스턴스 상태가 중지됨으로 나오면 완전히 중지된 상태이다.

인스턴스 종료(삭제)

이제 인스턴스를 삭제할 꺼다. 예전에 AWS 처음 할 때 저 인스턴스 종료가... 그냥 윈도우 잠깐 시스템 종료 해두듯이. 그냥.. 단순 종료인줄 알았는데.. 저거 서버 삭제다.. ㅋㅋ 아무생각없이 눌렀다가 서버 날아가서 오열했던 기억이 잠깐 난다.

1. 삭제할 인스턴스 선택

2. 인스턴스 상태 선택

3. 인스턴스 종료 선택

진짜 삭제할꺼냐고 묻는다. 종료를 눌러주자.

그럼 성공적으로 종료되었다는 메시지와 함께 인스턴스 상태를 보면 종료됨으로 표시된다. 처음에 어..? 삭제 끝났는데 왜 목록에 자꾸 남아있지!? 하고 이상해했다. 계속 새로고침을 눌러봐도 종료됨으로 떠있어서 이게 삭제가 아닌가? 했는데 한 5~10분 지나면 목록에서 사라진다 ㅋㅋ..

몇분 후면 이렇게 목록에서 사라져있다 ㅎㅎ 여기까지 EC2 인스턴스 삭제는 끝이다.

하지만, 인스턴스만 삭제고, 나머지 EIP 등으로 과금이 생길 수 있기때문에 깔끔하게 다른 것 까지 지워주자.

2. EIP 삭제 (Elastic IP / 탄력적 IP)

EIP를 사용하지 않고 유동 IP를 사용했다면 추가 과금 될 것은 없다. 하지만 서버에서 서비스를 운영하는 입장에서는 보통 고정 IP를 쓰고 프리티어에서 1개의 EIP는 무료로 사용 할 수 있기 때문에 아마도 다들 EIP 할당이 되어있을 것 같다.

EIP는 프리티어에서 1개까지는 무료지만, EIP할당 받아놓고 인스턴스를 Run 해놓지 않으면 과금이 발생한다. 보통 대학생들이 AWS에 돈나갔어요 ㅜㅜ 한번만 봐주세요 하고 보내는는 이유중, 이런 사유로 발생하는 경우가 많다 ㅋㅋ..

AWS 입장에서는 고정 IP를 한정적으로 가지고있고, 여기에 인스턴스가 돌아가지 않고 있다면, IP 자원 하나를 손실보는 것이기 떄문에 인스턴스가 안돌아가는 경우 과금을 하는 것 같다. 이제 할당된 EIP를 삭제하는 법에 대해 알아보자.

1. 좌측에 탄력적 IP를 눌러주자.

2. 삭제하려는 IP를 선택해주자.

3. 상단 작업을 클릭

4. 탄력적 IP 주소 릴리즈 를 눌러주자

진짜 삭제할 꺼냐고 묻는다. 릴리스를 눌러주자.

일단 여기까지 하면 보통 과금될 일은 없다. 추가적으로 AWS S3, Route 53, RDS, 스냅샷 을 사용할 경우 이 서비스들 각각 다 서비스를 삭제해주면 된다. 하지만 난 S3, RDS를 사용하지 않고 Route 53은 계속 사용할 것이기 떄문에 일단 여기까지만 했다.

다음은, 과금에 영향은 없지만 이 EC2와 관련된 것은 다 지우고 싶다 할 경우 진행하면 된다.

3. 보안그룹 삭제

일단 기존 EC2 에서 사용되었던 보안그룹도 삭제할 것이다. 보안 그룹이 뭐지? 하는 사람은 머.. 방화벽 정책정도로 생각하면 될 것 같다. 나중에 다시 EC2 인스턴스를 올려서 동일한 방화벽 정책을 사용할 경우에는 남겨두어도 좋지만, 난 라이트세일 서버로 이전했기 때문에 필요 없어서 지웠다. 머.. 나중에 EC2 인스턴스를 다시올릴때 필요하다면 다시 만들려고 한다. 머 어차피... DB포트정도만 열면되기 떄문..

1. 네트워크 및 보안 탭에 보안그룹을 클릭

2. 삭제하려는 보안 그룹 선택

→ 2번에 빨간 박스친 밑에 default 보안그룹은 말그대로 기본 설정이기 때문에 안지워도 된다. 본인이 만든것만 지우면 되기때문에 디폴트는 걍 무시한다.

3. 작업 선택

4. 보안그룹 삭제 선택

진짜 삭제할 꺼냐고 물어본다. 삭제를 눌러주자.

짜잔 삭제 완료

4. 키 페어 삭제

이제 기존 EC2 서버 접속간 사용했던 키페어를 삭제할 예정이다. 이거 머 삭제해도 되나..? 한번 고민은 해봤었는데 어치파.. 기존 EC2 접속에만 사용했었기 때문에 더 이상 그 인스턴스는 필요하지 않으니, 삭제해도 상관 없을 것이라고 판단됐다.

 

1. 네트워크 및 보안 키 페어 클릭

2. 삭제하려는 키 페어 선택

3. 작업 클릭

4. 삭제 클릭

그 다음 진짜 삭제할꺼냐고 묻는데 상당히 중요한 판단인가본지 직접 "삭제"라고 타이핑 하고 진행하라고 한다. 일단.. 삭제하기로 맘먹었기 때문에 그냥 삭제 치고 삭제를 누르자.

짜짠.. 키 페어 삭제 완료

삭제 후기

삭제 후기? 별거 없다. AWS 프리티어 1년간 정말 잘 썼다. 앞으로 이거 관련해서 추가 과금은 없겠지..? ㅎㅎ 요금 폭탄 안나오길 바란다.

#AWS #EC2 #인스턴스 #삭제 #프리티어 #종료 #방법 #탄력적IP #키페어 #보안그룹 #서버 #서버삭제 #인스턴스삭제

반응형
  1. 익명 2021.09.08 11:01

    비밀댓글입니다

  2. 익명 2022.04.15 17:10

    비밀댓글입니다

    • 외장_하드 2022.04.15 17:27 신고

      프리티어라디 엘라스틱 ip를 할당받아놓으셨다면 비용이 발생합니다!

  3. test 2022.05.05 19:59

    잊고있던 계정 인스턴스 덕분에 삭제했습니다. 두 달치 청구됐지만 ㅠ

반응형

최근 운영중인 웹서비스가 비규칙적으로 다운되는 현상이 있었는데, 발생했던 문제와 그 문제를 해결하는 과정에 대해서 포스팅을 해보려고 한다. 서버 운영을 하는 실무자들에게 도움이 되었으면 좋겠다.

문제 발생

첫 발생이 3월 초쯤 이었던가?.. 운영중인 웹 서비스가 종종 다운되는 현상을 겪었다. 운영 서버에 요청을 보내면 처리되지 않다가 결국 몇 분 뒤 Tomcat 서버가 죽어 위처럼 Service Unavailable 메시지를 띄었다.

보통 부하 분산과 장애에 대비해 WAS를 이중화 해놓기 때문에 WAS하나가 죽어도 다른 WAS가 처리해 줄껀데, 브라우저가 응답대기 상태도 아니고 Service Unavailable 을 띄운걸로 봐서는 WAS두개가 모두 죽은 것 같았다.

어떤 문제가 있었던걸까? 여태까지 악성쿼리때문에 DB 락 걸이 걸려 부하가 걸리는 장애는 종종 겪어 보았지만, 이번 케이스는 달랐다.

단서 1. CPU 사용률에 최대 부하 발생

해당 상황이 접수되고나서 바로 확인해보니 이중화 된 WAS 두개가 아예 삭선처리되어 모두 뻗어있었다. 그냥 Tomcat 서비스가 다운된 상태...

문제가 최초 발생 했을 시간대의 CPU사용량을 보니 WAS 2번이 기존 5~10% 내외로 사용하던 사용량이 어느 시점에 80%까지 올라가며 최대 부하가 걸려있었다. 5분 뒤 WAS 1번도 따라서 같은 현상을 보이기 시작했다.

보통 지연이 길거나, 부하가 강한 요청 중 단순 조회작업이라면 Kill을 해서 일단 서비스 복구를 하고 분석을 할텐데.. 이건뭐 톰캣이 다 죽어있으니 뭘 할수도 없고 ㅋㅋ당장 서비스 복구를 위해 WAS 재부팅밖에 답이 없었다. 그리고 바로 WAS 로그를 확인해봤다.

단서 2. java.lang.OutOfMemoryError: GC overhead limit exceeded

톰캣 로그를 확인하니, 발생 했을 때로 추정되는 시간때에 모두 java.lang.OutOfMemoryError: GC overhead limit exceeded 오류가 찍혀있었다.

GC에 대해서 간단하게 알아보고 넘어가보자. JVM은 메모리 확보를 위해서 GC를 수행한다. 대학 Java 시간에 잠깐 배웠던 그 GC가 맞다 바로 가비지 컬렉션(Garbage collection)이다. 더 이상 사용되지 않는 객체에 대해서 메모리를 해체해주면서 메모리 풀을 관리해주는 친구다.

근데 저 GC overhead limit exceeded 메시지는 왜 띄었는가..?

* GC를 진행하는데 CPU 98% 이상 사용

* GC 진행 후 메모리 2%미만이 복구 되었을 때

일단은 메모리가 부족했던 걸까? 생각이 들었다. 찾아보니, 위 문제에 직면한 경우 보통 JVM 옵션으로 힙 리밋 제한을 없애거나 메모리 사용량을 늘리라고들 하더라. 사실. 나는 이런 셋팅쪽 문제가 아닐거라고 개인적으로 생각은 들었지만, 팀 내부적으론 일단 메모리 부족으로 방향을 잡고, 톰캣, 자바 셋팅쪽을 손봤다.

하지만, 내 예상처럼 이런 증상은 셋팅으로 해결되지 않았다. 몇 일간 원인모를 이유로 서버는 다운됐다..ㅠ

그리고 GC 로그를 확인하기 위해서 서버에 GC로그를 남기는 설정도 추가하여 해당 문제가 발생했을 때 GC로그를 확인했으나, "GC 할껀데 메모리 없어~~~" 사실상 이런 내용만 도배되어있었다. 그런데 GC 시도 엄청 많이 했긴 했더라......암튼 이문제를 해결하는데 GC로그는 도움되지 않았다..

단서 3. 특정 요청에 문제가 생기는 것은 아니었다.

이게 어떤 특정요청에만 생기는 현상일까 생각이 들었다. 머 배치가 돌때 먼가 잘못 도는게 있는걸까? 아니면 사용자가 이상한 파라미터를 던져서 처리를 못하나...? 신기하게도 새벽에는 이런일이 발생하질 않네?.. 해서 의심이 갔었다.

문제가 발생했었을 때의 로그를 확인했으나, 공통점은 없었다. 심지어 GC error 가 발생한 해당 요청을 같은 파라미터를 넣고 다시 요청해도 같은 현상은 발생하지 않았다.

결론부터 말하자면, 특정한 요청이 문제가 됐었다. 다만, 내가 바로 찾지 못한 이유는, 이미 문제가 발생한 이후에 로그에 찍힌 GC error 로그에만 집착했기 때문이었다. 일단은 GC error 로그가 어떤 요청에 찍혔다 하더라도, 그 요청이 문제가 아니라는 거다. 이미 문제는 발생했고, 우연히 그 요청을 처리중일 때 GC 가 동작하여 error 을 띄운거란거다.

만약 이방법으로 간단하게 볼려면, GC Limit 이 발생하기 전 로그들을 뒤져봐야 한다.

이런 현상이 지속되고, 팀원들이 이 문제를 해결하기 위해 이미 붙어있었기 때문에, 내 업무를 좀 쳐내고 나중에 시간이 남으면 보려고 생각했다. 뭐 그때쯤 가서 이미 해결이 되면, 좋은거긴 한데, 나는 셋팅쪽 문제가 아닐꺼란 생각이 계속 들었다.

단서 4. 힙메모리 사용량 증가

시간적 여유가 생겨 다시 문제를 분석해봤다. 보니까 해당 문제가 발생 했을 때 CPU사용량도 돌라갔었지만, 힙 메모리 사용량도 폭발적으로 증가하는 현상이 확인되었다.

왜 처음부터 힙메모리 관제에 신경쓰지 않았을까, 평소에 악성쿼리처럼 CPU를 많이 점유하던 장애를 주로 만났었기 때문에 메모리보다는 CPU 사용량이나 어떤 요청이 왔는지 이런거 위주로 봤던게 좀 방심했던 것 같다.

원래 힙메모리 사용량의 이상적인 그래프는 맨 아래 그래프처럼 어느정도 메모리가 올라가다 GC가 작동하여 떨어지고, 계속 반복하여 적정한 수준을 유지하는게 이상적이다.

하지만 위 사진을 보다시피 3월 16일동안 3회나 01번 02번 WAS 힙메모리 점유율이 급격하게 올라가는 것을 볼 수 있다.

문제 해결을 위한 방향성 잡기

자 여기까지 정리를 해보자.

1. 새벽이 아닌 주야간 워크 타임때, 그리고 불특정, 비규칙적인 시간에 서버가 다운이 된다.

2. CPU 사용량과 힙 메모리 점유율이 급격히 상승한다.

3. 서버 에러 로그에는 GC overhead limit exceeded 이 발생한다.

자 일단 에러로그에 GC 할 메모리가 부족하다고 되어있어서 GC에만 문제가 있었던건가 여기에만 집중했지만, 내 생각에는 이건 메모리가 부족해지고 나서, 즉 어떤 문제가 발생하고 그 이후에 파생된 현상이지 주 원인은 갑작스럽게 메모리를 차지한 어떤게 있을거라고 생각했다.

즉, 어떤 원인에 의해 메모리가 급격하게 사용되었고, 그 이후에 평소처럼 GC를 하려니 GC 리밋 로그를 띄운 것 이다. 나도 그랬지만, 보통 다른 사람들도 이 GC 리밋 에러 로그를 보고, 왜 GC 리밋 로그를 띄었을까..? 검색해보면 "서버 힙메모리가 부족하네요 ㅎㅎ" 이럴텐데 이렇게 접근해서는 해결 할 수 없는 문제였다. (내 케이스의 경우)

자. 정리하자면 GC 관련된 문제가 아닐꺼다, 무언가가 힙메모리를 엄청나게 차지하니까, 당연히 GC도 못하니 저 오류를 띄운거고, 우리는 앞으로 어떤 녀석이 힙메모리를 그 순간에 차지하고 있었는지를 찾아야한다.

앞으로 해야할게 바로 힙메모리 분석이다. 다음 포스팅을 통해서 힙메모리 분석을 어떻게 했고, 어떤게 원인이었으며, 어떻게 조치했는지에 대해서 알아보자

 

#톰캣 #WAS #오류 #다운 #종료 #꺼짐 #GC #overhead #limit #Exceeded #메모리릭 #메모리누수 #힙 #힙메모리 #메모리 #사용량 #점유률 #급등 #증가 #서버 #장애 #트러블 슈팅

반응형

+ Recent posts