[TIL] 24.12.02 MON

GDORI·2024년 12월 2일
0

TIL

목록 보기
120/143
post-thumbnail

헬스체크 서버 기본설정

오늘은 헬스체크 서버 기본설정하고 서비스 구현하는 작업을 진행했다. 요즘 TCP만 하다가 API 서버 만드려고 하니
막히는 부분이 많아 조금밖에 구현하지 못했다.

1. 서버 설정

Express 서버를 설정하고, 라우터와 에러 핸들러 미들웨어를 설정했다.

import { config } from './config/config.js';
import express from 'express';
import router from './routes/index.router.js';
import errorHandlingMiddleware from './middlewares/error-handling.middleware.js';

const app = express();

app.use(express.json());
app.use('/', router);
app.use(errorHandlingMiddleware);

app.listen(config.server.port, config.server.host, () => {
  console.log(`SERVER ON - ${config.server.host}:${config.server.port}`);
});

2. 라우터 설정

각 라우트는 인증 미들웨어와 컨트롤러 메서드를 사용하여 요청을 처리한다.

import express from 'express';
import { CheckController } from '../controllers/check.controller.js';
import authMiddleware from '../middlewares/auth.middleware.js';
const router = express.Router();

const checkController = new CheckController();

router.get('/svrStatus', authMiddleware, checkController.getSvrStatus);
router.get('/availableSvr', authMiddleware, checkController.getAvailableSvr);
router.post('/svrStatus', authMiddleware, checkController.setSvrStatus);

export default router;

3. 인증 미들웨어

요청 헤더에서 API 키를 추출하고, 유효성을 검사한 후 다음 미들웨어로 전달한다.

import { checkHashed } from '../utils/auth/checkHashed.util.js';
import CustomErr from '../utils/error/CustomErr.js';

export default async function (req, _, next) {
  try {
    const { authorization } = req.headers;

    if (!authorization)
      throw new CustomErr('요청한 사용자의 API-KEY가 없습니다.', 401);

    const isValid = await checkHashed(authorization);

    if (!isValid)
      throw new CustomErr('일치하지 않은 API-KEY 정보입니다.', 401);

    next();
  } catch (err) {
    next(err);
  }
}

5. 서비스 및 모델 구현

서버 상태를 저장하고, 유효성을 검사하며, 필요한 경우 에러를 발생시킨다.

import { svrListModel } from '../models/svrList.model.js';
import { svrPortListModel } from '../models/svrPortList.model.js';
import CustomErr from '../utils/error/CustomErr.js';

class checkSvrService {
  constructor() {
    this.#svrListModel = new svrListModel();
    this.#svrPortListModel = new svrPortListModel();
    this.lowServer = null;
    this.lowCnt = Infinity;
    this.portNum = 5000;
  }

  setSvrStatus(ip, cpuUsage, memUsage, sessionCnt) {
    const ipAddress = ip.split('.');
    const incorrectIp = ipAddress.some((ip) => ip < 0 || ip > 255);
    const incorrectCpu = cpuUsage > 100 || cpuUsage < 0;
    const incorrectMem = memUsage > 100 || memUsage < 0;

    if (ipAddress.length < 4 || incorrectIp)
      throw new CustomErr('아이피 형식이 올바르지 않습니다.', 400);
    if (incorrectCpu || incorrectMem)
      throw new CustomErr('서버 입력 정보가 올바르지 않습니다.', 400);
    if (!this.#svrListModel.has(ip)) this.setSvrPort(ip, this.portNum);

    const result = this.#svrListModel.set(ip, { cpuUsage, memUsage, sessionCnt });
    if (!result) throw new CustomErr('서버 정보 입력에 실패하였습니다.', 500);
    if (cpuUsage <= 90 && memUsage <= 90 && sessionCnt < this.lowCnt) {
      this.lowServer = ip;
      this.lowCnt = sessionCnt;
    }
  }
}

export default checkSvrService;
export class svrListModel {
  #svrList;
  constructor() {
    this.#svrList = new Map();
  }

  get() {
    return Object.entries(this.#svrList);
  }

  has(ip) {
    return this.#svrList.has(ip);
  }

  set(ip, infos) {
    this.#svrList.set(ip, infos);
    const verification = this.#svrList.get(ip);
    if (verification === infos) return true;
  }

  find(ip) {
    return this.#svrList.get(ip);
  }

  delete(ip) {
    if (this.#svrList.has(ip)) this.#svrList.delete(ip);
  }
}
export class svrPortListModel {
  #svrPort;
  constructor() {
    this.#svrPort = new Map();
  }

  getPorts() {
    return this.#svrPort.values();
  }

  find(ip) {
    return this.#svrPort.get(ip);
  }

  set(ip, port) {
    this.#svrPort.set(ip, port);
  }

  delete(ip) {
    if (this.#svrPort.has(ip)) this.#svrPort.delete(ip);
  }
}

내일중으로 GCP API와 연동해서 인스턴스 자동생성 및 제거 구현할 예정이다.

profile
하루 최소 1시간이라도 공부하자..

0개의 댓글