관리 메뉴

SIMPLE & UNIQUE

3-4강 : 배치(스케줄러) 구현, EC2서버에 배포 본문

탈잉 강의 자료/2020_비전공자도 가능한 웹 프로젝트

3-4강 : 배치(스케줄러) 구현, EC2서버에 배포

착한코딩 2020. 8. 3. 22:16

3_4강 소스.zip
1.08MB
3_4강 소스_덮어쓰기.zip
0.00MB

3_4 목표 : 사용자가 접속하지 않아도 특정 시간에 코드가 실행되는 배치를 구현한다. CRON이라는 스케줄러를 사용해 실행 시간 조건을 설정한다. 로컬에서 개발완료 후 EC2서버에 배포한다.

 

1. cron을 사용해 스케줄러를 구현한다.

  server.js에 batch 라우터를 추가한다.

var express = require('express');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var swtoolRouter = require("./routes/SwtoolRout");
var fileuploadRouter = require("./routes/UploadRout");
require("./routes/BatchRout");

var app = express();

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use("/api/Swtool", swtoolRouter);
app.use("/api/upload", fileuploadRouter);
app.use(express.static("./uploads"));

const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));

  node 경로 C:\react200\routes에 BatchRout.js 파일을 생성하고 아래 코드를 붙여넣는다. cron을 사용하기 위해 node-cron을 설치한다.

npm install --save node-cron

  cron.schedule('* * * * *')은 1분마다 스케줄러를 실행하라는 뜻인데, 로컬에서 테스트용으로 사용하고, EC2 서버에 올릴때는 적절한 실행시간을 세팅하도록 한다.

  아래 코드는 정의한 시간에 BatchMapper.xml에서 insertBatchlog라는 mapperID를 찾아 insert 쿼리를 실행시킬 것이다.

 

 

var express = require('express');
var router = express.Router();
var cron = require('node-cron');

// cron.schedule('5 * * * *', () => {
// cron.schedule('5 0 * * *', () => {
cron.schedule('* * * * *', () => {
  var mapper = 'BatchMapper';//mybatis xml 파일명
  var crud = 'insert';//select, insert, update, delete 중에 입력
  var mapper_id = 'insertBatchlog';

  var param = { is_Batchnm: '테스트 배치', is_Batchlog: '테스트 배치가 정상 실행되었습니다.' };
  console.log('#######  배치 실행 / 테스트 배치 #######');

  const mysql = require('mysql');
  const mybatisMapper = require('mybatis-mapper');

  const connection = mysql.createConnection({
    host: "react200.#########.ap-northeast-2.rds.amazonaws.com",
    port: "3306",
    database: 'react',
    user: "admin",
    password: "react200RDS"
  });

  mybatisMapper.createMapper(['./models/'+mapper+'.xml']);
  var time1 = new Date();
  console.log('## '+time1+ ' ##');
  console.log("\n Called Mapper Name  = "+mapper);

  var format = { language: 'sql', indent: '  ' };
  var query = mybatisMapper.getStatement(mapper, mapper_id, param, format);
  console.log("\n========= Node Mybatis Query Log Start =========");
  console.log("* mapper namespce : "+mapper+"."+mapper_id+" *\n");
  console.log(query+"\n");

  connection.connect();
  connection.query(query, function (error, results, fields) {
    if (error) {
      console.log("db error************* : "+error);
    }
    var time2 = new Date();
    console.log('## '+time2+ ' ##');
    console.log('## RESULT DATA LIST ## : \n', results);
    console.log("========= Node Mybatis Query Log End =========\n");
  });
  connection.end();
});

module.exports = router;

 

## 참고 ##

 cron예시

 cron에 쓰이는 특수문자

 * : 모든 값을 뜻합니다.

 ? : 특정한 값이 없음을 뜻합니다. 

 - : 범위를 뜻합니다. (예) 월요일에서 수요일까지는 MON-WED로 표현

 , : 특별한 값일 때만 동작 (예) 월,수,금 MON,WED,FRI 

 / : 시작시간 / 단위  (예) 0분부터 매 5분 0/5

 L : 일에서 사용하면 마지막 일, 요일에서는 마지막 요일(토요일)

 W : 가장 가까운 평일 (예) 15W는 15일에서 가장 가까운 평일 (월 ~ 금)을 찾음

 # : 몇째주의 무슨 요일을 표현 (예) 3#2 : 2번째주 수요일

 

  node 경로 C:\react200\models에 BatchMapper.xml 파일을 추가해 아래 코드를 붙여넣는다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BatchMapper">  
  <insert id="insertBatchlog"> 
    INSERT INTO react.react_batch_log
    (
        batch_cd
        , batch_nm
        , batch_log
        , reg_date
    )
    VALUES (
        CONCAT("BL",DATE_FORMAT(now(), '%Y%m%d%H%i%s'))
        , #{is_Batchnm}
        , #{is_Batchlog}
        , DATE_FORMAT(now(), '%Y%m%d%H%i%s')
    )
  </insert>
</mapper>

workbench를 실행해 react_batch_log 테이블을 생성한다.

use react;
CREATE TABLE `react_batch_log` (
  `batch_cd` varchar(100) COMMENT '배치 코드',
  `batch_nm` varchar(100) DEFAULT NULL COMMENT '배치명',
  `batch_log` varchar(100) DEFAULT NULL COMMENT '배치내용',
  `reg_date` varchar(100) DEFAULT NULL COMMENT '등록날짜',
  PRIMARY KEY (`batch_cd`)
);
ALTER TABLE react.react_batch_log convert to charset utf8;

2. 서버를 실행해 1분마다 insert 문이 실행되는 것을 확인한다.

 설정한 시간마다 실행되는 쿼리를 확인한다.

 

실제로 table에 insert된 데이터를 확인한다.

 

3. ec2 서버에 스케줄러 관련 파일들을 업로드한다.

추가/수정된 파일(server.js, /routes/BatchRout.js, /models/BatchMapper.js)만 따로 새로운 폴더에 옮기고, tar 파일로 압축한다.

mobaXterm Sftp로 서버 경로를 보면, 아래와 같이 Owner와 Group권한이 모두 root이다.

Sftp 접속 계정은 ubuntu이기 때문에, 수정권한이 없다.

서버 폴더에 파일을 추가하기 위해서 Group권한을 ubuntu계정에 부여한다.

 

SSH 터미널 접속 후, 권한을 부여할 폴더 상위 경로에서 아래 명령어를 실행한다.

chown 명령어는 taling0127 이라는 폴더와 하위경로에 있는 폴더/파일들의 권한을 수정하는데

Owner는 root 계정에 Group은 ubuntu계정에 부여하겠다는 뜻이다.

 

chmod 명령어는 앞에 7은 root, 두번째 7은 group 권한을 의미하는데

## 참고 ##

7 숫자의 의미 : rwx권한 (read,write,execute)을 2진법으로 변환하면 111 > 십진법으로 변환하면 7

// Onwer 권한은 root계정, Group 권한은 ubuntu계정으로 부여 
chown -R root:ubuntu taling0127
// Onwer와 Group에 모두 읽기/쓰기/실행 권한을 부여한다.
chmod -R 770 taling0127

권한 부여 후 SFTP로 돌아오면 Group권한이 ubuntu로 수정된 것을 확인할 수 있다.

tar파일을 node 경로에 위치시킨다.

SSH 터미널에서 node경로에 위치한 tar파일 압축을 해제한다.

## 참고 ##

압축할 때 알집을 사용하면 tar파일 압축을 해제할 때, 압축한 최상위 폴더는 제외하고 하위 폴더/파일만 아래와 같이 꺼내진다. 이때 장점은 압축해제와 동시에 기존 파일들을 덮어쓰면서 소스가 반영된다는 것이다.

반디집은 초기 세팅이 최상위 폴더가 포함돼 압축해제가 된다.

node 경로에서 node-cron을 설치해준다.

npm install --save node-cron

설치완료 후, 서버를 구동하면 1분마다 스케줄러가 실행되는 것을 확인할 수 있다.

4. BatchRout.js 에서 cron을 매일 1회만 실행하도록 수정 후, ec2 서버를 계속 구동시킨다.

  BatchRout.js 파일에서 아래와 같이 00시 5분에만 실행하도록 코드를 수정한다.

var express = require('express');
var router = express.Router();
var cron = require('node-cron');

// cron.schedule('5 * * * *', () => {
cron.schedule('5 0 * * *', () => {
// cron.schedule('* * * * *', () => {
  var mapper = 'BatchMapper';//mybatis xml 파일명
  var crud = 'insert';//select, insert, update, delete 중에 입력
  var mapper_id = 'insertBatchlog';

  var param = { is_Batchnm: '테스트 배치', is_Batchlog: '테스트 배치가 정상 실행되었습니다.' };
  console.log('#######  배치 실행 / 테스트 배치 #######');

  const mysql = require('mysql');
  const mybatisMapper = require('mybatis-mapper');

  const connection = mysql.createConnection({
    host: "react200.#########.ap-northeast-2.rds.amazonaws.com",
    port: "3306",
    database: 'react',
    user: "admin",
    password: "react200RDS"
  });

  mybatisMapper.createMapper(['./models/'+mapper+'.xml']);
  var time1 = new Date();
  console.log('## '+time1+ ' ##');
  console.log("\n Called Mapper Name  = "+mapper);

  var format = { language: 'sql', indent: '  ' };
  var query = mybatisMapper.getStatement(mapper, mapper_id, param, format);
  console.log("\n========= Node Mybatis Query Log Start =========");
  console.log("* mapper namespce : "+mapper+"."+mapper_id+" *\n");
  console.log(query+"\n");

  connection.connect();
  connection.query(query, function (error, results, fields) {
    if (error) {
      console.log("db error************* : "+error);
    }
    var time2 = new Date();
    console.log('## '+time2+ ' ##');
    console.log('## RESULT DATA LIST ## : \n', results);
    console.log("========= Node Mybatis Query Log End =========\n");
  });
  connection.end();
});

module.exports = router;

로컬에서 cmd창에서 yarn dev로 서버를 구동시키고, cmd 창을 닫으면 서버가 꺼진다.

EC2 서버에서도 마찬가지로 SSH 터미널에서 yarn dev로 서버를 구동하고, 터미널을 닫으면 서버가 꺼진다.

이때, 터미널이 종료되어도 서버를 계속 구동시키기 위해서 nohup라는 명령어를 사용한다.

 

반대로 서버를 끄고 싶은데, 터미널을 종료해도 꺼지지 않을 것이다.

이럴 때는, react 서버 포트인 3000번 포트를 종료시키는 명령어를 사용한다. 

// 서버 상시구동
nohup yarn dev &
// 서버 종료시킬 때
fuser -k 3000/tcp

nohup 명령어로 서버를 켜놓고, 다음날 rtrod_batch_log 테이블에 00시 05분 데이터가 들어왔는지 확인한다.

 

https://taling.me/Talent/Detail/19341

 

[비전공자도 가능한 웹 프로젝트] 개발부터 배포까지, 배우면서 완성(react,nodejs,mysql,aws)! | 탈잉

✔ 수업 목표 & 5주 뒤 결과물 만들고 싶은 서비스를 직접 구현하게 됩니다. 사람들이 방문하고 액션을 할 수 있는 웹 페이지를 제작 & 배포하는 것까지 진행됩니다. 여러분이 개발 경험이 있든 ��

taling.me:443

강의 문의 : ljung5@naver.comhttps://taling.me/Talent/Detail/19341

 

Comments