정해진 시간에 scp로 파일을 받고 DB에 적재하기 (nodejs)

Singsoong·2022년 12월 2일
0

nodejs

목록 보기
3/3

📌 구현해야 하는 것 (목표)

  • hourlyJob : 매 시간마다 원격 서버에서 scp를 통해 파일을 받아와 필요한 데이터만 추출하여 DB에 적재
  • dailyJob : 하루에 한 번, 매일 원격 서버에서 scp를 통해 파일을 받아와 필요한 데이터만 추출하여 DB에 적재

📌 사용되는 라이브러리

  • node-schedule : 설정한 시간에 맞춰 job을 실행시켜 준다.
  • node-scp : 설정한 host에 접속하여 타겟 파일을 다운받는다.
$ npm install node-schedule
$ npm install node-scp

📌 scpService

  • scpService에는 매 시간마다 특정 파일을 다운하는 함수와, 하루에 한번 특정 파일을 다운하는 함수를 구현한다.

📄 scpDownloadHourly.js

async function scpDownloadHourly(){
  try {
    const client = await Client({
      ...config.scp.primary,
      port: 22,
    });
    await client.downloadFile(
      `다운받을 원격 서버의 파일 경로`,
      `서버 내 저장 할 경로`
    );
    client.close();
    return 1; // 성공적으로 다운을 받았을 경우 true를 리턴
  } catch (error) {
    console.error(error);
    return 0; // 다운을 실패했을 경우 false를 리턴
  }

📄 scpDownloadDaily.js

  • 원격 서버에서 다운 받는 파일의 이름이 날짜 형식인데, 매일 바뀌어서 날짜(DOY)를 계산해주는 함수를 추가 작성했다.
async function scpDownloadDaily() {
  let nowDOY = returnDOY();
  let year = returnYear();

  try {
    const client = await Client({
      ...config.scp.primary,
      port: 22,
    });
    await client.downloadFile(
      `다운받을 원격 서버의 파일 경로`, //`/home/user/${nowDOY}.${year}o.txt`,
      `서버 내 저장 할 경로` // `${__dirname}/filename.txt`
    );
    client.close();
    return 1; // 성공적으로 다운을 받았을 경우 true를 리턴
  } catch (error) {
    console.error(error);
    return 0; // 다운을 실패했을 경우 false를 리턴
  }
}

function returnDOY() {
  let now = new Date();
  let start = new Date(now.getFullYear(), 0, 0);
  let diff =
    now -
    start +
    (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
  let oneDay = 1000 * 60 * 60 * 24;
  let day = Math.floor(diff / oneDay);
  return day - 1;
}

function returnYear() {
  let now = new Date();
  let fullYear = String(now.getFullYear());

  return fullYear.slice(2, 4);
}

📌 Read File

  • 각 scpService가 정상적으로 처리가 됐다면 해당 파일을 읽는다.

📄 readHourlyFile.js

  • 다운받은 파일을 fs 모듈을 통해 읽어 리턴한다.
function readHourlyFile() {
  let modelData, seriesData;
  try {
    modelData = fs.readFileSync(__dirname + "/SLT1.model", "utf-8");
    seriesData = fs.readFileSync(__dirname + "/SLT1.series", "utf-8");
  } catch (err) {
    throw new Error(err);
  }
  return [modelData, seriesData];
}
  • 이와 비슷하게 readDailyFile.js 도 작성한다.

📌 Insert data to DB

  • 읽은 파일을 파싱 알고리즘을 돌려 필요한 데이터를 추출하고, DB에 적재한다.
  • Sequelize를 사용한다.

📄 insertHourlyData.js

function insertData(data){
  db.log.create({
    ...
  });
}

📌 JOB 구성

  • 이 과정들을 JOB으로 구성하여 단계별로 수행한다.

📄 dailyJob

function dailyJob(){
  // 먼저 scp를 통한 다운로드를 수행한다.
	scpDownloadDaily().then((flag) => {}){
    // 다운로드가 정상적으로 수행이 됐다면,
      if (flag) {
        // fs 모듈을 통해 데이터를 읽고
      let data = readDailyFile(); 
        // 필요한 데이터를 추출한 뒤
      let parsingData = parsing();
        // DB에 데이터를 넣는다.
      insertData(parsingData);
      }
    }
}

📌 Scheduler 설정

  • dailyJob과 hourlyJob의 시간을 설정한다.
const slackScheduler = () => {
  /* 9시 40분 schedule, 이 시간은 UTC TIME임!  */
  schedule.scheduleJob("40 0 * * *", () => {
    dailyJob();
  });
  /* 매 시 30분 schedule */
  schedule.scheduleJob("30 */1 * * *", () => {
    hourlyJob();
  });
};
  • hourlyJob은 상관없었는데, dailyJob의 시간을 설정하면서 알게 된 것은 AWS 서버에 소스를 올렸을 때 dailyJob이 제 시간에 작동을 안했다. 로컬에서는 분명 작동이 잘됐는데.
  • 알고보니 로컬에서는 KST 시간으로 작동했지만, AWS에는 서버가 국내에 있는것이 아닌것 같았다. UTC time으로 시간을 설정하니까 잘 작동하였다.
  • 위 문제를 해결하기 위해 node-schedule-tz라는 라이브러리를 통해 KST를 설정할 수 있지만, 굳이 사용할 필요성을 못느껴 코드에서 UTC time으로 설정하였다.

📌 완성

  • 매 시간마다 데이터를 자동으로 받아왔고, 화면에서 차트가 업데이트 되었다.
profile
Web Developer

0개의 댓글