내용 목차
본 장에서는 배치 서비스의 소개와 Job 내부 구성 요소 및 개발에 대해 설명한다.
센터컷은 대용량의 데이터를 처리하기 위한 추가적인 개발자의 코드를 최소화 하고 기 개발된 서비스를 통해 대용량 데이터를 처리한다. 대용량 데이터를 처리하기 위하여 멀티노드 처리 및 안정성을 위한 fail-over 처리를 지원한다.
센터컷은 ProObject의 서비스로 구성되어있으며 대용량 데이터 처리를 위한 추가적인 개발자 코드를 최소화 한 대신, 프레임워크의 테이블 구조 및 항목들에 이해가 필요하다.
다음은 센터컷 서비스를 하는 서버와 데이터베이스 구성에 대한 설명이다.
Service
DB 테이블
센터컷 관련 처리를 위한 데이터를 테이블에 저장한다.
테이블 | 설명 |
---|---|
PO_CC_MAIN | 센터컷의 메인 테이블로 호출할 서비스 및 병렬처리 등 각종 설정이 존재한다. |
PO_CC_SUMR | 센터컷의 집계 테이블로 센터컷의 처리되고 있는 집계 데이터 및 실행 전 처리할 데이터의 총량을 관리한다. |
PO_CC_SVCM | 센터컷의 현황 테이블로 각 CCTaskService가 처리하고 있는 처리 현황에 대해 보여주는 테이블이다. |
PO_CC_DATA | 센터컷의 원장 테이블로, 각 row마다 서비스의 Input 및 Header 데이터를 가지고 있다. |
관련된 내용은 다음의 경로에 설정한다.
${PROOBJECT_HOME}/config/proobject.xml
모든 설정은 <batch-config> 태그 아래에 설정에 존재한다. <batch-config>를 설정하면 배치 시스템의 서비스 그룹이 기동할 때 등록되게 되며, 센터컷 서비스를 호출하는데 해당 설정은 필수적이다.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE xml> <ProObjectConfig> ... <batch-config> </batch-config> ... </ProObjectConfig>
ProObject의 배치는 상태를 기록하는 테이블, 온라인 배치 혹은 멀티노드 처리를 위한 노드 관련 테이블 그리고 센터컷 관련 처리를 위한 데이터를 테이블에 저장한다.
노드 관련 설정이 없으면, 센터컷은 센터컷 서비스가 호출된 자신 노드로 CCTask를 호출한다.
PO_CC_MAIN
PO_CC_MAIN은 센터컷 메인 테이블이다.
PO_CC_SUMR
PO_CC_SUMR는 센터 컷 정보를 집계하는 테이블이다.
PO_CC_SVCM
PO_CC_SVCM은 센터컷 현황을 저장하는 테이블이다.
컬럼 | 설명 |
---|---|
CC_ID | 센터컷 아이디이다. |
CC_EXE_ID | 센터컷 실행 아이디이다. |
TASK_SER | 센터컷 처리 요청 일련번호이다. |
STT_SER | 센터컷 요청 데이터 시작 일련번호이다. |
END_SER | 센터컷 요청 데이터 끝 일련번호이다. |
CPLT_SER | 센터컷 요청 데이터 현재 처리 중 일련번호이다. |
CC_TASK_STATUS | 상태 코드이다.
|
NML_CNT | 정상 처리된 건수이다. |
NML_AMT | 정상 처리 합계이다. |
ERR_CNT | 에러 건이다. |
ERR_AMT | 에러건 합계이다. |
NODE_ID | 처리 중 노드 아이디이다. |
PO_CC_DATA
PO_CC_DATA는 센터컷 원장 테이블이다.
PO_NODE_JOB_SUMR
각 배치 노드의 처리 현황을 보여주는 테이블이며 추후 삭제될 테이블 입니다.
다음은 테이블 생성 스크립트 예제이다.
DROP TABLE PO_NODE_JOB_SUMR; CREATE TABLE PO_NODE_JOB_SUMR( JOB_ID VARCHAR2(20), JOB_EXE_ID VARCHAR2(64 BYTE), NODE_ID VARCHAR2(128), NML_CNT NUMBER(10), ERR_CNT NUMBER(10), UPDATE_TIME TIMESTAMP DEFAULT SYSDATE, /** 최종 상태 변경 시간 **/ PRIMARY KEY (JOB_ID,JOB_EXE_ID,NODE_ID) ); COMMENT ON TABLE PO_NODE_JOB_SUMR IS 'JOB 노드별 통계 테이블'; COMMENT ON column PO_NODE_JOB_SUMR.JOB_ID IS 'JOB ID'; COMMENT ON column PO_NODE_JOB_SUMR.JOB_EXE_ID IS 'JOB 실행 ID'; COMMENT ON column PO_NODE_JOB_SUMR.NODE_ID IS '노드 ID'; COMMENT ON column PO_NODE_JOB_SUMR.NML_CNT IS '정상건수'; COMMENT ON column PO_NODE_JOB_SUMR.ERR_CNT IS '실패건수'; COMMENT ON column PO_NODE_JOB_SUMR.UPDATE_TIME IS '업데이트시간'; DROP TABLE PO_NODE; CREATE TABLE PO_NODE( NODE_ID VARCHAR2(128), NODE_NAME VARCHAR2(256), HOST VARCHAR2(256), PORT NUMBER(5), STATUS VARCHAR2(20), /** 노드 상태 **/ UPDATE_TIME TIMESTAMP DEFAULT SYSDATE, /** 최종 상태 변경 시간 **/ PRIMARY KEY (NODE_ID) ); COMMENT ON TABLE PO_NODE IS 'ProObject Node 관리 테이블, 배치에서 활용'; COMMENT ON column PO_NODE.NODE_ID IS '노드 ID'; COMMENT ON column PO_NODE.NODE_NAME IS '센터컷 실행 애플리케이션명'; COMMENT ON column PO_NODE.HOST IS '호스트명, ex) 192.168.0.1'; COMMENT ON column PO_NODE.PORT IS '포트명 ex) 8888'; COMMENT ON column PO_NODE.STATUS IS '상태'; COMMENT ON column PO_NODE.UPDATE_TIME IS '업데이트시간'; DROP TABLE PO_NODE_JOB; CREATE TABLE PO_NODE_JOB( NODE_ID VARCHAR2(128), JOB_ID VARCHAR2(128), TASK_ID VARCHAR2(128), NODE_WEIGHT NUMBER(3) DEFAULT 0, unique(NODE_ID,JOB_ID,TASK_ID) ); COMMENT ON TABLE PO_NODE_JOB IS 'JOB에서 사용되는 NODE 정보 테이블'; COMMENT ON column PO_NODE_JOB.NODE_ID IS '노드 ID'; COMMENT ON column PO_NODE_JOB.JOB_ID IS 'JOB ID'; COMMENT ON column PO_NODE_JOB.TASK_ID IS 'TASK ID, CC의 경우 null'; COMMENT ON column PO_NODE_JOB.NODE_WEIGHT IS '노드 가중치'; DROP TABLE PO_CC_MAIN; CREATE TABLE PO_CC_MAIN( CC_ID VARCHAR2(20), APP_NAME VARCHAR2(256), SVC_GRP_NAME VARCHAR2(256), SVC_NAME VARCHAR2(256), INPUT_CLZ VARCHAR2(256) not null, CONCURRENT_NUM NUMBER(3), CHUNK_SIZE NUMBER(4), CALL_RETRY_CNT NUMBER(4) not null, HANDLER_CLASS VARCHAR2(256 BYTE), CONSTRAINT PO_CC_MAIN_PK PRIMARY KEY (CC_ID) ); COMMENT ON TABLE PO_CC_MAIN IS '센터컷 메인 테이블'; COMMENT ON column PO_CC_MAIN.CC_ID IS '센터컷 ID'; COMMENT ON column PO_CC_MAIN.APP_NAME IS '센터컷 실행 애플리케이션명'; COMMENT ON column PO_CC_MAIN.SVC_GRP_NAME IS '센터컷 실행 서비스그룹명'; COMMENT ON column PO_CC_MAIN.SVC_NAME IS '센터컷 실행 서비스명'; COMMENT ON column PO_CC_MAIN.INPUT_CLZ IS '센터컷 실행 서비스 InputDO 클래스명'; COMMENT ON column PO_CC_MAIN.CONCURRENT_NUM IS '동시처리수(0일경우 일시중지, -1이하 중지)'; COMMENT ON column PO_CC_MAIN.CHUNK_SIZE IS '호출당 데이터 묶음수'; COMMENT ON column PO_CC_MAIN.HANDLER_CLASS IS '센터컷 핸들러 클래스명'; DROP TABLE PO_CC_SUMR; CREATE TABLE PO_CC_SUMR( CC_ID VARCHAR2(20), CC_EXE_ID VARCHAR2(64 BYTE), CC_STATUS NUMBER(2), CC_STT_TIME VARCHAR2(14),--YYYYMMddHHmmss CC_END_TIME VARCHAR2(14), TOT_DSCNT NUMBER(10), TOT_DSAMT NUMBER(18,2), NML_CNT NUMBER(10), NML_AMT NUMBER(18,2), ERR_CNT NUMBER(10), ERR_AMT NUMBER(18,2), NODE_ID VARCHAR2(128), CONSTRAINT PO_CC_SUMR_PK PRIMARY KEY (CC_ID, CC_EXE_ID) ); COMMENT ON column PO_CC_SUMR.CC_ID IS '센터컷 ID'; COMMENT ON column PO_CC_SUMR.CC_EXE_ID IS '센터컷 실행 ID'; COMMENT ON column PO_CC_SUMR.CC_STATUS IS '상태(추후 상세정보)'; COMMENT ON column PO_CC_SUMR.CC_STT_TIME IS '시작시간(YYYYMMddHHmmss)'; COMMENT ON column PO_CC_SUMR.CC_END_TIME IS '종료시간(YYYYMMddHHmmss)'; COMMENT ON column PO_CC_SUMR.TOT_DSCNT IS '총처리건수'; COMMENT ON column PO_CC_SUMR.TOT_DSAMT IS '총금액'; COMMENT ON column PO_CC_SUMR.NML_CNT IS '정상건수'; COMMENT ON column PO_CC_SUMR.NML_AMT IS '정상금액'; COMMENT ON column PO_CC_SUMR.ERR_CNT IS '에러건수'; COMMENT ON column PO_CC_SUMR.ERR_AMT IS '에러금액'; DROP TABLE PO_CC_SVCM; CREATE TABLE PO_CC_SVCM( CC_ID VARCHAR2(20), CC_EXE_ID VARCHAR2(64 BYTE), TASK_SER NUMBER(10), STT_SER NUMBER(10), END_SER NUMBER(10), CPLT_SER NUMBER(10), CC_TASK_STATUS NUMBER(2) DEFAULT 0, NML_CNT NUMBER(10) DEFAULT 0, NML_AMT NUMBER(18,2) DEFAULT 0, ERR_CNT NUMBER(10) DEFAULT 0, ERR_AMT NUMBER(18,2) DEFAULT 0, NODE_ID VARCHAR2(20), CONSTRAINT PO_CC_SVCM_PK PRIMARY KEY (CC_ID, CC_EXE_ID,TASK_SER) ); COMMENT ON column PO_CC_SVCM.CC_ID IS '센터컷 ID'; COMMENT ON column PO_CC_SVCM.CC_EXE_ID IS '센터컷 실행 ID'; COMMENT ON column PO_CC_SVCM.TASK_SER IS 'Task일련번호'; COMMENT ON column PO_CC_SVCM.STT_SER IS '시작일련번호'; COMMENT ON column PO_CC_SVCM.END_SER IS '끝일련번호'; COMMENT ON column PO_CC_SVCM.CPLT_SER IS '현재일련번호'; COMMENT ON column PO_CC_SVCM.CC_TASK_STATUS IS '상태(추후 상세정보)'; COMMENT ON column PO_CC_SVCM.NML_CNT IS '정상건수'; COMMENT ON column PO_CC_SVCM.NML_AMT IS '정상금액'; COMMENT ON column PO_CC_SVCM.ERR_CNT IS '에러건수'; COMMENT ON column PO_CC_SVCM.ERR_AMT IS '에러금액'; DROP TABLE PO_CC_DATA; CREATE TABLE PO_CC_DATA( CC_ID VARCHAR2(20), CC_EXE_ID VARCHAR2(64 BYTE), SEQ NUMBER(10), DATA_STATUS NUMBER(2), AMT NUMBER(18), DATA1 VARCHAR2(4000), DATA2 VARCHAR2(4000), DATA3 VARCHAR2(4000), DATA4 VARCHAR2(4000), DATA5 VARCHAR2(4000), HEADER_DATA VARCHAR2(4000), ERR_MSG VARCHAR2(4000), CONSTRAINT PO_CC_DATA_PK PRIMARY KEY (CC_ID, CC_EXE_ID,SEQ) ); COMMENT ON column PO_CC_DATA.CC_ID IS '센터컷 ID'; COMMENT ON column PO_CC_DATA.CC_EXE_ID IS '센터컷 실행 ID'; COMMENT ON column PO_CC_DATA.SEQ IS '일련번호(0~)'; COMMENT ON column PO_CC_DATA.DATA_STATUS IS '상태(추후 상세정보)'; COMMENT ON column PO_CC_DATA.AMT IS '금액'; COMMENT ON column PO_CC_DATA.DATA1 IS '데이터1'; COMMENT ON column PO_CC_DATA.DATA2 IS '데이터2'; COMMENT ON column PO_CC_DATA.DATA3 IS '데이터3'; COMMENT ON column PO_CC_DATA.DATA4 IS '데이터4'; COMMENT ON column PO_CC_DATA.DATA5 IS '데이터5'; COMMENT ON column PO_CC_DATA.ERR_MSG IS '에러메시지';
본 절에서는 센터컷 개발 및 실행하는 방법을 설명한다.
센터컷은 이미 개발된 서비스를 통해 데이터를 처리하는 방식을 제공한다는 점은 온라인 배치와 동일하지만, 프레임워크의 원장을 활용하여 개발자의 코딩을 최소화한다는 점이 다르다. 센터컷은 개발자의 코딩을 최소화하기 위하여 프레임워크의 각 테이블에 대해 정확히 이해해야 한다.
다음은 센터컷의 개발 과정에 대한 설명이다.
PO_CC_MAIN 데이터를 삽입한다.
멀티노드 처리가 필요한 경우 PO_NODE 테이블에 노드 정보를 추가하고 PO_NODE_JOB 테이블에 데이터를 삽입한다.
센터컷의 개발이 완료된 후 다음의 과정으로 센터컷의 실행 및 준비를 한다.
실행하기 위해 필요한 고유값인 실행번호(아이디, 고유값, 날짜 혹은 시간)를 정의한다.
센터컷에 활용할 데이터를 센터컷 아이디, 센터컷 실행번호를 포함하여 프레임워크 원장(PO_CC_DATA)에 저장한다.
프레임워크 원장에 적재한 데이터 카운터 및 일자를 포함한 PO_CC_SUMR 테이블에 삽입한다.
센터컷을 센터컷 아이디와 실행번호를 INPUT으로 실행한다.
다음은 센터컷 테이블을 사용하는 예제이다.
--PO_CC_MAIN 데이터 삽입, 동시 요청수 1, 데이터 분할 수 10 --com.tmax.proobject.batch.dataobject.CCParameter Input 클래스를 가진 --app.svcG1.JobServiceCCTargetSample 서비스 호출 insert into po_cc_main(CC_ID, APP_NAME, SVC_GRP_NAME, SVC_NAME, INPUT_CLZ, CONCURRENT_NUM, CHUNK_SIZE, HANDLER_CLASS, CALL_RETRY_CNT) VALUES ('CC_ID_SAM1','app','svcG1','JobServiceCCTargetSample', 'com.tmax.proobject.batch.dataobject.CCParameter',1,10,null,0); --ProObject7_2 노드 추가 insert into PO_NODE(NODE_ID, NODE_NAME, HOST, TCP_PORT, STATUS) VALUES ('ProObject7_2','ProObject7_2','192.168.0.128',6778,1); --ProObject7_3 노드 추가 insert into PO_NODE(NODE_ID, NODE_NAME, HOST, TCP_PORT, STATUS) VALUES ('ProObject7_3','ProObject7_3','192.168.0.128',6779,1); --ProObject7_2에 비율 1 insert into PO_NODE_JOB(NODE_ID, JOB_ID, NODE_WEIGHT) VALUES ('ProObject7_2','CC_ID_SAM1',1); --ProObject7_3에 비율 1 insert into PO_NODE_JOB(NODE_ID, JOB_ID, NODE_WEIGHT) VALUES ('ProObject7_3','CC_ID_SAM1',1); --센터컷은 ProObject7_2 노드, ProObject7_3 노드 1:1 비율로 호출 --데이터 삽입, 실행번호는 'ex_190219'으로 임의 생성 insert into po_cc_data(CC_ID, CC_EXE_ID, SEQ, DATA_STATUS, AMT, DATA1, DATA2, DATA3, DATA4, DATA5) VALUES ('CC_ID_SAM1', 'ex_190219', 0, '0', 0, '{"cc_id":"123","cc_exe_id":"testEx0","retry_yn":"n"}', null, null, null, null); insert into po_cc_data(CC_ID, CC_EXE_ID, SEQ, DATA_STATUS, AMT, DATA1, DATA2, DATA3, DATA4, DATA5) VALUES ('CC_ID_SAM1', 'ex_190219', 1, '0', 0, '{"cc_id":"123","cc_exe_id":"33","retry_yn":"n"}', null, null, null, null); --sumr 삽입 insert into po_cc_sumr(CC_ID, CC_EXE_ID, CC_STATUS, CC_STT_TIME, CC_END_TIME, TOT_DSCNT, TOT_DSAMT, NML_CNT, NML_AMT, ERR_CNT, ERR_AMT) VALUES ('CC_ID_SAM1', 'ex_190219', '0', '', '', 2, 0, 0, 0, 0, 0);