대덕소프트웨어마이스터고등학교 SMS(학교 지원 시스템) 서버 Health Check 서비스
-
SMS(School Management System)는 대덕소프트웨어마이스터고등학교 전공 동아리 DMS에서 개발하여 현재 운영하고 있는 학교 지원 시스템입니다.
-
SMS Health Check는 SMS 서버를 운영중인 환경과 서버를 구성중인 여러 서비스들의 상태를 주기적으로 관리하는 플러그인 식의 서비스입니다.
-
특정 서비스의 상태 확인 결과가 특정 기준을 통해 정상적이지 않다고 판단이 되면 해당 서비스의 상태 회복을 위한 작업을 수행합니다.
1. System Check
- disk check
- 디스크 사용 용량 특정 수치 초과 시 알람 발행 후 Docker Prune 실행
- 디스크 사용의 주요 원인에는 로그 및 DB 데이터 또한 존재하지만, 해당 데이터를 건드는건 위험하다 판단하여 Docker Prune만 실행
- memory check
- 총 메모리 사용량 특정 수치 초과 시 알람 발행 후 메모리 과다 사용 프로세스 재부팅
- 프로세스 메모리 사용 조회 및 재부팅은 Docker Engine API를 통해 수행
- 참고로, 서버 구성에 있어서 부재가 발생하면 안되는 서비스들은 재부팅하지 않음
- elasticsearch check
- Elasticsearch Shard 갯수 특정 수치 초과 시 알람 발행 후 Jaeger Index 삭제
- Jaeger에서 매일 새로운 Index를 생성하여 데이터를 저장하기에 주기적으로 관리 필요
- 예전에 생성된 Index부터 삭제를 진행하며, 최근 한 달 내에 생성된 Index는 삭제되지 않음
- swarmpit check
- Swarmpit App 컨테이너 메모리 사용량 특정 기준 초과 시 알람 발행 후 해당 서비스 재부팅
- Swarmpit App의 경우, 메모리 사용량이 지속적으로 증가하기 때문에 특정 수치에 도달할 때 마다 재부팅이 필요함
- consul check
- Consul에 작동되지 않는 노드가 등록되었다면 알람 발행 후 해당 노드 등록 해제
- 또한, MSA 상의 서비스별로 등록된 노드가 존재하지 않는 경우 알람 발행 후 해당 서비스 재부팅
- 작동되지 않는 노드인지는 해당 노드와 gRPC 연결 시도를 통해 판별
- 노드 부재시에는, 서비스 재부팅을 함으로써 재시작 시점에 스스로 노드를 등록하게 함
- 기능에 따라 계층을 분리하고, 분리된 계층별로 패키지를 생성하여 해당 패키지에 구현
- 직접적인 타입의 명시가 아닌 인터페이스 추상화를 통해 느슨한 상하위 계층 간의 의존 관계 형성
- 상위 계층에서, 하위 계층의 처리 방식을 모른채로 데이터 처리의 책임을 빌려주는 구조
- 따라서 계층끼리의 의존성을 편리하게 관리하기 위해서 모든 의존성 주입은 main에서 발생
- 만약 인터페이스를 하위 계층이 소유하고 있다면, 여전히 하위 계층에 명시적으로 결합된 상태
- 따라서 인터페이스 소유권을 사용하는 계층으로 옮김으로써, 하위 계층과의 명시적인 결합을 완전히 끊을 수 있다.
- SOLID 중 DIP(의존성 역전) 원칙으로, 사용할 메서드들만 추상화하여 의존성을 생성할 수 있다는 장점 또한 존재한다.
- 예외) domain model 관련 패키지(repo, use case)들에 대한 추상화는 domain 패키지에 묶어서 관리
- app
- main function을 가지고 있는 main package로, Health Check를 실행시키는 시작점
- 모든 의존성 객체 생성 및 주입이 여기서 일어나며, domain 패키지를 제외한 다른 패키지를 명시적으로 import하는 유일한 패키지
- app/config
- app(main) 패키지에서 사용하는 config value들을 관리하고 반환하는 패키지
- 싱글톤 패턴으로 구현되어 있으며, environment variable 또는 fixed value 반환
- 특정 인터페이스의 구현체가 아니라, 단순히 app 패키지에서 명시적으로 불러와서 사용하는 객체이다.
- domain
- 특정 domain에서 사용할 model 정의와 그와 연관된 계층들(repo, use case)을 추상화하는 것이 필요
- 따라서 이와 관련된 것을 해당 패키지에서 묶어서 관리하며, 추상화에 대한 구현은 domain 이름으로 된 패키지 내부에서 진행한다.
- 결론적으로 도메인에 대한 model struct, repository와 usecase interface를 정의한다.
- 현재 추상화 및 구현이 완료된 domain에는 syscheck와 srvcheck가 있다.
- syscheck
- system check 기능의 domain에 대한 추상화를 실제로 구현 하는 패키지
- domain 패키지에서 정의한 추상화에 의존하고 있으며, 네 가지의 하위 패키지로 구성되어있다.
- repository
- domain 패키지에서 추상화된 system check 관련 repository들을 구현하는 패키지
- domain 패키지에 정의된 model struct에 의존하고 있으며, 데이터를 명령 혹은 조회하는 기능의 계층이다.
- 현재로써는 elasticsearch를 저장소로 사용하는 구현체만 존재한다.
- usecase
- domain 패키지에서 추상화된 system check 관련 usecase들을 구현하는 패키지
- domain 패키지에 정의된 repository 추상화에 의존하고 있으며, 실질적인 business logic을 처리하는 기능의 계층이다.
- 또한 외부 서비스들에 대해 추상화한 agency 인터페이스에도 의존하고 있으며, 해당 추상화에 대한 소유권은 해당 패키지가 가지고 있다.
- 외부 서비스들의 추상화에 대한 구현체는 아래의 Agent 패키지에서 확인할 수 있다.
- delivery
- 특정 API로부터 들어온 데이터를 usecase layer으로 전달하는 기능의 계층
- 따라서, domain 패키지에 정의된 usecase 추상화에 의존하고 있다.
- 해당 프로젝트 내에서 최상위 계층으로, 어떠한 추상화에 대한 구현체가 아니다.
- config
- syscheck의 모든 하위 패키지에서 사용하는 config value들을 관리하고 반환하는 패키지
- 싱글톤 패턴으로 구현되어 있으며, config.yaml 파일에 설정된 값 또는 기본 값 반환
- repository, usecase, delivery 패키지에서 추상화된 인터페이스들을 모두 구현하고 있음.
- 같은 도메인 내에서도 기능들끼리의 연관성을 없애기 위해, 모든 기능들에 대한 추상화와 구현체들이 서로 다른 타입으로 분리되어있다.
- srvcheck
- syscheck 패키지와 비슷하게, service check 기능의 domain에 대한 추상화를 구현하는 패키지이다.
- syscheck 패키지와 하위 구성 또한 동일하지만, 서로 간의 결합이 전혀 존재하지 않다.
- consul
- consul API를 이용하여 consul agency 인터페이스를 구현하는 agent 객체를 정의하는 패키지
- consul에 등록된 노드 조회, 노드 등록 해제 등의 기능이 있다.
- docker
- docker engine API를 이용하여 docker agency 인터페이스를 구현하는 agent 객체 정의
- 특정 컨테이너의 ID 및 메모리 사용량 조회, 컨테이너 삭제 등의 기능이 있다.
- elasticsearch
- elasticsearch API를 이용하여 elasticsearch agency 인터페이스를 구현하는 agent 객체 정의
- cluster 정보 조회, indices 조회 및 삭제 등의 기능이 있다.
- grpc
- gRPC SDK를 이용하여 gRPC agency 인터페이스를 구현하는 agent 객체 정의
- connection check를 위한 gRPC ping을 발행하는 기능이 있다.
- slack
- slack API를 이용하여 slack agency 인터페이스를 구현하는 agent 객체 정의
- slack app을 이용하여 특정 채널에 메시지를 전송하는 기능이 있다.
- system
- linux kernel API를 이용하여 각종 system agency 인터페이스를 구현하는 agent 객체 정의
- cpu 및 memory 사용량 조회, disk 잔여 용량 조회 등의 기능이 있다.
- json
- reqBodyWriter 인터페이스를 json 형식으로 구현하는 객체를 정의하는 패키지
- 위의 패키지들과는 달리, 외부 서비스를 추상화한 인터페이스에 대한 구현체는 아니다.
- 구현체인 mapWriter는 key값에 dot으로 depth가 구분된 map 타입의 변수를 json 형식으로 변환해준다.
- Ex) map["a.b": "c", "a.b": "d"] -> map["a": map["b": []string{"c", "d"}]]
의존성 그래프는 godepgraph에서 제공하는 툴을 통해 생성하였습니다.