서버가 죽어버렸다 

 

계엄령을 내렸나? 싶은 아침

 

자바는 heap memory가 부족하다며 절규하다가 그대로 사망했다. 

 

뭐 원인과 결과는 너무 명백하지만 시간이 없는 관계로 임시방편인 crontab에 쉘스크립트를 등록시켜

 

pm2에 해당 프로세스를 야심한 새벽시간대에 reload 명령을 넣기로했다

 

우선 실행시킬 쉘스크립트를 만들자

touch pm2reload.sh

---pm2reload.sh--- 

pm2 reload myapi

 

경로는 ec2환경의 우분투라면 /home/ubuntu/pm2reload.sh 가 될것이다

 

crontab -e 명령어를 치면

 


Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny
  4. /bin/ed

 

위와 같은 명령어가 나온다 어떤 편집기를 쓸꺼냐라고 묻는것인데 나는 개틀딲개발자니까 vim.basic을 쓸것이다

 

2를 입력하고 엔터를 치면

 

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command

 

위와 같은 편집기에 내용이 열린다

 

0 18 * * * sh /home/ubuntu/pm2reload.sh

 

위 내용을 추가한 다음 저장하고 

 

crontab -l을 치면 내가 등록한 크론탭 명령어가 보인다

 

제대로 보인다면 profit이고 없다면 무언가 잘못되거니까 다시 한번 차근차근해보자

 

 

 

사실 자바 탭에 쓸까 말까 고민하다가 귀찮아서 자바탭에 씀

 

'개발 > java' 카테고리의 다른 글

queryDsl의 Q클래스 객체 사용하기  (1) 2024.12.02
404 Not Found으로 전력투구  (1) 2024.03.26
JPA QUERYDSL의 LIKE 구현  (0) 2024.03.22
java 탭을 신설했다.  (0) 2023.06.01

러닝커브 낮은게 장점이라 들었는데 막상 손대고 나서 보니 뭐 이렇게 어렵지

 

angular보다 더 어려운데...

queryDsl의 철학 중 하나는 

 

런타임 보단 빌드타임에 에러를 잡자가 있다.

 

그런 의도로 보자면 더욱 엄격한 빌드타임 에러를 체크하고

 

코드편집기(인텔리제이)의 자동완성 이점을 얻고 싶다면

 

Q클래스 객체를 사용하면 보다 철학을 지키며 더 좋은 생산성을 가질 수 있다. 

 

뭐..늘 이런 논지로 이야기를 하는편인데 쉽게 수긍하는 사람이 있는 반면 또 한편으로는 싫어하는 사람이 있을 수 있으니

 

본인의 팀의 사정과 아키텍처 등등 여러 방면을 고려하고 도입하자

 

언어 : 자바 17버전 

 

프레임워크 : spring boot 3.3.4

 

편집기 : 인텔리제이

 

컴파일 : gradle

 

build.gradle

def querydslDir = "$buildDir/generated/querydsl"

sourceSets {
    main.java.srcDirs += "$buildDir/generated/sources/annotationProcessor/java/main"
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}

compileJava {
    options.annotationProcessorPath = configurations.annotationProcessor
    
    source = source.filter { !it.path.startsWith("$buildDir/generated") }
}

clean {
    delete file(querydslDir)
}

 

사실 뭐 하나 하나 뜯어보자면 큐 클래스 객체의 생성경로,중복제거,클린 생명주기시 취해야할 내역 등등 뭐 있는데 

 

전부다 설명하기에는 너무 기니까 간단히 요약하자면 위 빌드파일의 셋팅은

 

큐 클래스 객체에 어노테이션을 활용해 생성시키며, 경로를 정하고 중복파일 필터를 설정하며 clean 명령어 수행시

 

제거하는 명령어이다. 위 빌드내역을 추가시키고 아래 의존성까지 추가하자

ependencies {
    // 기본 의존성
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

    // Lombok
    compileOnly 'org.projectlombok:lombok:1.18.28'
    annotationProcessor 'org.projectlombok:lombok:1.18.28'

    // DB 관련
    runtimeOnly 'com.mysql:mysql-connector-j'

    // Querydsl
    implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
    annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"

    // 이메일 모듈
    implementation 'org.springframework.boot:spring-boot-starter-mail'

    // 테스트 의존성
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    // 뷰 템플릿
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}

 

이렇게 추가하고 나면 이제 Repository단에서 import하여 아래와 같이 접근할 수 있게 된다.

import static ai.matics.mailservice.domain.QCertificationRequest.certificationRequest;


  public Long updateMailConfirmRequest(
      LocalDateTime confirmAt,
      String uuid
  ) {
    return queryFactory
        .update(certificationRequest)
        .set(certificationRequest.confirmYn, true)
        .set(certificationRequest.confirmAt, confirmAt)
        .where(certificationRequest.uuid.eq(uuid))
        .execute();
  }

 

profit! 

 

이제 이 코드가 정상적으로 빌드되면 로직과 다른부분에 문제가 없다면 런타임에서 오류가 없다 보장할 수 있다

 

적어도 위에 쓴 부분만큼은 말이다.

'개발 > java' 카테고리의 다른 글

리눅스 crontab으로 쉘 스크립트 실행 등록하기  (2) 2024.12.04
404 Not Found으로 전력투구  (1) 2024.03.26
JPA QUERYDSL의 LIKE 구현  (0) 2024.03.22
java 탭을 신설했다.  (0) 2023.06.01

 

예전부터 인프라는 꾸준히 다루었는데

 

여기는 좀 본격적으로 다뤄야할거같다. 

 

이번 기회에 aws를 자주 다루면서 든 소감은

 

인프라 엔지니어가 되고 싶다는 생각을 접게되었다. 

 

그냥 할줄아는 사람1이 되기로 결심했다 

 

쉽지않음.

 

 

 

 

'개발 > aws' 카테고리의 다른 글

프로메테우스 도입기 - 곱뺴기  (0) 2024.08.01
프로메테우스 도입기 - 시작  (0) 2024.07.30

 

소프트웨어 직군에서 종사하다보면 종종 아니면 늘상 그런일이 생긴다

 

우린 늘 이런 상황이다

 

이번 경우도 어쩌다보니 그렇게 됬다 처음엔 시스템 노드를 기반으로 EC2와 RDS에 대한 모니터링 시스템 구축이 끝인줄 

 

알았지만 막상 구축되고나니

 

"백엔드 시스템의 세부 정보사항들을 보고싶어요 왜 그런거 있잖아요.."

 

정리하자면 요구하는것은 이렇다.

 

1. 백엔드의 엔드포인트 시스템이 http 통신을 할때 각 url별 호출수가 많은것들을 보고 싶다.

 

2. 현재 백엔드 시스템을 많이 점유하고 있는 프로세스를 모니터링했으면 좋겠다.

 

3. http 통신때 어떤 url이 많은 자원을 소모하는지도 실시간으로 보고 싶다.

 

 

 

그렇다면 추가해야될 시스템과 추가적으로 알아야할 시스템은 이렇다.

 

 

1. 프로세스 익스포터

 

- 노드 익스포터는 노드의 현황을 프로메테우스가 폴링하게 해주는 도구다. 

 

이 도구는 시스템 노드의 정보를 담아 줄 뿐이지 시스템 노드 위에 작동하는 여러 계층의 프로세스까지 추적하진 못한다.

 

그렇기에 우리는 어플리케이션들의 프로세스 현황을 보려면 위와 같은 프로세스 익스포터를 추가로 설치해야한다.

 

 

2. 프로메테우스 라이브러리

 

- 추가적인 요청 사항을 수용하려면 우리는 거기에 더해 java단의 리소스 사용량의 추적도 필요하다. 다행스럽게도

 

Spring boot 환경이라면 쉽게 관련된 사용량을 노출 시켜주는 라이브러리들이 준비되어 있다 

 

 

 

처참한 도식을 한번보자

 

 

 

위와 같이 우리는 리눅스에 2개의 익스포터 그리고 프로메테우스 자바가 메트릭을 수집하면 프로메테우스가 

 

해당 데이터를 스크래핑하고 그라파나를 활용해 멋있게 시각화 화면 된다.

 

이 얼마나 멋지고 쉬운(?) 과정인가,

 

물론 나도 초장기 셋팅부터 여기까지만 온 상태다...암울..

 

앞으로 천천히 프로세스 익스포터와 프로메테우스 라이브러리를 설치하며 관련된 내용을 기록할 예정이다. 

 

관련된 가이드는 프로젝트 구축이 끝나면...정리해서 올릴 예정이다.

'개발 > aws' 카테고리의 다른 글

aws 카테고리 개설  (0) 2024.08.14
프로메테우스 도입기 - 시작  (0) 2024.07.30

사내에 마땅한 모니터링 도구가 없었다.

 

그래서 모니터링을 도입하자! 라고 건의하니 그럼 너가해라! 라는 평범한 플로우로 흘러갔다

 

늘 이런 새로운 도전은 스트레스와 성취를 동반한다. 

 

 

우선 나는 프로메테우스와 그라파나를 중점적으로 살펴보았다. 

 

그렇게 해서 아래와 같은 결과가 나왔다. 

 

  • 필요성
  1. 현재 사내에 서비스 이상 감지를 할 수 있는 수단이 없어 장애 대응의 신속성이 떨어짐
  2. 서비스 현황을 참고하여 사용량 이상 구간을 사전에 탐지 예방하기 위함
  3. RDS 및 서비스의 사용량을 추산하여 사용량을 조정하여 지출 비용 감소

 

  • 설계 방향

처참한 도식표현

 

위 설계를 하게된 이유는 아래와 같습니다

  • 우리는 시스템 간의 결속력 혹은 의존성이 떄론 장점이 되지만 떄로는 단점이 된다는 사실을 알고있다 그런 관점에서 볼때 이러한 시스템은 뛰어난 작동 보장성을 담보받아야한다. 즉 모니터링 시스템이 잘못되어도 알람은 어떤 경우에도 와야하며, 알람시스템이 잘못되어도 모니터링 시스템은 가동해야한다

장점

  1. 독립성: 모니터링과 알람 시스템이 독립적으로 운영되기 때문에 한 시스템에 문제가 발생해도 다른 시스템은 영향을 받지 않습니다. 이는 시스템의 신뢰성을 높입니다.
  2. 유연성: 각각의 시스템이 자신들의 강점을 최대한 활용할 수 있습니다. Prometheus-Grafana는 강력한 모니터링과 시각화를 제공하고, AWS CloudWatch는 알람 설정과 자동화된 대응을 지원합니다.
  3. 확장성: 각 시스템이 독립적으로 확장 가능하며, 필요에 따라 모니터링이나 알람 설정을 유연하게 변경할 수 있습니다.
  4. 전문성 활용: 각 도구가 잘하는 부분에 집중할 수 있습니다. Prometheus-Grafana는 다양한 메트릭 수집과 시각화에, AWS CloudWatch는 알람과 AWS 리소스 모니터링에 특화되어 있습니다.
  5. 비용 효율성: AWS 리소스에 대한 알람만 CloudWatch를 통해 처리하기 때문에, Prometheus의 모니터링 비용과 CloudWatch의 알람 비용을 따로 관리할 수 있습니다.

단점

  1. 관리 오버헤드: 두 시스템을 따로 설정하고 유지보수해야 하기 때문에 관리에 더 많은 시간이 필요할 수 있습니다.
  2. 중복 모니터링 위험: 동일한 리소스를 두 시스템에서 중복 모니터링할 경우, 불필요한 알람이 발생할 수 있습니다. 이를 방지하기 위해 모니터링 항목을 명확히 구분해야 합니다.
  3. 지연 시간: 두 시스템 간의 데이터 전송이 없기 때문에 각각의 시스템에서 발생하는 지연 시간은 용인 가능하더라도, 전체적인 알람 반응 시간에 영향을 줄 수 있습니다.
  4. 비용: AWS CloudWatch, SNS, Lambda 사용에 따른 추가 비용이 발생할 수 있습니다.

결론

  • 용인 가능한 수준: 언급된 단점들은 대부분 용인 가능한 수준입니다. 특히, 관리 오버헤드나 중복 모니터링은 설계와 운영상의 주의로 충분히 관리할 수 있습니다.
  • 장점 활용: 설계의 장점을 최대한 활용하면, 보다 신뢰성 있고 유연한 모니터링 및 알람 시스템을 구축할 수 있습니다.

 

Q : 프로메테우스-그라파나 시스템의 과부화는?

A : 프로메테우스는 대규모 모니터링은 로드밸런서 혹은 샤딩 시스템의 구축을 권장합니다 샤딩은 하나의 프로메테우스가 모니터링할 영역을 나눠 맡는 시스템의 아키텍처로 대규모에는 해당 관리를 권장하지만 우리의 모니터링은 그렇게 많은 리소스가 필요치않다고 판단하여 중규모 관리 시스템인 그라파나와 프로메테우스 둘의 시스템을 독립시키는 방향으로 가게 되었습니다. 향후 시스템의 규모가 더 작아져도 괜찮다고 판단될 경우 소규모 시스템 권장 방향인 하나의 EC2에 그라파나와 프로메테우스를 몰아 설치하는 방법으로 전환될것입니다.

 

 

Q : 데이터의 보관은? EC2 용량은 그리 넉넉하지 않지않나?

A : 프로메테우스의 자체적인 롤링과 보관은 사용자 설정에 따라 대부분 다릅니다 별도의 시계열 데이터 베이스 (thanos,InfluxDB,cortex)를 사용하지 않아도 중규모의 모니터링은 자체 내장된 시계열

데이터 베이스로도 충분히 관리가 가능합니다. 이후 누적되는 데이터의 수량,요구사항에 맞추어

추가적인 데이터베이스의 관리가 필요하다 요구되면 전환될 수 있습니다.

(프로메테우스의 공식문서에서는 데이터의 장기보관화와 데이터의 불변성을 필요로하다면 RAID 구성의 저장 설계를 할것을 권장하지만 아니라면 내부 데이터베이스로도 충분하다는 입장입니다)

 

부연 설명

노드익스포터: 작동하는 서비스의 백그라운드에서 가동하여 현재 시스템의 사용정보를 외부로 전달하는 리눅스 프로그램입니다 바이너리 파일로 구성되어있으며 백그라운드에서 작동합니다

그라파나 : 시계열 데이터를 그래프화 하여 EC2별 , RDS별로 대쉬보드 편집을 하여 보기 쉽게 관리해주는 모니터링 오픈소스입니다 자체적으로는 데이터를 노드익스포터에서 가져 올 수 없습니다.

프로메테우스 : 노드익스포터가 보내온 시계열 데이터를 정리 및 보관하며 일부분 사용자에게 노출 시켜줍니다. 그라파나의 시각화 기능이 강력하여 대부분 노드 익스포터와 그라파나를 이어주는 게이트웨이의 역할로 많이 사용합니다.

 

 

 

실제 뭐..이런 고민들과 설계를 결정하며 그 이유에는 이런것이 있다~ 라고 설명하기 위해 같은 엔지니어들에게 전달할

 

요량으로 작성하다보니 내용도 좀 지저분하고 그런데 대충 그렇다~ 정도만 이해하면될거같다.

 

그렇게해서 지금 초안 작업이 마무리되어 가동 중 인 서비스 하나를 테스트로 그라파나까지 연동이 되어 그래프까지 잘나온다

 

보다 절차적인 방법은 커밍쑨 

 

아마..

 

 

'개발 > aws' 카테고리의 다른 글

aws 카테고리 개설  (0) 2024.08.14
프로메테우스 도입기 - 곱뺴기  (0) 2024.08.01

 

 

사내에서 오래된 아주 레거시 프로젝트가 있는데(문젠 그걸 아직도 현역으로 굴리는곳이 있다는것이다)

 

이클립스로 프로젝트가 세팅되어 인텔리제이나 vscode같은 툴로 해본적이 없는데 

 

어느날 이클립스를 켜보니 응용 프로그램을 실행할 수 없습니다 이러면서 뻗는것 아닌가

 

다행스럽게도 구글링 해보니 나와 같은 사람이 많다

 

 

해결 방법은 터미널에 아래 명령어를 입력하면된다

 

codesign --force --deep --sign - /Applications/Eclipse.app/Contents/MacOS/eclipse

 

 

 

 

막상 오류났을떄 심장이 덜컹했는데 예상외로 이런 문제를 겪는사람이 많다는 사실에 놀랬고 다들 덤덤하게 쓰는것도 웃기네 ㅋㅋㅋ

 

env를 폴더로 관리하여 실제 관리해야하는(독립형 시스템이기 때문에)지점 마다 설정 파일을 따로 관리하여 내부 git에 

 

업로드해 관리하기로 했는데

 

폴더로 옮기자마자 먹통이 되어버렸다 

 

답은 package.json의 스크립트 명령어가 문제였다

 

"start:dev": "env-cmd -f environments/.env.dev concurrently \"npm run start\" \"wait-on http://localhost:3000 && electron \"",

 

 

env의 설정은 스크립트 명령어 전에 작동해야되니 앞에 쓰는게 맞지만 단순히 실행시킬때와 빌드때는 또 이야기가 다르다

 

"build:electron:win64": "env-cmd -f environments/.env.prod rm -rf dist && npm run build && electron-builder --config ./electron-build.yml --win nsis:x64",

 

위와 같은 스크립트는 실제로 실행해보면 env의 값이 undefined로 표시되는데 이유는 쉘 스크립트의 작동 방식과 연관이 있다.

 

쉘스크립트내에서는 상속관계가 있어서 부모-자식 간의 환경 변수 전달은 가능하지만 위와 같은 케이스는 env가 하나의 독립된 

 

스크립트로 부모와 자식관계로  이렇게 동작하는 이유는 프로세스 트리 구조와 프로세스 상속 규칙 때문이다

 

새 프로세스는 부모의 환경변수를 상속받지만, 새 셸은 부모 셸의 모든 환경을 물려받기 때문이고 이를 해결하려면

 

환경변수를 자식 프로세스에 전달하려면 직접 자식을 실행하는 것이 아니라 새 셸을 열고 그 안에서 실행해야 한다 

 

실제로 잘 작동되는 스크립트 명령어는 아래와 같다

 

"build:electron:win64": "rm -rf dist && env-cmd -f environments/.env.prod npm run build && electron-builder --config ./electron-build.yml --win nsis:x64",

 

 

 

어딘가에서 개고생하는 일렉트론 개발자들 화이팅

 

 

 

 

 

+ Recent posts