init
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 1. 기능 : Cache정보를 표현하는 Java Value Object 클래스. 2. 처리 개요 : Cache 정보를 정의한다. 3.
|
||||
* 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
*/
|
||||
public class CacheInfoVO implements Serializable {
|
||||
private String name;
|
||||
private List<String> keys;
|
||||
private long size;
|
||||
private long timeToLive;
|
||||
|
||||
/**
|
||||
* 1. 기능 : EAI서비스 코드를 초기화하는 생성자 함수 2. 처리 개요 : EAI 서비스 코드를 초기화한다. 3. 주의사항
|
||||
*
|
||||
* @param eaiInstCd
|
||||
* EAI 서버인스턴스명
|
||||
* @param eaiSvcCd
|
||||
* EAI 서비스 코드
|
||||
**/
|
||||
public CacheInfoVO() {
|
||||
keys = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<String> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public void setKeys(List<String> keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public long getTimeToLive() {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
public long getTimeToLiveSeconds() {
|
||||
return timeToLive / 1000;
|
||||
}
|
||||
|
||||
public void setTimeToLive(long timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class CacheStoreObject implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String message;
|
||||
private long expirationTime;
|
||||
|
||||
public CacheStoreObject(String message, long expirationTime) {
|
||||
this.message = message;
|
||||
this.expirationTime = expirationTime;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return System.currentTimeMillis() > expirationTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.java_websocket.WebSocket;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
|
||||
|
||||
import com.eactive.eai.adapter.websocket.WebSocketSessionManager;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.property.PropertyLoginKeys;
|
||||
import com.eactive.eai.common.server.EAIServerManager;
|
||||
import com.eactive.eai.common.sessioninfo.SessionHistoryDTO;
|
||||
import com.eactive.eai.common.sessioninfo.SessionHistoryVO;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoVO;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoVO.Status;
|
||||
import com.eactive.eai.common.util.DatetimeUtil;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
public class ChannelSessionFacade {
|
||||
|
||||
public enum LogoutType {
|
||||
Logout, AutoLogout, ForceLogout, WebSocketTimeout, DateChange, ServerDown
|
||||
}
|
||||
|
||||
private static ChannelSessionFacade instance;
|
||||
private Logger logger;
|
||||
|
||||
private SessionManager sessionManager;
|
||||
private WebSocketSessionManager webSocketSessionManager;
|
||||
|
||||
private SessionStatusManager sessionStatusManager;
|
||||
|
||||
private ExecutorService logoutRunnerExecutor;
|
||||
|
||||
private static final Integer DEFAULT_LOGOUT_MIN_THREAD_COUNT = 10;
|
||||
|
||||
public static ChannelSessionFacade getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (ChannelSessionFacade.class) {
|
||||
if (instance == null) {
|
||||
instance = new ChannelSessionFacade();
|
||||
instance.logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
|
||||
instance.sessionManager = SessionManager.getInstance();
|
||||
instance.webSocketSessionManager = WebSocketSessionManager.getInstance();
|
||||
instance.sessionStatusManager = SessionStatusManager.getInstance();
|
||||
|
||||
PropManager pManager = PropManager.getInstance();
|
||||
if (pManager.isContainProperties(PropertyLoginKeys.LOGIN)){
|
||||
|
||||
Properties loginProp = pManager.getProperties(PropertyLoginKeys.LOGIN);
|
||||
|
||||
int logoutMaxThreadCount = Integer.parseInt(loginProp.getProperty(PropertyLoginKeys.LOGOUT_MAX_THREAD, "30"));
|
||||
int logoutMinThreadCount = logoutMaxThreadCount < DEFAULT_LOGOUT_MIN_THREAD_COUNT ? logoutMaxThreadCount : DEFAULT_LOGOUT_MIN_THREAD_COUNT;
|
||||
int logoutMaxQueueSize = Integer.parseInt(loginProp.getProperty(PropertyLoginKeys.LOGOUT_MAX_QUEUE, "500"));
|
||||
|
||||
LinkedBlockingQueue<Runnable> runnerQueue = new LinkedBlockingQueue<Runnable>(logoutMaxQueueSize);
|
||||
instance.logoutRunnerExecutor =
|
||||
new ThreadPoolExecutor(
|
||||
logoutMinThreadCount, logoutMaxThreadCount, 60000L, TimeUnit.MILLISECONDS, runnerQueue, new CustomizableThreadFactory("LogoutRunner-"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void login(String userId, String uuid, JSONObject resultJson) {
|
||||
|
||||
logger.debug("login] userId : " + userId, " uuid : " + uuid);
|
||||
|
||||
PropManager pManager = PropManager.getInstance();
|
||||
Properties loginProp = pManager.getProperties(PropertyLoginKeys.LOGIN);
|
||||
|
||||
/** PostBank
|
||||
String KEY_USER_NM = loginProp.getProperty(PropertyLoginKeys.LOGIN_USER_NM);
|
||||
// 소속국
|
||||
String KEY_BRN_CD = loginProp.getProperty(PropertyLoginKeys.LOGIN_BRN_CD);
|
||||
String KEY_BRN_NM = loginProp.getProperty(PropertyLoginKeys.LOGIN_BRN_NM);
|
||||
|
||||
// 소속청
|
||||
String KEY_ROFC_CD = loginProp.getProperty(PropertyLoginKeys.LOGIN_ROFC_CD);
|
||||
|
||||
// terminalId
|
||||
String TERMINAL_ID = loginProp.getProperty(PropertyLoginKeys.LOGIN_TERMINAL_ID);
|
||||
**/
|
||||
|
||||
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
String serverName = eaiServerManager.getLocalServerName();
|
||||
// String brncd = (String) resultJson.get(KEY_BRN_CD);
|
||||
|
||||
SessionVO sessionVo = new SessionVO();
|
||||
sessionVo.setUuid(uuid);
|
||||
sessionVo.setLoginUserId(userId);
|
||||
sessionVo.setLoginInstId(serverName);
|
||||
// sessionVo.setBrncd(brncd);
|
||||
// sessionVo.setTerminalId((String) resultJson.get(TERMINAL_ID));
|
||||
|
||||
sessionManager.putLogin(userId, sessionVo);
|
||||
sessionManager.putHttpLogin(uuid, sessionVo);
|
||||
|
||||
sessionManager.putWebSocketTimeout(userId, sessionVo);
|
||||
|
||||
SessionInfoVO sessionInfoVO = new SessionInfoVO(userId);
|
||||
sessionInfoVO.setSessionId(uuid);
|
||||
sessionInfoVO.setCreateTime(DatetimeUtil.getCurrentDateTime());
|
||||
sessionInfoVO.setSessionStatus(SessionInfoVO.Status.active);
|
||||
// sessionInfoVO.setUserName((String) resultJson.get(KEY_USER_NM));
|
||||
// sessionInfoVO.setRofcCode((String) resultJson.get(KEY_ROFC_CD));
|
||||
// sessionInfoVO.setBrnName((String) resultJson.get(KEY_BRN_NM));
|
||||
// sessionInfoVO.setBrnCode(brncd);
|
||||
// sessionInfoVO.setTerminalId((String) resultJson.get(TERMINAL_ID));
|
||||
|
||||
sessionStatusManager.manageStatus(sessionInfoVO);
|
||||
}
|
||||
|
||||
public void logout(String userId, String uuid, boolean logoutTransaction, LogoutType logoutType) {
|
||||
|
||||
sessionManager.removeLogin(userId);
|
||||
sessionManager.removeHTTPLogin(uuid);
|
||||
|
||||
sessionManager.removeWebSocketTimeout(userId); // logout시 timeout 해제
|
||||
|
||||
logger.info(userId + " 사용자 연결 끊어짐으로 로그아웃 거래 수행.");
|
||||
|
||||
if(logoutTransaction) {
|
||||
logoutRunnerExecutor.submit(() -> {
|
||||
try {
|
||||
sendLogoutTransaction(userId, uuid, logoutType);
|
||||
} catch (Exception e) {
|
||||
logger.error("sendLogoutTransaction Runner error. USERID{"+userId+"}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sessionStatusManager.manageLoginStatus(userId);
|
||||
}
|
||||
|
||||
public void logout(String userId, String uuid, boolean logoutTransaction, LogoutType logoutType, CountDownLatch latch) {
|
||||
|
||||
sessionManager.removeLogin(userId);
|
||||
sessionManager.removeHTTPLogin(uuid);
|
||||
|
||||
sessionManager.removeWebSocketTimeout(userId); // logout시 timeout 해제
|
||||
|
||||
logger.info(userId + " 사용자 연결 끊어짐으로 로그아웃 거래 수행.");
|
||||
|
||||
if(logoutTransaction) {
|
||||
logoutRunnerExecutor.submit(() -> {
|
||||
try {
|
||||
sendLogoutTransaction(userId, uuid, logoutType);
|
||||
latch.countDown();
|
||||
logger.info("Remove Cache And Logout. key= " + userId + "remain=" + latch.getCount());
|
||||
} catch (Exception e) {
|
||||
logger.error("sendLogoutTransaction Runner error. USERID{"+userId+"}", e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
latch.countDown();
|
||||
logger.info("cache has been removed but not a logoutTransaction. key= " + userId + "remain=" + latch.getCount());
|
||||
SessionHistoryLogger.getInstance().log(
|
||||
new SessionHistoryDTO("LOGOUT( "+userId+" )NOT-TRANSACTION", SessionHistoryVO.convertLogoutType_EnumToString(logoutType), "N", uuid, null, false));
|
||||
}
|
||||
|
||||
sessionStatusManager.manageLoginStatus(userId);
|
||||
}
|
||||
|
||||
public void removeFromLoginCache(String userId) {
|
||||
logger.debug("removeFromLoginCache] userId : " + userId);
|
||||
sessionManager.removeLogin(userId);
|
||||
}
|
||||
|
||||
public void removeFromHttpCache(String uuid) {
|
||||
logger.debug("removeFromHttpCache] uuid : " + uuid);
|
||||
sessionManager.removeHTTPLogin(uuid);
|
||||
}
|
||||
|
||||
public void removeFromHttpCacheByUserId(String userId) {
|
||||
logger.debug("removeFromHttpCacheByUserId] userId : " + userId);
|
||||
for(String uuid : sessionManager.getHttpLoginCache().getKeys()) {
|
||||
SessionVO httpLogin = sessionManager.getHttpLogin(uuid);
|
||||
if(StringUtils.equals(userId, httpLogin.getLoginUserId())) {
|
||||
sessionManager.removeHTTPLogin(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onAttachWebSocketSession(String adapterGroupName, WebSocket conn, String userId) {
|
||||
|
||||
logger.debug("onAttachWebSocketSession] adapterGroupName : " + adapterGroupName + " userId : " + userId);
|
||||
SessionVO sessionVo = SessionManager.getInstance().getLogin(userId);
|
||||
|
||||
webSocketSessionManager.sessionLogin(adapterGroupName, conn, userId);
|
||||
|
||||
// WebSocket connection instance
|
||||
String serverName = EAIServerManager.getInstance().getLocalServerName();
|
||||
sessionVo.setWsInstId(serverName);
|
||||
sessionVo.setWsAdapterGroupName(adapterGroupName);
|
||||
|
||||
sessionManager.putLogin(userId, sessionVo); // refresh
|
||||
sessionManager.putHttpLogin(sessionVo.getUuid(), sessionVo); // refresh
|
||||
|
||||
sessionManager.removeWebSocketTimeout(userId); // webSocket 연결 시 timeout 해제
|
||||
|
||||
SessionInfoVO sessionInfoVO = new SessionInfoVO(userId);
|
||||
sessionInfoVO.setWsocInstance(serverName);
|
||||
sessionInfoVO.setWsocRemoteAddr(conn.getRemoteSocketAddress().toString());
|
||||
sessionInfoVO.setWsocSessionStatus(Status.active);
|
||||
|
||||
sessionStatusManager.manageStatus(sessionInfoVO);
|
||||
}
|
||||
|
||||
public void onDetachWebSocketSession(String adapterGroupName, WebSocket conn) {
|
||||
|
||||
logger.debug("onDetachWebSocketSession] adapterGroupName : " + adapterGroupName + " connection : " + conn.getRemoteSocketAddress());
|
||||
webSocketSessionManager.onCloseEvent(adapterGroupName, conn);
|
||||
|
||||
}
|
||||
|
||||
public void closeWebSocketByUserId(String userId, boolean logoutTransaction, LogoutType logoutType) {
|
||||
|
||||
logger.debug("closeWebSocketByUserId] userId : " + userId + " logoutTransaction : " + logoutTransaction + " logoutType : " + logoutType.name());
|
||||
|
||||
for (String adapterGroupName : webSocketSessionManager.getAdapterGroupNames()) {
|
||||
try {
|
||||
if (webSocketSessionManager.isContainKeys(adapterGroupName, userId)) {
|
||||
WebSocket conn = webSocketSessionManager.getSession(adapterGroupName, userId);
|
||||
if (conn != null) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("Close WebSocket Connection : " + conn.getRemoteSocketAddress());
|
||||
}
|
||||
webSocketSessionManager.closeSession(adapterGroupName, userId);
|
||||
} else {
|
||||
logger.debug("closeWebSocketByUserId] userId ["+userId+"]connection is NULL. closeWebSocket skipped");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Logging And Skip
|
||||
logger.error("closeSession Error : " + e.getMessage(), e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(logoutTransaction) {
|
||||
logoutRunnerExecutor.submit(() -> {
|
||||
try {
|
||||
sendLogoutTransaction(userId, null, logoutType);
|
||||
} catch (Exception e) {
|
||||
logger.error("sendLogoutTransaction Runner error. USERID{"+userId+"}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SessionStatusManager.getInstance().manageWebSocketStatus(userId, Status.inactive);
|
||||
}
|
||||
|
||||
public void closeWebSocketByAdapterGroupAndUserId(String adapterGroupName, String userId, boolean logoutTransaction, LogoutType logoutType) {
|
||||
|
||||
if(webSocketSessionManager.getAdapterGroupNames().contains(adapterGroupName)) {
|
||||
try {
|
||||
WebSocket conn = webSocketSessionManager.getSession(adapterGroupName, userId);
|
||||
if (conn != null) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("Close WebSocket Connection : " + conn.getRemoteSocketAddress());
|
||||
}
|
||||
webSocketSessionManager.closeSession(adapterGroupName, userId);
|
||||
} else {
|
||||
logger.debug("closeWebSocketByUserId] userId ["+userId+"]connection is NULL. closeWebSocket skipped");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Logging And Skip
|
||||
logger.error("closeSession Error : " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if(logoutTransaction) {
|
||||
logoutRunnerExecutor.submit(() -> {
|
||||
try {
|
||||
sendLogoutTransaction(userId, null, logoutType);
|
||||
} catch (Exception e) {
|
||||
logger.error("sendLogoutTransaction Runner error. USERID{"+userId+"}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SessionStatusManager.getInstance().manageWebSocketStatus(userId, Status.inactive);
|
||||
}
|
||||
|
||||
public void refreshLoginCache(String userId, SessionVO sessionVO) {
|
||||
sessionManager.putLogin(userId, sessionVO);
|
||||
}
|
||||
|
||||
public void refreshHttpLoginCache(String uuid, SessionVO sessionVO) {
|
||||
sessionManager.putHttpLogin(uuid, sessionVO);
|
||||
}
|
||||
|
||||
public void onDateChange() {
|
||||
|
||||
logger.debug("DateChange] Start");
|
||||
|
||||
webSocketSessionManager.closeSessionAll();
|
||||
|
||||
try {
|
||||
|
||||
removeAllLocalCache(false, LogoutType.DateChange);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("removeAllLocalCache error.", e);
|
||||
}
|
||||
|
||||
logger.debug("DateChange] End");
|
||||
}
|
||||
|
||||
public void onServerDown() {
|
||||
|
||||
logger.debug("ServerDown] Start");
|
||||
|
||||
webSocketSessionManager.closeSessionAll();
|
||||
|
||||
try {
|
||||
removeAllLocalCache(true, LogoutType.ServerDown);
|
||||
} catch (Exception e) {
|
||||
logger.error("removeAllLocalCache error.", e);
|
||||
} finally { // onServerDown시 Executor와 sessionManager를 close한다.
|
||||
if (logoutRunnerExecutor != null)
|
||||
try {
|
||||
logoutRunnerExecutor.shutdown();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (sessionManager != null)
|
||||
try {
|
||||
sessionManager.closeManager();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
}
|
||||
if (logoutRunnerExecutor != null) {
|
||||
logoutRunnerExecutor.shutdown();
|
||||
}
|
||||
logger.debug("ServerDown] End");
|
||||
}
|
||||
|
||||
private void removeAllLocalCache(boolean logoutTransaction, LogoutType logoutType) throws InterruptedException {
|
||||
|
||||
List<String> loginCacheKeys = sessionManager.getLoginCache().getKeys();
|
||||
CountDownLatch latch = new CountDownLatch(loginCacheKeys.size());
|
||||
|
||||
for(String loginKey : loginCacheKeys) {
|
||||
SessionVO login = sessionManager.getLogin(loginKey);
|
||||
if(login != null) {
|
||||
String localServerName = EAIServerManager.getInstance().getLocalServerName();
|
||||
String wsInstId = login.getWsInstId();
|
||||
String loginInstId = login.getLoginInstId();
|
||||
if((wsInstId == null && localServerName.equals(loginInstId))// http login 을 했는데 websocket 로그인이 안된경우
|
||||
|| localServerName.equals(wsInstId)) { // stop 하는 인스턴스의 websocket을 구별해서
|
||||
logout(login.getLoginUserId(), login.getUuid(), logoutTransaction, logoutType, latch);
|
||||
} else {
|
||||
latch.countDown();
|
||||
logger.info("pass other instance. key= " + loginKey + "remain=" + latch.getCount());
|
||||
}
|
||||
} else {
|
||||
latch.countDown();
|
||||
logger.info("pass sessionVo is null. key= " + loginKey + "remain=" + latch.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
boolean await = latch.await(180, TimeUnit.SECONDS);
|
||||
|
||||
if(await) {
|
||||
logger.debug("removeAllLocalCache success. remain latch count : " + latch.getCount());
|
||||
} else {
|
||||
logger.warn("latch timeout occurred. remain count : " + latch.getCount());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sendLogoutTransaction(String userId, String uuid, LogoutType logoutType) throws Exception {
|
||||
//
|
||||
// String historyDstcd = SessionHistoryVO.convertLogoutType_EnumToString(logoutType);
|
||||
//
|
||||
// PropManager pManager = PropManager.getInstance();
|
||||
// Properties loginProp = pManager.getProperties("LOGIN");
|
||||
// Properties stdMessageProp = pManager.getProperties("STDMESSAGE");
|
||||
// EAIServerManager serverManager = EAIServerManager.getInstance();
|
||||
//// String envMode = System.getProperty(Keys.EAI_SYSTEMMODE);
|
||||
// String envMode = serverManager.getSystemEnvTypeConvert();
|
||||
//
|
||||
// String logoutServiceId = loginProp.getProperty("LOGOUT_SERVICE_ID");
|
||||
// String logoutInterfaceId = loginProp.getProperty("LOGOUT_INTERFACE_ID");
|
||||
// String messageVersion = stdMessageProp.getProperty("VERSION");
|
||||
//
|
||||
// String currentTimeMills = DatetimeUtil.getCurrentTimeMillis();
|
||||
//
|
||||
// String systemCode = "MCC";
|
||||
// String guid = UUIDGenerator.getGUID(systemCode);
|
||||
// STDMessage stdmsg = new STDMessage();
|
||||
// stdmsg.setData("systemHeader.VRSN", messageVersion); //버전
|
||||
// stdmsg.setData("systemHeader.IPOP_DVSN_CD", "I"); //입력출력구분코드
|
||||
// stdmsg.setData("systemHeader.FRST_GUID", guid); //최초GUID
|
||||
// stdmsg.setData("systemHeader.GUID", guid); //GUID
|
||||
// //stdmsg.setData("systemHeader.PRGR_SN", "1"); //진행일련번호
|
||||
// //stdmsg.setData("systemHeader.TLGR_ENCRT_YN", "N"); //전문암호화여부
|
||||
// stdmsg.setData("systemHeader.CHNL_DVSN_CD", "00"); //채널구분
|
||||
// stdmsg.setData("systemHeader.IP_VRSN_DVSN_CD", "V4"); //IP버전구분코드
|
||||
// stdmsg.setData("systemHeader.ENVR_INFO_DVSN_CD", envMode); //환경정보구분코드
|
||||
// stdmsg.setData("systemHeader.FRST_DMND_APLC_SYS_CD", systemCode); //최초요청어플리케이션시스템코드
|
||||
// stdmsg.setData("systemHeader.FRST_DMND_INTF_SYS_CD", systemCode); //최초요청인터페이스시스템코드
|
||||
// stdmsg.setData("systemHeader.TRSM_SYS_CD", systemCode); //전송시스템코드
|
||||
// stdmsg.setData("systemHeader.MCI_INTF_ID", logoutInterfaceId); //MCI_인터페이스ID
|
||||
// stdmsg.setData("systemHeader.FRST_TLGR_DMND_DT", currentTimeMills); //최초전문요청일시
|
||||
// stdmsg.setData("systemHeader.DMND_SYS_CD", systemCode); //요청시스템코드
|
||||
// stdmsg.setData("systemHeader.TLGR_DMND_DT", currentTimeMills); //전문요청일시
|
||||
// stdmsg.setData("systemHeader.DLNG_PRCS_DVSN_CD", "S"); //거래처리구분코드
|
||||
//
|
||||
// stdmsg.setData("systemHeader.RSPNS_RSLT_DVSN_CD", "N"); //응답결과구분코드
|
||||
//
|
||||
// //stdmsg.setData("systemHeader.MULTILNG_DVSN_CD", "ko"); //다국어구분코드
|
||||
// stdmsg.setData("systemHeader.DLNG_ID", logoutServiceId); //거래ID
|
||||
// //stdmsg.setData("systemHeader.RTRCN_DLNG_YN", "N"); //취소거래여부
|
||||
// //stdmsg.setData("systemHeader.TLGR_TYP_DVSN_CD", "G"); //전문 유형코드
|
||||
// //stdmsg.setData("systemHeader.LVOL_DAT_PRCS_DVSN_CD", "N"); //대량데이터처리구분코드
|
||||
// //stdmsg.setData("systemHeader.LVOL_DAT_PRCS_SN", "0"); //대량데이터처리일련번호
|
||||
// //stdmsg.setData("systemHeader.SMLT_DLNG_DVSN_CD", "G"); //시뮬레이션 거래 구분코드
|
||||
// //stdmsg.setData("systemHeader.ACNT_MODE_DVSN_CD", "0"); //계정모드 구분코드
|
||||
//
|
||||
// //기존 대비 validation 추가 항목 - start - 20220310
|
||||
// stdmsg.setData("systemHeader.FRST_DMND_SYS_IP_VAL", serverManager.getServerIp()); //최초요청시스템IP값
|
||||
// stdmsg.setData("systemHeader.FRST_DMND_SYS_MAC_VAL", serverManager.getServerMac()); //최초요청시스템MAC값
|
||||
// stdmsg.setData("systemHeader.TMOT_CD", "S"); //타임아웃코드
|
||||
// //기존 대비 validation 추가 항목 - end - 20220310
|
||||
//
|
||||
// stdmsg.setData("commonHeader.USERID", userId); //사용자 ID
|
||||
//
|
||||
// //공통 헤더 셋팅 못함
|
||||
// //청코드
|
||||
// //국코드
|
||||
// //취급청코드
|
||||
// //취급국코드
|
||||
//
|
||||
// String body = "{\"USERID\":\""+userId+"\"}";
|
||||
// String sendData = stdmsg.toJSONString(body);
|
||||
//
|
||||
// try {
|
||||
// String eaiSvcCd = logoutInterfaceId + STDMessage.SEND_RECV_CD_SEND + STDMessage.DIRECTION_IN;
|
||||
// EAIMessage eaiMsg = EAIMessageManager.getInstance().getEAIMessage(eaiSvcCd);
|
||||
// if(eaiMsg == null){
|
||||
// logger.error(eaiSvcCd+" 서비스가 존재하지 않음");
|
||||
// return;
|
||||
// }
|
||||
// String adapterGroupName = eaiMsg.getCurrentSvcMsg().getPsvSysItfTp();
|
||||
//
|
||||
// AdapterGroupVO gvo = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName);
|
||||
//
|
||||
// // 어댑터가 사용중이 아니면 Skip한다.
|
||||
// if (gvo == null || gvo.isUsedFlag() == false) {
|
||||
// logger.error(adapterGroupName+" 어댑터가 등록되어있지 않거나 미사용 상태라 로그아웃 미수행");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// AdapterVO avo = gvo.nextAdapterVO();
|
||||
// if (avo == null){
|
||||
// logger.error(adapterGroupName+"에 가용한 어댑터가 없어 로그아웃 미수행");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// AdapterPropManager manager = AdapterPropManager.getInstance();
|
||||
// Properties outboundProp = (Properties)manager.getProperties(avo.getPropGroupName()).clone();
|
||||
// String charset = outboundProp.getProperty(HttpClientAdapterServiceKey.ENCODE, "utf-8");
|
||||
//
|
||||
// if(logger.isDebug())
|
||||
// logger.debug("logout send >> "+sendData);
|
||||
//
|
||||
// byte[] reqBytes = sendData.getBytes(charset);
|
||||
// Properties tempProp = new Properties();
|
||||
// tempProp.put(HttpClientAdapterServiceKey.TRAN_CODE, logoutServiceId);
|
||||
// tempProp.setProperty(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME, adapterGroupName);
|
||||
// tempProp.setProperty(HttpClientAdapterServiceKey.ADAPTER_NAME, avo.getName());
|
||||
//
|
||||
// byte[] resBytes = null;
|
||||
// if ("SOCKETOUT".equals(eaiMsg.getCurrentSvcMsg().getOutbRtnNm()) ){
|
||||
// resBytes = SocketSender.callService(adapterGroupName, outboundProp, reqBytes, tempProp);
|
||||
// }else{
|
||||
// resBytes = HttpSender.callService(adapterGroupName, outboundProp, reqBytes, tempProp);
|
||||
// }
|
||||
//
|
||||
// if(logger.isDebug()){
|
||||
// String recvData = new String(resBytes, charset);
|
||||
// logger.debug("logout recv << "+recvData);
|
||||
// }
|
||||
//
|
||||
// ExtMessage resExtMessage = ExtMessageConverter.getExtMessageForStandard(resBytes, gvo.getMessageType());
|
||||
//
|
||||
// SessionHistoryLogger.getInstance().log(
|
||||
// new SessionHistoryDTO(sendData, historyDstcd, resExtMessage.getResponseType(), uuid, null, true));
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
//
|
||||
// SessionHistoryLogger.getInstance().log(
|
||||
// new SessionHistoryDTO(sendData, historyDstcd, "C", uuid, null, true));
|
||||
//
|
||||
// throw e;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.ignite.events.CacheEvent;
|
||||
import org.apache.ignite.events.EventType;
|
||||
import org.apache.ignite.internal.binary.BinaryObjectImpl;
|
||||
import org.apache.ignite.lang.IgnitePredicate;
|
||||
|
||||
import com.eactive.eai.common.message.EAIMessage;
|
||||
import com.eactive.eai.common.server.EAIServerManager;
|
||||
import com.eactive.eai.common.session.ChannelSessionFacade.LogoutType;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.worker.Future;
|
||||
import com.eactive.eai.common.worker.ResponseMap;
|
||||
|
||||
public class IgniteEvent implements IgnitePredicate<CacheEvent> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
private static final ExecutorService executor = new ThreadPoolExecutor(20, 20, 0, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>());
|
||||
|
||||
@Override
|
||||
public boolean apply(CacheEvent event) {
|
||||
IgniteEventDataBundle bundle = new IgniteEventDataBundle(event);
|
||||
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] local event<"+ event.name() +"> [name= " + bundle.getCacheName() + ", " + "key=" + bundle.getKey() + ", "
|
||||
+ "oldVal=" + bundle.getOldValue() + ", " + "newVal=" + bundle.getNewValue());
|
||||
}
|
||||
|
||||
// if (SessionManager.TOPIC_CAHCE_NAME.equals(bundle.getCacheName()) && EventType.EVT_CACHE_OBJECT_PUT == bundle.getEventType()) {
|
||||
// removeTopic(bundle);
|
||||
// }
|
||||
if (SessionManager.TOPIC_CAHCE_NAME.equals(bundle.getCacheName()) && EventType.EVT_CACHE_OBJECT_PUT == bundle.getEventType()) {
|
||||
Future future = ResponseMap.getInstance().get(event.key());
|
||||
if ( future == null) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] event.key["+event.key() + "] skip to Future");
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] event.key["+event.key() + "] put to Future");
|
||||
}
|
||||
EAIMessage data = (EAIMessage)event.newValue();
|
||||
future.getSlot().put(data);
|
||||
}
|
||||
} else
|
||||
if (SessionManager.LOGIN_CAHCE_NAME.equals(bundle.getCacheName())
|
||||
&& EventType.EVT_CACHE_OBJECT_REMOVED == bundle.getEventType()) {
|
||||
// if (logger.isWarn()) {
|
||||
// logger.warn("localListener] loginSession removed event[" + bundle.getKey() + "] start");
|
||||
// }
|
||||
// if (isWebSocketContainer(bundle)) {
|
||||
// closeWebSocket(bundle);
|
||||
// }
|
||||
} else if (SessionManager.LOGIN_CAHCE_NAME.equals(bundle.getCacheName())
|
||||
&& EventType.EVT_CACHE_OBJECT_EXPIRED == bundle.getEventType()) {
|
||||
// if (logger.isWarn()) {
|
||||
// logger.warn("localListener] loginSession expired event[" + bundle.getKey() + "] start");
|
||||
// }
|
||||
// if (isWebSocketContainer_or_httpLoginContainer(bundle)) {
|
||||
// SessionStatusManager.getInstance().manageLoginStatus(bundle.getKey());
|
||||
// closeWebSocketWithLogoutTransaction(bundle);
|
||||
// }
|
||||
} else if (SessionManager.HTTP_CAHCE_NAME.equals(bundle.getCacheName())
|
||||
&& EventType.EVT_CACHE_OBJECT_EXPIRED == bundle.getEventType()) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] httpLogin expired event[" + bundle.getKey() + "] start");
|
||||
}
|
||||
// if (isWebSocketContainer_or_httpLoginContainer(bundle)) {
|
||||
// removeLoginCacheWithLogoutTransaction(bundle, LogoutType.AutoLogout);
|
||||
// }
|
||||
manageLoginStatusWithUUID(bundle);
|
||||
} else if (SessionManager.WEBSOCKER_CAHCE_NAME.equals(bundle.getCacheName())
|
||||
&& EventType.EVT_CACHE_OBJECT_EXPIRED == bundle.getEventType()) {
|
||||
// if (logger.isWarn()) {
|
||||
// logger.warn("localListener] webSocketTimeout expired event[" + bundle.getKey() + "] start");
|
||||
// }
|
||||
// if (isHTTPLoginContainer(bundle)) {
|
||||
// removeLoginCacheWithLogoutTransaction(bundle, LogoutType.WebSocketTimeout);
|
||||
// }
|
||||
}
|
||||
return true; // Continue listening.
|
||||
}
|
||||
|
||||
private void removeTopic(IgniteEventDataBundle bundle) {
|
||||
EAIMessage data = (EAIMessage) bundle.getNewValue();
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] setEvent[" + bundle.getKey() + "]");
|
||||
}
|
||||
Future future = ResponseMap.getInstance().get(bundle.getKey());
|
||||
if (future != null) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] setEvent[" + bundle.getKey() + "] put to Future");
|
||||
}
|
||||
future.getSlot().put(data);
|
||||
SessionManager.getInstance().removeTopic(bundle.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isWebSocketContainer(IgniteEventDataBundle bundle) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession setExpireEvent[" + bundle.getKey() + "] start");
|
||||
}
|
||||
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
|
||||
if (sessionVo == null) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession setExpireEvent SessionVO not found! - " + bundle.getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
String serverName = eaiServerManager.getLocalServerName();
|
||||
String webSocketInstanceName = sessionVo.getWsInstId();
|
||||
|
||||
if (webSocketInstanceName == null) {
|
||||
return false;
|
||||
} else if (serverName.equals(webSocketInstanceName)) {
|
||||
return true;
|
||||
}
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession setExpireEvent[" + bundle.getKey() + "] skip.. ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isWebSocketContainer_or_httpLoginContainer(IgniteEventDataBundle bundle) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession event[" + bundle.getKey() + "] start");
|
||||
}
|
||||
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
|
||||
if (sessionVo == null) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession event SessionVO not found! - " + bundle.getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
String serverName = eaiServerManager.getLocalServerName();
|
||||
String webSocketInstanceName = sessionVo.getWsInstId();
|
||||
|
||||
if (webSocketInstanceName == null) {
|
||||
if (serverName.equals(sessionVo.getLoginInstId())) {
|
||||
return true;
|
||||
}
|
||||
} else if (serverName.equals(webSocketInstanceName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession event[" + bundle.getKey() + "] skip.. ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isHTTPLoginContainer(IgniteEventDataBundle bundle) {
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
if (sessionVo == null) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession setExpireEvent SessionVO not found! - " + bundle.getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String localServerName = EAIServerManager.getInstance().getLocalServerName();
|
||||
String httpLoginInstanceName = sessionVo.getLoginInstId();
|
||||
|
||||
if (localServerName.equals(httpLoginInstanceName)) {
|
||||
return true;
|
||||
} else {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession setExpireEvent[" + bundle.getKey() + "] skip.. ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void closeWebSocket(IgniteEventDataBundle bundle) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession closeWebSocket[" + bundle.getKey() + "] start");
|
||||
}
|
||||
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
|
||||
String adapterGroupName = sessionVo.getWsAdapterGroupName();
|
||||
|
||||
try {
|
||||
executor.execute(() -> {
|
||||
ChannelSessionFacade.getInstance().closeWebSocketByAdapterGroupAndUserId(adapterGroupName,
|
||||
bundle.getKey(), false, LogoutType.AutoLogout);
|
||||
});
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] loginSession ChannelSessionFacade.closeWebSocketByAdapterGroupAndUserId ["
|
||||
+ bundle.getKey() + "] -" + adapterGroupName);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(
|
||||
"localListener] loginSession login removed ChannelSessionFacade.closeWebSocketByAdapterGroupAndUserId failed, adapterGroupName ["
|
||||
+ adapterGroupName + "] loginUserId [" + bundle.getKey() + "]",
|
||||
ex);
|
||||
}
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession login removed[" + bundle.getKey() + "] end");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void closeWebSocketWithLogoutTransaction(IgniteEventDataBundle bundle) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(
|
||||
"localListener] loginSession closeWebSocketWithLogoutTransaction[" + bundle.getKey() + "] start");
|
||||
}
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
|
||||
String adapterGroupName = sessionVo.getWsAdapterGroupName();
|
||||
|
||||
try {
|
||||
executor.execute(() -> {
|
||||
ChannelSessionFacade.getInstance().closeWebSocketByAdapterGroupAndUserId(adapterGroupName,
|
||||
bundle.getKey(), true, LogoutType.AutoLogout);
|
||||
ChannelSessionFacade.getInstance().removeFromHttpCacheByUserId(bundle.getKey());
|
||||
});
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] loginSession ChannelSessionFacade.closeWebSocketByAdapterGroupAndUserId ["
|
||||
+ bundle.getKey() + "] - adapterGroupName : " + adapterGroupName);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(
|
||||
"localListener] loginSession login expired ChannelSessionFacade.closeWebSocketByAdapterGroupAndUserId failed, adapterGroupName ["
|
||||
+ adapterGroupName + "] loginUserId [" + bundle.getKey() + "]",
|
||||
ex);
|
||||
}
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession login expired[" + bundle.getKey() + "] end. ");
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLoginCacheWithLogoutTransaction(IgniteEventDataBundle bundle, LogoutType logoutType) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession removeLoginCacheWithLogoutTransaction [" + bundle.getKey()
|
||||
+ "] start");
|
||||
}
|
||||
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
try {
|
||||
executor.execute(() -> {
|
||||
ChannelSessionFacade.getInstance().logout(sessionVo.getLoginUserId(), sessionVo.getUuid(), true,
|
||||
logoutType);
|
||||
});
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("localListener] loginSession ChannelSessionFacade.logout [" + bundle.getKey() + "]");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("localListener] loginSession HTTP expired ChannelSessionFacade.logout failed", e);
|
||||
}
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession HTTP expired [" + bundle.getKey() + "] end. ");
|
||||
}
|
||||
}
|
||||
|
||||
private void manageLoginStatusWithUUID(IgniteEventDataBundle bundle) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("localListener] loginSession manageLoginStatusWithUUID [" + bundle.getKey() + "] start");
|
||||
}
|
||||
|
||||
SessionVO sessionVo = bundle.getSessionVO();
|
||||
|
||||
SessionStatusManager.getInstance().manageLoginStatusWithUUID(sessionVo);
|
||||
}
|
||||
public void shutdown() {
|
||||
if(executor != null) {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IgniteEventDataBundle {
|
||||
private String cacheName;
|
||||
private int eventType;
|
||||
private String key;
|
||||
private Object oldValue;
|
||||
private Object newValue;
|
||||
private SessionVO sessionVO;
|
||||
|
||||
public IgniteEventDataBundle(CacheEvent event) {
|
||||
cacheName = event.cacheName();
|
||||
eventType = event.type();
|
||||
key = event.key();
|
||||
oldValue = event.oldValue();
|
||||
newValue = event.newValue();
|
||||
if (oldValue instanceof SessionVO) {
|
||||
sessionVO = (SessionVO) oldValue;
|
||||
}
|
||||
else if (oldValue instanceof BinaryObjectImpl) {
|
||||
BinaryObjectImpl b = (BinaryObjectImpl) oldValue;
|
||||
sessionVO = (SessionVO) b.deserialize();
|
||||
}
|
||||
}
|
||||
|
||||
public String getCacheName() {
|
||||
return cacheName;
|
||||
}
|
||||
|
||||
public int getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Object getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public Object getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public SessionVO getSessionVO() {
|
||||
return sessionVO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.event.CacheEventListener;
|
||||
import net.sf.ehcache.event.CacheEventListenerFactory;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class LoggingCacheListenerFactory extends CacheEventListenerFactory {
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
@Override
|
||||
public CacheEventListener createCacheEventListener(Properties properties) {
|
||||
return new CacheEventListener(){
|
||||
public Object clone() throws CloneNotSupportedException{
|
||||
logger.debug("LoggingCacheListenerFactory] Clone obtained");
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("LoggingCacheListenerFactory] disponse the listener");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyElementEvicted(Ehcache ehcache,
|
||||
Element element) {
|
||||
logger.debug("LoggingCacheListenerFactory] Element evicted from the cache: "+element.getObjectKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyElementExpired(Ehcache ehcache,
|
||||
Element element) {
|
||||
logger.debug("LoggingCacheListenerFactory] Element expired in the cache: "+element.getObjectKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyElementPut(Ehcache ehcache, Element element)
|
||||
throws CacheException {
|
||||
logger.debug("LoggingCacheListenerFactory] Element put into the cache: "+element.getObjectKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyElementRemoved(Ehcache ehcache,
|
||||
Element element) throws CacheException {
|
||||
logger.debug("LoggingCacheListenerFactory] Element remove from the cache: "+element.getObjectKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyElementUpdated(Ehcache ehcache,
|
||||
Element element) throws CacheException {
|
||||
logger.debug("LoggingCacheListenerFactory] Element updated in the cache: "+element.getObjectKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyRemoveAll(Ehcache ehcache) {
|
||||
logger.debug("LoggingCacheListenerFactory] Element remove all element from the cache");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.eactive.eai.common.dao.DAOException;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.property.PropertyLoginKeys;
|
||||
import com.eactive.eai.common.sessioninfo.SessionHistoryDAO;
|
||||
import com.eactive.eai.common.sessioninfo.SessionHistoryDTO;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
@Component("onlSessionHistoryLogger")
|
||||
public class SessionHistoryLogger {
|
||||
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
|
||||
|
||||
@Autowired
|
||||
private SessionHistoryDAO sessionHistoryDAO;
|
||||
|
||||
// private static SessionHistoryLogger instance = null;
|
||||
|
||||
private SessionHistoryLogger() {
|
||||
}
|
||||
|
||||
public static SessionHistoryLogger getInstance() {
|
||||
return ApplicationContextProvider.getContext().getBean(SessionHistoryLogger.class);
|
||||
}
|
||||
|
||||
public void log(SessionHistoryDTO sessionHistoryDTO) {
|
||||
try {
|
||||
if (!"Y".equals(PropManager.getInstance().getProperty(PropertyLoginKeys.LOGIN,
|
||||
PropertyLoginKeys.LOGIN_LOGGING_YN, "Y"))) {
|
||||
logger.debug("LOGIN_LOGGING_YN option is \"N\". SessionHistory not logged.");
|
||||
return;
|
||||
}
|
||||
sessionHistoryDAO.insertSessionHistory(sessionHistoryDTO.toVo());
|
||||
} catch (DAOException de) {
|
||||
logger.error("SessionHistoryLogger] Fail logging session history. sessionHistoryDTO : "
|
||||
+ sessionHistoryDTO.toString(), de);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import com.eactive.eai.common.lifecycle.Lifecycle;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleException;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleListener;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleSupport;
|
||||
import com.eactive.eai.common.message.EAIMessage;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.server.EAIServerManager;
|
||||
import com.eactive.eai.common.server.EAIServerVO;
|
||||
import com.eactive.eai.common.sessioninfo.TerminalInfoVO;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
/**
|
||||
* 1. 기능 :
|
||||
* 1) websocket login session 정보
|
||||
* 2) SA 응답거래 매핑 정보
|
||||
* 3) Single Socket 접속정보
|
||||
* 4) 복원거래에 대한 헤더정보 저장
|
||||
* 정보 공유 관리하는 Manager 클래스
|
||||
* 2. 처리 개요 : Cache 를 통한 기능처리
|
||||
* 3. 주의사항
|
||||
* 4. 오류처리
|
||||
* deadlock 회피 - 2022.01.05 jun's
|
||||
* 1. WebSocketSessionManager.sessionClose() : synchronized 범위변경
|
||||
* 2. CustomRMICacheEventListener
|
||||
* - cache 가 다른 cache에 접근할때 Thread 방식으로 변경
|
||||
* - websocket 인스턴스에서만 작동하도록변경
|
||||
* 인스턴스 stop시 오류
|
||||
* 1. WebSocket 인증시에 HttpLogin 의 websocket instance및 어댑터 그룹 갱신
|
||||
* 2. sessionManager stop 시 expireThread interrupt 후 logout 처리 및 cacheManager.shutdown
|
||||
*
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
* :
|
||||
*/
|
||||
public abstract class SessionManager implements Lifecycle {
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
public static final String ADAPTER_MASTER_CAHCE_NAME = "evictMasterCache";
|
||||
public static final String ADAPTER_CAHCE_NAME = "adapterSession";
|
||||
|
||||
public static final String TOPIC_CAHCE_NAME = "topic";
|
||||
public static final String TOPIC_MAXSZIE = "topicMaxSize";
|
||||
public static final String CACHE_TOPIC_DURATION = "topicDurationSecs";
|
||||
|
||||
public static final String CACHE_WORKING_DIR= "workingDir";
|
||||
public static final String STORE_CAHCE_NAME = "cacheStore";
|
||||
public static final String CAHCE_STORE_MAXSIZE = "cacheStoreMaxSize";
|
||||
public static final String CACHE_STORE_DURATION = "cacheStoreDurationSecs";
|
||||
// public static final String CACHE_MAX_MEM_MB = "cacheMaxMemMb";
|
||||
|
||||
public static final String LOGIN_CAHCE_NAME = "loginSession";
|
||||
public static final String HTTP_CAHCE_NAME = "httpLogin";
|
||||
public static final String USERID_CAHCE_NAME = "convertUserIdSession";
|
||||
public static final String WEBSOCKER_CAHCE_NAME = "webSocketTimeout";
|
||||
public static final String TERMINAL_CAHCE_NAME = "terminalSession";
|
||||
|
||||
public static final String SESSION_MANAGER_GROUPNAME = "RMIInfo";
|
||||
public static final String SESSION_MANAGER_CACHETYPE = "cacheType";
|
||||
public static final String SESSION_MANAGER_CACHETYPE_IGNITE = "IGNITE";
|
||||
public static final String SESSION_MANAGER_CACHETYPE_EHCACHE = "EHCACHE";
|
||||
|
||||
public static final String SESSION_MANAGER_EXPIRE_INTERVAL = "expireInterval";
|
||||
public static final String SESSION_MANAGER_MULTI_GROUP_IP = "multi_group_ip";
|
||||
public static final String SESSION_MANAGER_MULTI_GROUP_PORT = "multi_group_port";
|
||||
public static final String SESSION_MANAGER_SESSION_TIMEOUT = "sessionTimeout";
|
||||
public static final String SESSION_MANAGER_WEBSOCKET_TIMEOUT = "webSocketTimeout";
|
||||
|
||||
public static final String SESSION_MANAGER_KUBERNETES_NAMESPACE = "kubernetes_namespace";
|
||||
public static final String SESSION_MANAGER_KUBERNETES_SERVICENAME = "kubernetes_servicename";
|
||||
public static final String SESSION_MANAGER_KUBERNETES_MASTERURL = "kubernetes_masterurl";
|
||||
public static final String SESSION_MANAGER_KUBERNETES_ACCOUNTTOKEN = "kubernetes_accounttoken";
|
||||
public static final String SESSION_MANAGER_KUBERNETES_DISCOVERYPORT = "kubernetes_discoveryport";
|
||||
|
||||
public static final String ENABLE_MULTILOGIN_YN = "enable_multilogin_yn";
|
||||
public static final String SESSION_VO_VALIDATION_FROM = "session_vo_validation_from";
|
||||
|
||||
private static ChannelSessionFacade channelSessionFacade;
|
||||
private static SessionManager instance;
|
||||
|
||||
private boolean started;
|
||||
|
||||
public static final String MASTER_KEY = "master";
|
||||
|
||||
private LifecycleSupport lifecycle = new LifecycleSupport(this);
|
||||
|
||||
protected SessionManager() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public static synchronized SessionManager getInstance() {
|
||||
if (instance == null) {
|
||||
PropManager manager = PropManager.getInstance();
|
||||
String type = manager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME,
|
||||
SessionManager.SESSION_MANAGER_CACHETYPE, SESSION_MANAGER_CACHETYPE_IGNITE);
|
||||
|
||||
if (SESSION_MANAGER_CACHETYPE_IGNITE.equalsIgnoreCase(type)) {
|
||||
instance = new SessionManagerForIgnite();
|
||||
} else if (SESSION_MANAGER_CACHETYPE_EHCACHE.equalsIgnoreCase(type)) {
|
||||
instance = new SessionManagerForEhcache();
|
||||
} else {
|
||||
instance = new SessionManagerForIgnite();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void start() throws LifecycleException {
|
||||
if (started) {
|
||||
throw new LifecycleException("RECEAICRT201");
|
||||
}
|
||||
|
||||
lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
|
||||
|
||||
int port = 0;
|
||||
int remoteObjectPort = 0;
|
||||
|
||||
channelSessionFacade = ChannelSessionFacade.getInstance();
|
||||
|
||||
EAIServerManager mgr = EAIServerManager.getInstance();
|
||||
EAIServerVO vo = mgr.getEAIServer(mgr.getLocalServerName());
|
||||
// site의 포트 정책에 따라 변경될 수 있음.
|
||||
// EAIServerVO 에 정의됨.
|
||||
port = vo.getCacheLocalPort();
|
||||
remoteObjectPort = vo.getCacheRemotePort();
|
||||
init(port, remoteObjectPort);
|
||||
started = true;
|
||||
lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
|
||||
}
|
||||
|
||||
public void stop() throws LifecycleException {
|
||||
if (!started) {
|
||||
throw new LifecycleException("RECEAICRT203");
|
||||
}
|
||||
lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
|
||||
|
||||
channelSessionFacade.onServerDown();
|
||||
|
||||
started = false;
|
||||
lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
|
||||
}
|
||||
|
||||
public void addLifecycleListener(LifecycleListener listener) {
|
||||
lifecycle.addLifecycleListener(listener);
|
||||
}
|
||||
|
||||
public LifecycleListener[] findLifecycleListeners() {
|
||||
return lifecycle.findLifecycleListeners();
|
||||
}
|
||||
|
||||
public void removeLifecycleListener(LifecycleListener listener) {
|
||||
lifecycle.removeLifecycleListener(listener);
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return this.started;
|
||||
}
|
||||
|
||||
protected abstract void init(int localPort, int remoteObjectPort);
|
||||
|
||||
// Single Socket 관련
|
||||
public abstract SessionVO getConnectionInfo(String key);
|
||||
|
||||
public abstract SessionVO getConnectionStatus(String key);
|
||||
|
||||
public abstract void putConnectionInfo(String key, SessionVO value);
|
||||
|
||||
public abstract void removeConnectionInfo(String key);
|
||||
|
||||
// Topic 관련
|
||||
public abstract EAIMessage getTopic(String key);
|
||||
|
||||
public abstract void putTopic(String key, EAIMessage value);
|
||||
|
||||
public abstract void removeTopic(String key);
|
||||
|
||||
// 비동기 거래 복원용
|
||||
public abstract String getCacheStore(String key);
|
||||
|
||||
public abstract void putCacheStore(String key, String value, int ttlSecs);
|
||||
|
||||
public abstract void putCacheStore(String key, String value);
|
||||
|
||||
public abstract void removeCacheStore(String key);
|
||||
|
||||
// Login Cache
|
||||
public abstract SessionVO getLogin(String key);
|
||||
|
||||
public abstract void putLogin(String key, SessionVO value);
|
||||
|
||||
public abstract void removeLogin(String key);
|
||||
|
||||
// HTTP Cache
|
||||
public abstract SessionVO getHttpLogin(String key);
|
||||
|
||||
public abstract void putHttpLogin(String key, SessionVO value);
|
||||
|
||||
public abstract void removeHTTPLogin(String key);
|
||||
|
||||
// Terminal
|
||||
public abstract TerminalVO getTerminal(String key);
|
||||
|
||||
public abstract void putTerminal(String key, TerminalVO value, TerminalInfoVO terminalInfoVO);
|
||||
|
||||
public abstract void removeTerminal(String key);
|
||||
|
||||
// CacheInfoVO
|
||||
public abstract CacheInfoVO getLoginCache();
|
||||
|
||||
public abstract CacheInfoVO getHttpLoginCache();
|
||||
|
||||
public abstract CacheInfoVO getEvictMasterCache();
|
||||
|
||||
public abstract CacheInfoVO getTerminalCache();
|
||||
|
||||
public abstract CacheInfoVO getConvertUserIdCache();
|
||||
|
||||
public abstract CacheInfoVO getSocketCache();
|
||||
|
||||
public abstract String getMasterInstId();
|
||||
|
||||
// Convert terminalId to userId
|
||||
public abstract String getConvertUserId(String key);
|
||||
|
||||
// WebSocketTimeout Cache
|
||||
public abstract void putWebSocketTimeout(String key, SessionVO value);
|
||||
|
||||
public abstract void removeWebSocketTimeout(String key);
|
||||
|
||||
public abstract void closeManager();
|
||||
|
||||
public abstract String getCacheStatus();
|
||||
}
|
||||
@@ -0,0 +1,924 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.eactive.eai.common.ehcache.CustomRMICacheReplicatorFactory;
|
||||
import com.eactive.eai.common.logger.EAIDBLogControl;
|
||||
import com.eactive.eai.common.message.EAIMessage;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.server.EAIServerManager;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoVO;
|
||||
import com.eactive.eai.common.sessioninfo.TerminalInfoDAO;
|
||||
import com.eactive.eai.common.sessioninfo.TerminalInfoVO;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
import com.eactive.eai.util.HealthCheckManager;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
|
||||
import net.sf.ehcache.bootstrap.BootstrapCacheLoaderFactory;
|
||||
import net.sf.ehcache.config.CacheConfiguration;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import net.sf.ehcache.config.FactoryConfiguration;
|
||||
import net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory;
|
||||
import net.sf.ehcache.distribution.RMICacheReplicatorFactory;
|
||||
import net.sf.ehcache.event.CacheEventListener;
|
||||
import net.sf.ehcache.event.CacheEventListenerFactory;
|
||||
|
||||
//use Ehcache
|
||||
public class SessionManagerForEhcache extends SessionManager {
|
||||
// evictMaster Instance - single socket 관련
|
||||
private static Cache evictMasterCache = null;
|
||||
// Socket Session cache 정보
|
||||
private static Cache cacheSocket = null;
|
||||
// Topic 용 cache 정보
|
||||
private static Cache cacheTopic = null;
|
||||
// 비동기 거래 복원용
|
||||
private static Cache cacheStore = null;
|
||||
|
||||
// WebSocket Login cache 정보
|
||||
private static Cache cacheLogin = null; // key = loginId
|
||||
private static Cache cacheConvertUserId = null; // 단말ID 를 userID로 변경
|
||||
// HTTP Polling 에 대한 timeout 관리용
|
||||
private static Cache httpLogin = null; // key == uuid
|
||||
// Terminal용 cache 정보 : ATM, 무인공과금
|
||||
private static Cache cacheTerminal = null;
|
||||
|
||||
// HTTP Login 후 WebSocket Connection 일정 시간동안 없을시 Expired되며 자동 로그아웃 발생
|
||||
private static Cache cacheWebSocketTimeout = null;
|
||||
|
||||
private static CacheManager manager = null;
|
||||
|
||||
// expireThread run interval secs, default 10 secs
|
||||
int expireInterval = 10;
|
||||
Thread expireThread = null;
|
||||
String localServerName = null;
|
||||
|
||||
private int cacheStoreDurationSecs = 60;
|
||||
|
||||
private final String logPrefix = this.getClass().getName();
|
||||
|
||||
public void init(int localPort, int remoteObjectPort) {
|
||||
PropManager pManager = PropManager.getInstance();
|
||||
Properties prpty = pManager.getProperties(SessionManager.SESSION_MANAGER_GROUPNAME);
|
||||
String mltIp = "230.0.0.1"; // 224.0.1.0 ~ 239.255.255.255
|
||||
String gPort = "4443";
|
||||
int sessionTimeout = 60;
|
||||
int webSocketTimeout = 60;
|
||||
|
||||
int topicTimeout = 60;
|
||||
int topicMaxSize = 10000;
|
||||
|
||||
int cacheStoreMaxSize = 10000;
|
||||
|
||||
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
localServerName = eaiServerManager.getLocalServerName();
|
||||
|
||||
if (prpty != null) {
|
||||
mltIp = prpty.getProperty(SessionManager.SESSION_MANAGER_MULTI_GROUP_IP);
|
||||
gPort = prpty.getProperty(SessionManager.SESSION_MANAGER_MULTI_GROUP_PORT);
|
||||
String sTimeout = prpty.getProperty(SessionManager.SESSION_MANAGER_SESSION_TIMEOUT);
|
||||
if (sTimeout != null) {
|
||||
try {
|
||||
sessionTimeout = Integer.parseInt(sTimeout);
|
||||
if (sessionTimeout < 30)
|
||||
sessionTimeout = 30;
|
||||
} catch (NumberFormatException ex) {
|
||||
sessionTimeout = 60;
|
||||
}
|
||||
}
|
||||
|
||||
String sExpireInterval = prpty.getProperty(SessionManager.SESSION_MANAGER_EXPIRE_INTERVAL);
|
||||
if (sExpireInterval != null) {
|
||||
try {
|
||||
expireInterval = Integer.parseInt(sExpireInterval);
|
||||
if (expireInterval < 10)
|
||||
expireInterval = 10;
|
||||
} catch (NumberFormatException ex) {
|
||||
expireInterval = 10;
|
||||
}
|
||||
}
|
||||
|
||||
String wTimeout = prpty.getProperty(SessionManager.SESSION_MANAGER_WEBSOCKET_TIMEOUT);
|
||||
if (wTimeout != null) {
|
||||
try {
|
||||
webSocketTimeout = Integer.parseInt(wTimeout);
|
||||
} catch (NumberFormatException ex) {
|
||||
webSocketTimeout = 60;
|
||||
}
|
||||
}
|
||||
|
||||
String topicTimeoutSec = prpty.getProperty(SessionManager.CACHE_TOPIC_DURATION);
|
||||
if (topicTimeoutSec != null) {
|
||||
try {
|
||||
topicTimeout = Integer.parseInt(topicTimeoutSec);
|
||||
if (topicTimeout < 0)
|
||||
topicTimeout = 60;
|
||||
} catch (NumberFormatException ex) {
|
||||
topicTimeout = 60;
|
||||
}
|
||||
}
|
||||
String topicMax = prpty.getProperty(SessionManager.TOPIC_MAXSZIE);
|
||||
if (topicMax != null) {
|
||||
try {
|
||||
topicMaxSize = Integer.parseInt(topicMax);
|
||||
if (topicMaxSize < 0)
|
||||
topicMaxSize = 10000;
|
||||
} catch (NumberFormatException ex) {
|
||||
topicMaxSize = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
String durationSecs = prpty.getProperty(SessionManager.CACHE_STORE_DURATION);
|
||||
if (durationSecs != null) {
|
||||
try {
|
||||
cacheStoreDurationSecs = Integer.parseInt(durationSecs);
|
||||
if (cacheStoreDurationSecs < 60)
|
||||
cacheStoreDurationSecs = 60;
|
||||
} catch (NumberFormatException ex) {
|
||||
cacheStoreDurationSecs = 60;
|
||||
}
|
||||
}
|
||||
String cacheStoreMax = prpty.getProperty(SessionManager.CAHCE_STORE_MAXSIZE);
|
||||
if (cacheStoreMax != null) {
|
||||
try {
|
||||
cacheStoreMaxSize = Integer.parseInt(cacheStoreMax);
|
||||
if (cacheStoreMaxSize < 0)
|
||||
cacheStoreMaxSize = 10000;
|
||||
} catch (NumberFormatException ex) {
|
||||
cacheStoreMaxSize = 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.setProperty("net.sf.ehcache.skipUpdateCheck", "true");
|
||||
String bootstrapAsynchronously = "false";
|
||||
|
||||
Configuration cf = new Configuration();
|
||||
FactoryConfiguration ppFactory = new FactoryConfiguration();
|
||||
/**
|
||||
* manual로 설정할경우 shutdown시 멈춤현상이 발생 auto로 변경됨
|
||||
* ppFactory.setClass("com.eactive.eai.common.session.TimeoutRMICacheManagerPeerProviderFactory");
|
||||
* ppFactory.setProperties("peerDiscovery=manual,rmiUrls="+rmiUrls);
|
||||
*/
|
||||
ppFactory.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory");
|
||||
ppFactory.setProperties(
|
||||
"peerDiscovery=automatic,multicastGroupAddress=" + mltIp + ", multicastGroupPort=" + gPort);
|
||||
ppFactory.setPropertySeparator(",");
|
||||
|
||||
cf.addCacheManagerPeerProviderFactory(ppFactory);
|
||||
|
||||
logger.debug(logPrefix + " >>>>INIT<<< Multicast ip = " + mltIp + ", port = " + gPort);
|
||||
|
||||
FactoryConfiguration plFactory = new FactoryConfiguration();
|
||||
plFactory.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory");
|
||||
plFactory.setProperties("port=" + localPort + ", remoteObjectPort=" + remoteObjectPort);
|
||||
|
||||
plFactory.setPropertySeparator(",");
|
||||
cf.addCacheManagerPeerListenerFactory(plFactory);
|
||||
|
||||
CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
|
||||
defaultCacheConfiguration.setName("ChannelSessionCache");
|
||||
defaultCacheConfiguration.setMaxElementsInMemory(200000);
|
||||
cf.addDefaultCache(defaultCacheConfiguration);
|
||||
|
||||
manager = new CacheManager(cf);
|
||||
|
||||
initSocket(manager, sessionTimeout, 10000, bootstrapAsynchronously);
|
||||
initTopic(manager, topicTimeout, topicMaxSize, bootstrapAsynchronously);
|
||||
initCacheStore(manager, cacheStoreDurationSecs, cacheStoreMaxSize, bootstrapAsynchronously);
|
||||
|
||||
initLogin(manager, sessionTimeout, 20000, bootstrapAsynchronously);
|
||||
initHttpLogin(manager, sessionTimeout, 20000, bootstrapAsynchronously);
|
||||
initEvict(manager, sessionTimeout, 10, bootstrapAsynchronously);
|
||||
initTerminal(manager, sessionTimeout, 20000, bootstrapAsynchronously);
|
||||
initConvertUserId(manager, sessionTimeout, 20000, bootstrapAsynchronously);
|
||||
initWebSocketTimeout(manager, webSocketTimeout, 20000, bootstrapAsynchronously);
|
||||
|
||||
/**
|
||||
* expire event가 전파가 안되는 문제 발견(2022-01-13)
|
||||
* 조치는 master에서만 하는게 아니라 전체 인스턴스에서
|
||||
* expireThread 실행되도록변경
|
||||
*/
|
||||
expireThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
String logPrefix = "SessionManager.expireThread] ";
|
||||
while (true) {
|
||||
String master = null;
|
||||
try {
|
||||
Thread.sleep(expireInterval * 1000);
|
||||
if (evictMasterCache.getSize() > 0) {
|
||||
evictMasterCache.evictExpiredElements();
|
||||
Element element = evictMasterCache.get(MASTER_KEY);
|
||||
if (element == null) {
|
||||
evictMasterCache.put(new Element(MASTER_KEY, localServerName));
|
||||
if (logger.isInfo())
|
||||
logger.info(logPrefix + "EVICT-PUT master = " + localServerName);
|
||||
} else {
|
||||
master = (String) element.getObjectValue();
|
||||
if (localServerName.equals(master)) {
|
||||
evictMasterCache.put(new Element(MASTER_KEY, localServerName));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
evictMasterCache.put(new Element(MASTER_KEY, localServerName));
|
||||
if (logger.isInfo())
|
||||
logger.info(logPrefix + "INIT-PUT master = " + localServerName);
|
||||
}
|
||||
|
||||
int cacheSize = cacheLogin.getSize();
|
||||
if (cacheSize > 0) {
|
||||
if (logger.isInfo()) {
|
||||
logger.info(logPrefix + "cacheLogin.evictExpiredElements = " + cacheSize);
|
||||
}
|
||||
cacheLogin.evictExpiredElements();
|
||||
}
|
||||
cacheSize = httpLogin.getSize();
|
||||
if (cacheSize > 0) {
|
||||
if (logger.isInfo()) {
|
||||
logger.info(logPrefix + "httpLogin.evictExpiredElements = " + cacheSize);
|
||||
}
|
||||
httpLogin.evictExpiredElements();
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
logger.error(logPrefix + "expireThread error - stop", ie);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
logger.error(logPrefix + "expireThread error - skip", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
expireThread.setName("SessionManagerForEhcache-expireThread");
|
||||
expireThread.start();
|
||||
}
|
||||
|
||||
private synchronized void initEvict(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
int masterTimeout = (expireInterval + expireInterval / 2);
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create evictMasterCache cache - expire=" + masterTimeout + ", maxSize=" + maxSize);
|
||||
}
|
||||
evictMasterCache = new Cache(ADAPTER_MASTER_CAHCE_NAME, 10, false, false, masterTimeout, masterTimeout);
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", "false");
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
evictMasterCache.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
evictMasterCache.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(evictMasterCache);
|
||||
}
|
||||
|
||||
private synchronized void initSocket(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create AdapterSession cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
cacheSocket = new Cache(ADAPTER_CAHCE_NAME, maxSize, false, false, 0, 0);
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", "false");
|
||||
// celfProp.put("asynchronousReplicationIntervalMillis", "100");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheSocket.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
cacheSocket.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(cacheSocket);
|
||||
}
|
||||
|
||||
private synchronized void initTopic(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create topic cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
cacheTopic = new Cache(TOPIC_CAHCE_NAME, maxSize, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", "false");
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheTopic.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", "false");
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
cacheTopic.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
cacheTopic.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(cacheTopic);
|
||||
}
|
||||
|
||||
private synchronized void initCacheStore(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create cacheStore cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
cacheStore = new Cache(STORE_CAHCE_NAME, maxSize, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", "false");
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheStore.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", "false");
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
cacheStore.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
cacheStore.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(cacheStore);
|
||||
}
|
||||
|
||||
private synchronized void initLogin(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create loginSession cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
|
||||
cacheLogin = new Cache(LOGIN_CAHCE_NAME, 20000, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
String isAsync = PropManager.getInstance().getProperty("LOGIN", "IS_ASYNC", "false");
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", isAsync);
|
||||
// 비동기 방식을 사용할때 변경 내역을 다른 노드에 통지하는 주기 default 1000
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheLogin.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", isAsync);
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
cacheLogin.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
|
||||
cacheLogin.setBootstrapCacheLoader(bcl);
|
||||
// cacheLogin.getCacheConfiguration().setDiskExpiryThreadIntervalSeconds(10);
|
||||
manager.addCache(cacheLogin);
|
||||
logger.warn(logPrefix + " cacheLogin DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = "
|
||||
+ Cache.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS);
|
||||
}
|
||||
|
||||
private synchronized void initHttpLogin(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create httpLogin cache timeToIdleSeconds=" + sessionTimeout);
|
||||
}
|
||||
httpLogin = new Cache(HTTP_CAHCE_NAME, 20000, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
String isAsync = PropManager.getInstance().getProperty("LOGIN", "IS_ASYNC", "false");
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", isAsync);
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
httpLogin.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", isAsync);
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
httpLogin.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
httpLogin.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(httpLogin);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(logPrefix + " httpLogin DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = "
|
||||
+ Cache.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private synchronized void initConvertUserId(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create convertUserIdSession cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
cacheConvertUserId = new Cache(USERID_CAHCE_NAME, maxSize, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
String isAsync = PropManager.getInstance().getProperty("LOGIN", "IS_ASYNC", "false");
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", isAsync);
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheConvertUserId.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", isAsync);
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
cacheConvertUserId.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
cacheConvertUserId.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(cacheConvertUserId);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(logPrefix + " cacheConvertUserId DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = "
|
||||
+ Cache.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void initWebSocketTimeout(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create webSocketTimeout cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
|
||||
cacheWebSocketTimeout = new Cache(WEBSOCKER_CAHCE_NAME, maxSize, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
String isAsync = PropManager.getInstance().getProperty("LOGIN", "IS_ASYNC", "false");
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", isAsync);
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");// 비동기 방식을 사용할때 변경 내역을 다른 노드에 통지하는 주기 default 1000
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheWebSocketTimeout.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", isAsync);
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
cacheWebSocketTimeout.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
cacheWebSocketTimeout.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(cacheWebSocketTimeout);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(logPrefix + " cacheWebSocketTimeout DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = "
|
||||
+ Cache.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void initTerminal(CacheManager manager, int sessionTimeout, int maxSize, String bootstrapAsynchronously) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create TerminalSession cache sessionTimeout="+sessionTimeout +", maxSize=" + maxSize);
|
||||
}
|
||||
cacheTerminal = new Cache(TERMINAL_CAHCE_NAME, maxSize, false, false, sessionTimeout, sessionTimeout);
|
||||
|
||||
CacheEventListenerFactory celf = new RMICacheReplicatorFactory();
|
||||
Properties celfProp = new Properties();
|
||||
celfProp.put("replicateAsynchronously", "false");
|
||||
celfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener cel = celf.createCacheEventListener(celfProp);
|
||||
cacheTerminal.getCacheEventNotificationService().registerListener(cel);
|
||||
|
||||
// add Custom EventListener
|
||||
CacheEventListenerFactory ccelf = new CustomRMICacheReplicatorFactory();
|
||||
Properties ccelfProp = new Properties();
|
||||
ccelfProp.put("replicateAsynchronously", "false");
|
||||
ccelfProp.put("asynchronousReplicationIntervalMillis", "1000");
|
||||
CacheEventListener ccel = ccelf.createCacheEventListener(ccelfProp);
|
||||
cacheTerminal.getCacheEventNotificationService().registerListener(ccel);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
BootstrapCacheLoaderFactory bclf = new RMIBootstrapCacheLoaderFactory();
|
||||
Properties bclfProp = new Properties();
|
||||
bclfProp.put("bootstrapAsynchronously", bootstrapAsynchronously);
|
||||
bclfProp.put("maximumChunkSizeBytes", "5000000");
|
||||
BootstrapCacheLoader bcl = bclf.createBootstrapCacheLoader(bclfProp);
|
||||
cacheTerminal.setBootstrapCacheLoader(bcl);
|
||||
|
||||
manager.addCache(cacheTerminal);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(logPrefix + " cacheTerminal DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = "
|
||||
+ Cache.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
// WebSocket Login 관련
|
||||
public SessionVO getLogin(String key) {
|
||||
try {
|
||||
Element element = cacheLogin.get(key);
|
||||
if (element != null) {
|
||||
return (SessionVO) element.getObjectValue();
|
||||
}
|
||||
return null;
|
||||
} catch (CacheException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putLogin(String key, SessionVO value) {
|
||||
putLogin(key, value, null);
|
||||
}
|
||||
|
||||
public void putLogin(String key, SessionVO value, SessionInfoVO sessionInfoVO) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put session key - " + key + ", Session - " + value.toString());
|
||||
}
|
||||
cacheLogin.put(new Element(key, value));
|
||||
// terminal to userID 매핑 생성
|
||||
if (value != null && value.getTerminalId() != null) {
|
||||
cacheConvertUserId.put(new Element(value.getTerminalId(), key));
|
||||
}
|
||||
|
||||
if (sessionInfoVO != null) {
|
||||
SessionStatusManager.getInstance().manageStatus(sessionInfoVO);
|
||||
} else {
|
||||
SessionStatusManager.getInstance().manageLoginStatus(key);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLogin(String key) {
|
||||
SessionVO vo = getLogin(key);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove websocket login session key - " + key);
|
||||
}
|
||||
// terminal to userID 매핑 제거
|
||||
if (vo != null && vo.getTerminalId() != null) {
|
||||
cacheConvertUserId.remove(vo.getTerminalId());
|
||||
}
|
||||
cacheLogin.remove(key);
|
||||
SessionStatusManager.getInstance().manageLoginStatus(key);
|
||||
}
|
||||
|
||||
// terminalId 2 userId convert
|
||||
public String getConvertUserId(String key) {
|
||||
try {
|
||||
Element element = cacheConvertUserId.get(key);
|
||||
if (element != null) {
|
||||
return (String) element.getObjectValue();
|
||||
}
|
||||
return null;
|
||||
} catch (CacheException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public SessionVO getHttpLogin(String key) {
|
||||
try {
|
||||
Element element = httpLogin.get(key);
|
||||
if (element != null) {
|
||||
return (SessionVO) element.getObjectValue();
|
||||
}
|
||||
return null;
|
||||
} catch (CacheException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putHttpLogin(String key, SessionVO value) {
|
||||
logger.warn("Put session key - " + key + ", Session - " + value.toString());
|
||||
httpLogin.put(new Element(key, value));
|
||||
}
|
||||
|
||||
public void removeHTTPLogin(String key) {
|
||||
logger.warn("Remove http login session key - " + key);
|
||||
httpLogin.remove(key);
|
||||
}
|
||||
|
||||
// Single Socket 관련
|
||||
public SessionVO getConnectionInfo(String key) {
|
||||
try {
|
||||
Element element = cacheSocket.get(key);
|
||||
if (element != null) {
|
||||
SessionVO sessionVo = (SessionVO) element.getObjectValue();
|
||||
return sessionVo;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public SessionVO getConnectionStatus(String adapterGroupName) {
|
||||
SessionVO sessionVo = null;
|
||||
try {
|
||||
sessionVo = getConnectionInfo(adapterGroupName);
|
||||
if (sessionVo != null) {
|
||||
String connectedInst = sessionVo.getLoginInstId();
|
||||
// 싱글어댑터 Start --------------------------->
|
||||
// EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
// String localServerName = eaiServerManager.getLocalServerName();
|
||||
|
||||
// 로컬서버가 연결시도 중인데 캐시에 자신의 인스턴스가 있을경우 삭제
|
||||
if (localServerName.equals(connectedInst)) {
|
||||
cacheSocket.remove(adapterGroupName);
|
||||
return null;
|
||||
}
|
||||
// 싱글어댑터 End <---------------------------
|
||||
|
||||
// 케시에서 조회된 인스던스가 살았는지 확인 - 좀비캐시 삭제
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("getConnectionInfo check primary server status - " + connectedInst);
|
||||
}
|
||||
boolean isAlive = HealthCheckManager.getInstance().getServerStatus(connectedInst);
|
||||
|
||||
if (!isAlive) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("getConnectionInfo check primary server is Not Alive, clear cache.");
|
||||
}
|
||||
cacheSocket.remove(adapterGroupName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return sessionVo;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putConnectionInfo(String key, SessionVO value) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put socket session key - " + key + ", Session - " + value.toString());
|
||||
}
|
||||
cacheSocket.put(new Element(key, value));
|
||||
}
|
||||
|
||||
public void removeConnectionInfo(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove socket session key - " + key);
|
||||
}
|
||||
cacheSocket.remove(key);
|
||||
}
|
||||
|
||||
// Topic 관련
|
||||
public EAIMessage getTopic(String key) {
|
||||
try {
|
||||
Element element = cacheTopic.get(key);
|
||||
if (element != null) {
|
||||
return (EAIMessage) element.getObjectValue();
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putTopic(String key, EAIMessage value) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put Topic response - " + key + ", value - " + value.toString());
|
||||
}
|
||||
cacheTopic.put(new Element(key, value));
|
||||
}
|
||||
|
||||
public void removeTopic(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove Topic response key - " + key);
|
||||
}
|
||||
cacheTopic.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCacheStore(String key) {
|
||||
try {
|
||||
Element element = cacheStore.get(key);
|
||||
if (element == null) {
|
||||
return null;
|
||||
} else {
|
||||
// String message = (String)element.getObjectValue();
|
||||
CacheStoreObject object = (CacheStoreObject) element.getObjectValue();
|
||||
if (object.isExpired()) {
|
||||
if (logger.isWarn())
|
||||
logger.warn("getCacheStore expired key [" + key + "]");
|
||||
cacheStore.remove(key);
|
||||
return null;
|
||||
} else {
|
||||
return object.getMessage();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putCacheStore(String key, String value) {
|
||||
putCacheStore(key, value, cacheStoreDurationSecs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putCacheStore(String key, String value, int ttlSecs) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put cacheStore key[" + key + "], value - " + value);
|
||||
}
|
||||
// cacheStore.put(new Element(key, value));
|
||||
CacheStoreObject object = new CacheStoreObject(value, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ttlSecs));
|
||||
cacheStore.put(new Element(key, object));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCacheStore(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove cacheStore key - " + key);
|
||||
}
|
||||
cacheStore.remove(key);
|
||||
}
|
||||
|
||||
public TerminalVO getTerminal(String key) {
|
||||
try {
|
||||
Element element = cacheTerminal.get(key);
|
||||
if (element != null) {
|
||||
return (TerminalVO) element.getObjectValue();
|
||||
}
|
||||
return null;
|
||||
} catch (CacheException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putTerminal(String key, TerminalVO value, TerminalInfoVO terminalInfoVO) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put terminal key - " + key + ", Terminal - " + value.toString());
|
||||
}
|
||||
cacheTerminal.put(new Element(key, value));
|
||||
if (terminalInfoVO != null && EAIDBLogControl.isEnable()) {
|
||||
try {
|
||||
TerminalInfoDAO dao = ApplicationContextProvider.getContext().getBean(TerminalInfoDAO.class);
|
||||
dao.upsertTerminalInfo(terminalInfoVO);
|
||||
} catch (Exception e) {
|
||||
logger.error(" insert Terminal DB ERROR. - " + e.getMessage(), e);
|
||||
}
|
||||
} else if (terminalInfoVO != null) {
|
||||
logger.error("DB 장애로 업데이트 미수행 - " + value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTerminal(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove socket teminal session key - " + key);
|
||||
}
|
||||
cacheTerminal.remove(key);
|
||||
|
||||
if (EAIDBLogControl.isEnable()) {
|
||||
try {
|
||||
TerminalInfoDAO dao = ApplicationContextProvider.getContext().getBean(TerminalInfoDAO.class);
|
||||
TerminalInfoVO terminalInfoVO = new TerminalInfoVO(key);
|
||||
terminalInfoVO.setSocSessionStatus(TerminalInfoVO.Status.inactive);
|
||||
dao.upsertTerminalInfo(terminalInfoVO);
|
||||
} catch (Exception e) {
|
||||
logger.error(" insert Terminal DB ERROR. - " + key, e);
|
||||
}
|
||||
} else {
|
||||
logger.error(" DB 장애로 인해 업데이트 미수행 - " + key);
|
||||
}
|
||||
}
|
||||
|
||||
private CacheInfoVO convert(Cache cache) {
|
||||
CacheInfoVO v = new CacheInfoVO();
|
||||
v.setName(cache.getName());
|
||||
v.setSize(cache.getSize());
|
||||
v.setTimeToLive(cache.getCacheConfiguration().getTimeToLiveSeconds() * 1000L);
|
||||
v.setKeys(cache.getKeys());
|
||||
return v;
|
||||
}
|
||||
|
||||
public CacheInfoVO getLoginCache() {
|
||||
return convert(cacheLogin);
|
||||
}
|
||||
|
||||
public CacheInfoVO getHttpLoginCache() {
|
||||
return convert(httpLogin);
|
||||
}
|
||||
|
||||
public CacheInfoVO getEvictMasterCache() {
|
||||
return convert(evictMasterCache);
|
||||
}
|
||||
|
||||
public CacheInfoVO getTerminalCache() {
|
||||
return convert(cacheTerminal);
|
||||
}
|
||||
|
||||
public CacheInfoVO getConvertUserIdCache() {
|
||||
return convert(cacheConvertUserId);
|
||||
}
|
||||
|
||||
public CacheInfoVO getSocketCache() {
|
||||
return convert(cacheSocket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putWebSocketTimeout(String key, SessionVO value) {
|
||||
cacheWebSocketTimeout.put(new Element(key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWebSocketTimeout(String key) {
|
||||
cacheWebSocketTimeout.remove(key);
|
||||
}
|
||||
|
||||
public String getMasterInstId() {
|
||||
Element element = evictMasterCache.get(MASTER_KEY);
|
||||
if (element == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (String) element.getObjectValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeManager() {
|
||||
manager.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCacheStatus() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] cacheNames = manager.getCacheNames();
|
||||
sb.append("<Caches type=\"Ehcache\">").append("\n");
|
||||
for(String cacheName : cacheNames) {
|
||||
Cache cache = manager.getCache(cacheName);
|
||||
// Get the cache size
|
||||
long cacheSize = cache.getSize();
|
||||
sb.append("<Cache name=\"" + cacheName + "\" Size=\"" + cacheSize).append("\"/>\n");
|
||||
}
|
||||
sb.append("</Caches>");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,813 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.cache.Cache;
|
||||
import javax.cache.configuration.Factory;
|
||||
import javax.cache.expiry.Duration;
|
||||
import javax.cache.expiry.ModifiedExpiryPolicy;
|
||||
import javax.cache.expiry.TouchedExpiryPolicy;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ignite.Ignite;
|
||||
import org.apache.ignite.IgniteCache;
|
||||
import org.apache.ignite.IgniteEvents;
|
||||
import org.apache.ignite.IgniteLogger;
|
||||
import org.apache.ignite.Ignition;
|
||||
import org.apache.ignite.cache.CacheAtomicityMode;
|
||||
import org.apache.ignite.cache.CacheMetrics;
|
||||
import org.apache.ignite.cache.CacheMode;
|
||||
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
|
||||
import org.apache.ignite.cache.eviction.lru.LruEvictionPolicy;
|
||||
import org.apache.ignite.cache.query.QueryCursor;
|
||||
import org.apache.ignite.cache.query.ScanQuery;
|
||||
import org.apache.ignite.configuration.CacheConfiguration;
|
||||
import org.apache.ignite.configuration.ClientConnectorConfiguration;
|
||||
import org.apache.ignite.configuration.ConnectorConfiguration;
|
||||
import org.apache.ignite.configuration.IgniteConfiguration;
|
||||
import org.apache.ignite.configuration.NearCacheConfiguration;
|
||||
import org.apache.ignite.events.CacheEvent;
|
||||
import org.apache.ignite.events.EventType;
|
||||
import org.apache.ignite.kubernetes.configuration.KubernetesConnectionConfiguration;
|
||||
import org.apache.ignite.lang.IgnitePredicate;
|
||||
import org.apache.ignite.logger.slf4j.Slf4jLogger;
|
||||
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
|
||||
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
|
||||
import org.apache.ignite.spi.discovery.tcp.ipfinder.kubernetes.TcpDiscoveryKubernetesIpFinder;
|
||||
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
|
||||
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
|
||||
|
||||
import com.eactive.eai.adapter.socket2.common.Env;
|
||||
import com.eactive.eai.common.logger.EAIDBLogControl;
|
||||
import com.eactive.eai.common.message.EAIMessage;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.server.EAIServerManager;
|
||||
import com.eactive.eai.common.server.EAIServerVO;
|
||||
import com.eactive.eai.common.sessioninfo.TerminalInfoDAO;
|
||||
import com.eactive.eai.common.sessioninfo.TerminalInfoVO;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
import com.eactive.eai.common.worker.Future;
|
||||
import com.eactive.eai.common.worker.ResponseMap;
|
||||
import com.eactive.eai.util.HealthCheckManager;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
|
||||
// use Ignite
|
||||
//------------------------------------------------------------------------------------
|
||||
// Important :
|
||||
// Persistence 를 사용할 경우, 일부서버 다운시 에러가 발생하므로 사용하지 않도록 한다.
|
||||
// 에러내용 : Failed to execute the cache operation
|
||||
// (all partition owners have left the grid, partition data has been lost)
|
||||
//------------------------------------------------------------------------------------
|
||||
public class SessionManagerForIgnite extends SessionManager {
|
||||
// evictMaster Instance - single socket 관련
|
||||
private static IgniteCache<String, String> evictMasterCache = null;
|
||||
// Socket Session cache 정보
|
||||
private static IgniteCache<String, SessionVO> cacheSocket = null;
|
||||
// SyncAsync Type 거래 매핑을 위한 Topic 용 cache 정보
|
||||
private static IgniteCache<String, EAIMessage> cacheTopic = null;
|
||||
// 비동기 거래 복원용
|
||||
private static IgniteCache<String, CacheStoreObject> cacheStore = null;
|
||||
|
||||
// webSocket Login cache 정보
|
||||
private static IgniteCache<String, SessionVO> cacheLogin = null; // key = loginId
|
||||
private static IgniteCache<String, String> cacheConvertUserId = null; // 단말ID 를 userID로 변경
|
||||
// HTTP Polling 에 대한 timeout 관리용
|
||||
private static IgniteCache<String, SessionVO> httpLogin = null; // key == uuid
|
||||
// Terminal용 cache 정보 ATM, 무인공과금
|
||||
private static IgniteCache<String, TerminalVO> cacheTerminal = null;
|
||||
// HTTP Login 후 WebSocket Connection 일정 시간동안 없을시 Expired되며 자동 로그아웃 발생
|
||||
private static IgniteCache<String, SessionVO> cacheWebSocketTimeout = null;
|
||||
|
||||
private static Ignite manager = null;
|
||||
|
||||
String localServerName = null;
|
||||
|
||||
private final String logPrefix = this.getClass().getName();
|
||||
|
||||
private boolean useMulticast = false;
|
||||
|
||||
private IgnitePredicate<CacheEvent> localListener = null;
|
||||
|
||||
private int cacheStoreDurationSecs = 60;
|
||||
|
||||
public void init(int communicationPort, int discoveryPort) {
|
||||
int topicTimeout = 60;
|
||||
int topicMaxSize = 10000;
|
||||
int cacheStoreMaxSize = 10000;
|
||||
|
||||
PropManager pManager = PropManager.getInstance();
|
||||
Properties prpty = pManager.getProperties(SessionManager.SESSION_MANAGER_GROUPNAME);
|
||||
// 224.0.1.0 ~ 239.255.255.255
|
||||
String mltIp = "230.0.0.1";
|
||||
|
||||
String workingDirectory = null;
|
||||
|
||||
int iPort = 4443;
|
||||
int sessionTimeout = 60;
|
||||
|
||||
int webSocketTimeout = 60;
|
||||
|
||||
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
localServerName = eaiServerManager.getLocalServerName();
|
||||
|
||||
EAIServerVO eaiServerVo = eaiServerManager.getEAIServer(localServerName);
|
||||
|
||||
if (prpty != null) {
|
||||
workingDirectory = prpty.getProperty(SessionManager.CACHE_WORKING_DIR);
|
||||
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> CACHE_WORKING_DIR = " + workingDirectory);
|
||||
}
|
||||
|
||||
mltIp = prpty.getProperty(SessionManager.SESSION_MANAGER_MULTI_GROUP_IP);
|
||||
|
||||
String sPort = prpty.getProperty(SessionManager.SESSION_MANAGER_MULTI_GROUP_PORT);
|
||||
if (sPort != null) {
|
||||
try {
|
||||
iPort = Integer.parseInt(sPort);
|
||||
} catch (NumberFormatException ex) {
|
||||
iPort = 4443;
|
||||
}
|
||||
}
|
||||
|
||||
String sTimeout = prpty.getProperty(SessionManager.SESSION_MANAGER_SESSION_TIMEOUT);
|
||||
if (sTimeout != null) {
|
||||
try {
|
||||
sessionTimeout = Integer.parseInt(sTimeout);
|
||||
if (sessionTimeout < 30)
|
||||
sessionTimeout = 30;
|
||||
} catch (NumberFormatException ex) {
|
||||
sessionTimeout = 60;
|
||||
}
|
||||
}
|
||||
|
||||
String wTimeout = prpty.getProperty(SessionManager.SESSION_MANAGER_WEBSOCKET_TIMEOUT);
|
||||
if (wTimeout != null) {
|
||||
try {
|
||||
webSocketTimeout = Integer.parseInt(wTimeout);
|
||||
} catch (NumberFormatException ex) {
|
||||
webSocketTimeout = 60;
|
||||
}
|
||||
}
|
||||
|
||||
String topicTimeoutSec = prpty.getProperty(SessionManager.CACHE_TOPIC_DURATION);
|
||||
if (topicTimeoutSec != null) {
|
||||
try {
|
||||
topicTimeout = Integer.parseInt(topicTimeoutSec);
|
||||
if (topicTimeout < 0)
|
||||
topicTimeout = 60;
|
||||
} catch (NumberFormatException ex) {
|
||||
topicTimeout = 60;
|
||||
}
|
||||
}
|
||||
String topicMax = prpty.getProperty(SessionManager.TOPIC_MAXSZIE);
|
||||
if (topicMax != null) {
|
||||
try {
|
||||
topicMaxSize = Integer.parseInt(topicMax);
|
||||
if (topicMaxSize < 0)
|
||||
topicMaxSize = 10000;
|
||||
} catch (NumberFormatException ex) {
|
||||
topicMaxSize = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
String durationSecs = prpty.getProperty(SessionManager.CACHE_STORE_DURATION);
|
||||
if (durationSecs != null) {
|
||||
try {
|
||||
cacheStoreDurationSecs = Integer.parseInt(durationSecs);
|
||||
if (cacheStoreDurationSecs < 60)
|
||||
cacheStoreDurationSecs = 60;
|
||||
} catch (NumberFormatException ex) {
|
||||
cacheStoreDurationSecs = 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
String cacheStoreMax = prpty.getProperty(SessionManager.CAHCE_STORE_MAXSIZE);
|
||||
if (cacheStoreMax != null) {
|
||||
try {
|
||||
cacheStoreMaxSize = Integer.parseInt(cacheStoreMax);
|
||||
if (cacheStoreMaxSize < 0)
|
||||
cacheStoreMaxSize = 10000;
|
||||
} catch (NumberFormatException ex) {
|
||||
cacheStoreMaxSize = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
IgniteConfiguration config = new IgniteConfiguration();
|
||||
|
||||
if(StringUtils.isNotEmpty(workingDirectory)) {
|
||||
config.setWorkDirectory(workingDirectory);
|
||||
}
|
||||
// System.setProperty("net.sf.ehcache.skipUpdateCheck", "true");
|
||||
// CommunicationSpi
|
||||
TcpCommunicationSpi communicationSpi = new TcpCommunicationSpi();
|
||||
communicationSpi.setLocalPort(communicationPort);
|
||||
communicationSpi.setIdleConnectionTimeout(15000);
|
||||
communicationSpi.setConnectTimeout(1000);
|
||||
communicationSpi.setReconnectCount(3);
|
||||
communicationSpi.setMaxConnectTimeout(30000);
|
||||
communicationSpi.setConnectionsPerNode(2);
|
||||
communicationSpi.setSlowClientQueueLimit(1000);
|
||||
|
||||
String instanceLocalGroup = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME, localServerName,
|
||||
"DEFAULT");
|
||||
|
||||
// discoverySpi
|
||||
TcpDiscoverySpi discoverySpi = new TcpDiscoverySpi();
|
||||
discoverySpi.setLocalPort(discoveryPort);
|
||||
discoverySpi.setClientReconnectDisabled(false);
|
||||
discoverySpi.setSocketTimeout(5000);
|
||||
discoverySpi.setNetworkTimeout(5000);
|
||||
discoverySpi.setAckTimeout(5000);
|
||||
discoverySpi.setMaxAckTimeout(15000);
|
||||
discoverySpi.setReconnectCount(3);
|
||||
|
||||
if (!Env.isWindows() && BooleanUtils.toBoolean(System.getProperty("scalable", "false"))) {
|
||||
// https://kubernetes.default.svc.cluster.local:443/api/v1/namespaces/card/endpoints/card-channel-runtime
|
||||
String nameSpace = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME, SESSION_MANAGER_KUBERNETES_NAMESPACE, "");
|
||||
String serviceName = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME, SESSION_MANAGER_KUBERNETES_SERVICENAME, "");
|
||||
String masterUrl = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME, SESSION_MANAGER_KUBERNETES_MASTERURL, "");
|
||||
String accountToken = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME, SESSION_MANAGER_KUBERNETES_ACCOUNTTOKEN, "");
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " >>>>Ignite INIT<<< Multicast nameSpace = " + nameSpace);
|
||||
}
|
||||
KubernetesConnectionConfiguration kubernetesCfg = new KubernetesConnectionConfiguration();
|
||||
if (StringUtils.isNotBlank(nameSpace)) {
|
||||
kubernetesCfg.setNamespace(nameSpace.trim());
|
||||
}
|
||||
if (StringUtils.isNotBlank(serviceName)) {
|
||||
kubernetesCfg.setServiceName(serviceName.trim());
|
||||
}
|
||||
if (StringUtils.isNotBlank(masterUrl)) {
|
||||
kubernetesCfg.setMasterUrl(masterUrl.trim());
|
||||
}
|
||||
if (StringUtils.isNotBlank(accountToken)) {
|
||||
kubernetesCfg.setAccountToken(accountToken.trim());
|
||||
}
|
||||
TcpDiscoveryKubernetesIpFinder ipFinder = new TcpDiscoveryKubernetesIpFinder(kubernetesCfg);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> Use TcpDiscoveryKubernetesIpFinder setting nameSpace = " + nameSpace + ", serviceName = "
|
||||
+ serviceName + ", masterUrl = " + masterUrl + ", accountToken = " + accountToken);
|
||||
logger.warn(">> Use TcpDiscoveryKubernetesIpFinder config nameSpace = " + kubernetesCfg.getNamespace()
|
||||
+ ", servcieName = " + kubernetesCfg.getServiceName() + ", masterUrl = "
|
||||
+ kubernetesCfg.getMaster() + ", accountToken = " + kubernetesCfg.getAccountToken());
|
||||
}
|
||||
discoverySpi.setIpFinder(ipFinder);
|
||||
}else {
|
||||
// ipFinder
|
||||
List<String> lists = new ArrayList<>();
|
||||
for (String key : EAIServerManager.getInstance().getAllServer().keySet()) {
|
||||
EAIServerVO vo = EAIServerManager.getInstance().getEAIServer(key);
|
||||
if ("ALL".equals(key))
|
||||
continue;
|
||||
int discoverPort = vo.getCacheRemotePort();
|
||||
String instanceGroup = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME, key, "DEFAULT");
|
||||
|
||||
// 서버그룹별 Cluster 분리
|
||||
if (instanceLocalGroup.equals(instanceGroup)) {
|
||||
String server = null;
|
||||
// 서버정보의 IP가 시스템과 다른 ip로 설정되면 기동이 안되는 문제
|
||||
if (localServerName.equals(key) && !"GW".equals(System.getProperty("spring.profiles.active", ""))) {
|
||||
server = "127.0.0.1:" + discoverPort;
|
||||
} else {
|
||||
server = vo.getAddress() + ":" + discoverPort;
|
||||
}
|
||||
lists.add(server);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("ipFind key= " + key + ", lists = " + server + ", instanceLocalGroup ="
|
||||
+ instanceLocalGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMulticast) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " >>>>Ignite INIT<<< Multicast ip = " + mltIp);
|
||||
}
|
||||
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
|
||||
ipFinder.setMulticastGroup(mltIp);
|
||||
ipFinder.setMulticastPort(iPort);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> Use TcpDiscoveryMulticastIpFinder mltIp = " + mltIp + ", port = " + iPort);
|
||||
}
|
||||
discoverySpi.setIpFinder(ipFinder);
|
||||
} else {
|
||||
if (lists.isEmpty()) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> Single Server mode skip regist TcpDiscoveryVmIpFinder addresses");
|
||||
}
|
||||
} else {
|
||||
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
|
||||
ipFinder.setAddresses(lists);
|
||||
discoverySpi.setIpFinder(ipFinder);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> Use TcpDiscoveryVmIpFinder addresses = " + lists);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String bootstrapAsynchronously = "false";
|
||||
|
||||
ClientConnectorConfiguration cliConnCfg = new ClientConnectorConfiguration();
|
||||
cliConnCfg.setPort(Integer.parseInt(eaiServerVo.getPort()) + 6);
|
||||
config.setClientConnectorConfiguration(cliConnCfg);
|
||||
|
||||
ConnectorConfiguration connectorCfg = new ConnectorConfiguration();
|
||||
connectorCfg.setPort(Integer.parseInt(eaiServerVo.getPort()) + 7);
|
||||
config.setConnectorConfiguration(connectorCfg);
|
||||
|
||||
String serverGroupName = EAIServerManager.getInstance().getServerMappingType();
|
||||
String instName = EAIServerManager.getInstance().getLocalServerName();
|
||||
|
||||
config.setGridName("elink_" + serverGroupName);// elink_mcc
|
||||
config.setIgniteInstanceName(instName);// elink_mcc
|
||||
config.setConsistentId(instName);
|
||||
|
||||
ch.qos.logback.classic.Logger blogger = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory
|
||||
.getLogger("org.apache.ignite");
|
||||
blogger.setLevel(Level.INFO);
|
||||
|
||||
IgniteLogger log = new Slf4jLogger((org.slf4j.Logger) blogger);
|
||||
config.setGridLogger(log);
|
||||
config.setMetricsLogFrequency(10 * 60 * 1000); // 10분
|
||||
|
||||
config.setCommunicationSpi(communicationSpi);
|
||||
config.setDiscoverySpi(discoverySpi);
|
||||
config.setClientMode(false);
|
||||
config.setIncludeEventTypes(EventType.EVT_CACHE_OBJECT_PUT, EventType.EVT_CACHE_OBJECT_REMOVED,
|
||||
EventType.EVT_CACHE_OBJECT_EXPIRED
|
||||
// , EventType.EVT_NODE_JOINED
|
||||
// , EventType.EVT_NODE_LEFT
|
||||
);
|
||||
|
||||
List<CacheConfiguration> caches = new ArrayList<>();
|
||||
// Default
|
||||
caches.add(initCache(config, 0, bootstrapAsynchronously, ADAPTER_MASTER_CAHCE_NAME, 10, false));
|
||||
caches.add(initCache(config, 0, bootstrapAsynchronously, ADAPTER_CAHCE_NAME, 10000, false));
|
||||
|
||||
caches.add(initCache(config, topicTimeout, bootstrapAsynchronously, TOPIC_CAHCE_NAME, topicMaxSize, false));
|
||||
|
||||
if(logger.isWarn()) {
|
||||
logger.warn(STORE_CAHCE_NAME +" - cacheStoreDurationSecs = " + cacheStoreDurationSecs);
|
||||
}
|
||||
|
||||
caches.add(initCache(config, cacheStoreDurationSecs, bootstrapAsynchronously, STORE_CAHCE_NAME, cacheStoreMaxSize, false));
|
||||
|
||||
// for MCI
|
||||
caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, LOGIN_CAHCE_NAME, 20000, false));
|
||||
caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, HTTP_CAHCE_NAME, 20000, false));
|
||||
caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, USERID_CAHCE_NAME, 20000, false));
|
||||
caches.add(initCache(config, webSocketTimeout, bootstrapAsynchronously, WEBSOCKER_CAHCE_NAME, 20000, false));
|
||||
caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, TERMINAL_CAHCE_NAME, 20000, false));
|
||||
|
||||
config.setCacheConfiguration(caches.stream().toArray(CacheConfiguration[]::new));
|
||||
|
||||
// Start a node.
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> Ignition.starting...");
|
||||
}
|
||||
manager = Ignition.start(config);
|
||||
manager.cluster().active(true);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(">> Ignition.started.");
|
||||
}
|
||||
|
||||
IgniteEvents events = manager.events();
|
||||
// Local listener that listens to local events.
|
||||
localListener = new IgniteEvent();
|
||||
|
||||
// Subscribe to the cache events that are triggered on the local node.
|
||||
events.localListen(localListener,
|
||||
EventType.EVT_CACHE_OBJECT_PUT,
|
||||
EventType.EVT_CACHE_OBJECT_REMOVED,
|
||||
EventType.EVT_CACHE_OBJECT_EXPIRED);
|
||||
|
||||
evictMasterCache = manager.cache(ADAPTER_MASTER_CAHCE_NAME);
|
||||
cacheSocket = manager.cache(ADAPTER_CAHCE_NAME);
|
||||
cacheTopic = manager.cache(TOPIC_CAHCE_NAME);
|
||||
cacheStore = manager.cache(STORE_CAHCE_NAME);
|
||||
|
||||
cacheLogin = manager.cache(LOGIN_CAHCE_NAME);
|
||||
httpLogin = manager.cache(HTTP_CAHCE_NAME);
|
||||
cacheConvertUserId = manager.cache(USERID_CAHCE_NAME);
|
||||
cacheWebSocketTimeout = manager.cache(WEBSOCKER_CAHCE_NAME);
|
||||
cacheTerminal = manager.cache(TERMINAL_CAHCE_NAME);
|
||||
}
|
||||
|
||||
private CacheConfiguration initCache(IgniteConfiguration config, int expiryDurationSecs, String bootstrapAsynchronously,
|
||||
String name, int maxsize, boolean useCacheWriteModeAsync) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug(logPrefix + " create " + name + " cache expiryDurationSecs=" + expiryDurationSecs);
|
||||
}
|
||||
// near-cache
|
||||
NearCacheConfiguration nearConfiguration = new NearCacheConfiguration();
|
||||
LruEvictionPolicy nearEvictionPolicy = new LruEvictionPolicy();
|
||||
nearEvictionPolicy.setMaxSize(maxsize);
|
||||
nearConfiguration.setNearEvictionPolicy(nearEvictionPolicy);
|
||||
|
||||
CacheConfiguration cacheConfig = new CacheConfiguration(name);
|
||||
// REPLICATED,PARTITIONED(default)
|
||||
// cacheConfig.setCacheMode(CacheMode.REPLICATED);
|
||||
cacheConfig.setCacheMode(CacheMode.PARTITIONED);
|
||||
|
||||
// ATOMIC,TRANSACTIONAL
|
||||
cacheConfig.setAtomicityMode(CacheAtomicityMode.ATOMIC);
|
||||
|
||||
// Set the number of backups (replicas) for each partition : default(0)
|
||||
cacheConfig.setBackups(1);
|
||||
// Enable reading from backups to improve read consistency : default(true)
|
||||
cacheConfig.setReadFromBackup(true);
|
||||
|
||||
// FULL_SYNC/FULL_ASYNC/PRIMARY_SYNC(default)
|
||||
if (useCacheWriteModeAsync) {
|
||||
cacheConfig.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_ASYNC);
|
||||
} else {
|
||||
// cacheConfig.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
|
||||
cacheConfig.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
|
||||
}
|
||||
|
||||
if(expiryDurationSecs > 0) {
|
||||
cacheConfig
|
||||
.setExpiryPolicyFactory(ModifiedExpiryPolicy.factoryOf(new Duration(TimeUnit.SECONDS, expiryDurationSecs)));
|
||||
}
|
||||
else {
|
||||
cacheConfig
|
||||
.setExpiryPolicyFactory( ModifiedExpiryPolicy.factoryOf(Duration.ETERNAL) );
|
||||
}
|
||||
cacheConfig.setNearConfiguration(nearConfiguration);
|
||||
return cacheConfig;
|
||||
}
|
||||
|
||||
// WebSocket Login 관련
|
||||
public SessionVO getLogin(String key) {
|
||||
try {
|
||||
return cacheLogin.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("getLogin null key=" + key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putLogin(String key, SessionVO value) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put session key - " + key + ", Session - " + value.toString());
|
||||
}
|
||||
cacheLogin.put(key, value);
|
||||
// terminal to userID 매핑 생성
|
||||
if (value != null && value.getTerminalId() != null) {
|
||||
cacheConvertUserId.put(value.getTerminalId(), key);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLogin(String key) {
|
||||
SessionVO vo = getLogin(key);
|
||||
// terminal to userID 매핑 제거
|
||||
if (vo != null && vo.getTerminalId() != null) {
|
||||
cacheConvertUserId.remove(vo.getTerminalId());
|
||||
}
|
||||
cacheLogin.remove(key);
|
||||
}
|
||||
|
||||
// terminalId 2 userId convert
|
||||
public String getConvertUserId(String key) {
|
||||
try {
|
||||
return cacheConvertUserId.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("getConvertUserId null key=" + key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public SessionVO getHttpLogin(String key) {
|
||||
try {
|
||||
return httpLogin.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("getHttpLogin null key=" + key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putHttpLogin(String key, SessionVO value) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put session key - " + key + ", Session - " + value.toString());
|
||||
}
|
||||
httpLogin.put(key, value);
|
||||
}
|
||||
|
||||
public void removeHTTPLogin(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove http login session key - " + key);
|
||||
}
|
||||
httpLogin.remove(key);
|
||||
}
|
||||
|
||||
// Single Socket 관련
|
||||
public SessionVO getConnectionInfo(String key) {
|
||||
try {
|
||||
return cacheSocket.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("getConnectionInfo null key=" + key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public SessionVO getConnectionStatus(String adapterGroupName) {
|
||||
SessionVO sessionVo = null;
|
||||
try {
|
||||
sessionVo = getConnectionInfo(adapterGroupName);
|
||||
|
||||
if (sessionVo != null) {
|
||||
String connectedInst = sessionVo.getLoginInstId();
|
||||
// 싱글어댑터 Start --------------------------->
|
||||
// EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
// String localServerName = eaiServerManager.getLocalServerName();
|
||||
|
||||
// 로컬서버가 연결시도 중인데 캐시에 자신의 인스던스가 있을경우 삭제
|
||||
if (localServerName.equals(connectedInst)) {
|
||||
cacheSocket.remove(adapterGroupName);
|
||||
return null;
|
||||
}
|
||||
// 싱글어댑터 End <---------------------------
|
||||
|
||||
// 케시에서 조회된 인스던스가 살았는지 확인 - 좀비캐시 삭제
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("getConnectionInfo check primary server status - " + connectedInst);
|
||||
}
|
||||
boolean isAlive = HealthCheckManager.getInstance().getServerStatus(connectedInst);
|
||||
|
||||
if (!isAlive) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("getConnectionInfo check primary server is Not Alive, clear cache.");
|
||||
}
|
||||
cacheSocket.remove(adapterGroupName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return sessionVo;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putConnectionInfo(String key, SessionVO value) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put socket session key - " + key + ", Session - " + value.toString());
|
||||
}
|
||||
try {
|
||||
cacheSocket.put(key, value);
|
||||
} catch (Exception e) {
|
||||
logger.error("Put socket session error key=" + key + " Session - " + value.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeConnectionInfo(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove socket session key - " + key);
|
||||
}
|
||||
try {
|
||||
cacheSocket.remove(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("Remove socket session error key=" + key, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Topic 관련
|
||||
public EAIMessage getTopic(String key) {
|
||||
try {
|
||||
return cacheTopic.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("getTopic null key=" + key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putTopic(String key, EAIMessage value) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put Topic response - " + key + ", value - " + value.toString());
|
||||
}
|
||||
|
||||
// local event인 경우 ignite skip
|
||||
Future future = ResponseMap.getInstance().get(key);
|
||||
if(future != null) {
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("PutTopic] local [" + key + "] put to Future");
|
||||
}
|
||||
future.getSlot().put(value);
|
||||
return;
|
||||
}
|
||||
// remote Event
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("PutTopic] remote [" + key + "] put to Future");
|
||||
}
|
||||
int retry = 3;
|
||||
while(!cacheTopic.putIfAbsent(key, value) && retry > 0) {
|
||||
retry--;
|
||||
try {
|
||||
Thread.sleep(300);
|
||||
} catch (InterruptedException e) {
|
||||
if(logger.isDebug()) {
|
||||
logger.debug("PutTopic] sleep Fail");
|
||||
}
|
||||
}
|
||||
if (logger.isDebug()) {
|
||||
logger.debug("PutTopic] remote retry [" + key + "] put to Future");
|
||||
}
|
||||
};
|
||||
removeTopic(key);
|
||||
}
|
||||
|
||||
public void removeTopic(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove Topic response key - " + key);
|
||||
}
|
||||
cacheTopic.remove(key);
|
||||
}
|
||||
|
||||
// cacheStore 관련
|
||||
public String getCacheStore(String key) {
|
||||
try {
|
||||
// Important : get 힌 후 바로 remove 하므로, 객체를 생성해서 return 해야 함.
|
||||
// String message = cacheStore.get(key);
|
||||
CacheStoreObject object = cacheStore.get(key);
|
||||
if (object.isExpired()) {
|
||||
if (logger.isWarn())
|
||||
logger.warn("getCacheStore expired key [" + key + "]");
|
||||
cacheStore.remove(key);
|
||||
return null;
|
||||
} else {
|
||||
return object.getMessage();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("getTopic null key [" + key + "]", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void putCacheStore(String key, String value, int ttlSecs) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put CacheStore key [" + key + "], value - " + value);
|
||||
}
|
||||
// cacheStore.put(key, value);
|
||||
CacheStoreObject object = new CacheStoreObject(value, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ttlSecs));
|
||||
cacheStore.put(key, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putCacheStore(String key, String value) {
|
||||
putCacheStore(key, value, cacheStoreDurationSecs);
|
||||
}
|
||||
|
||||
public void removeCacheStore(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove CacheStore key [" + key + "]");
|
||||
}
|
||||
cacheStore.remove(key);
|
||||
}
|
||||
|
||||
// Terminal
|
||||
public TerminalVO getTerminal(String key) {
|
||||
try {
|
||||
return cacheTerminal.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("getTerminal null key=" + key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void putTerminal(String key, TerminalVO value, TerminalInfoVO terminalInfoVO) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Put terminal key - " + key + ", Terminal - " + value.toString());
|
||||
}
|
||||
cacheTerminal.put(key, value);
|
||||
if (terminalInfoVO != null && EAIDBLogControl.isEnable()) {
|
||||
try {
|
||||
TerminalInfoDAO dao = ApplicationContextProvider.getContext().getBean(TerminalInfoDAO.class);
|
||||
dao.upsertTerminalInfo(terminalInfoVO);
|
||||
} catch (Exception e) {
|
||||
logger.error(" insert Terminal DB ERROR. - " + e.getMessage(), e);
|
||||
}
|
||||
} else if (terminalInfoVO != null) {
|
||||
logger.error("DB 장애로 업데이트 미수행 - " + value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTerminal(String key) {
|
||||
if (logger.isWarn()) {
|
||||
logger.warn("Remove socket teminal session key - " + key);
|
||||
}
|
||||
try {
|
||||
// 서버다운시 org.apache.ignite.internal.processors.cache.CacheStoppedException 때문에
|
||||
// try catch 추가 : jun's 20220826
|
||||
cacheTerminal.remove(key);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error(" cacheTerminal remove error. - " + key, e);
|
||||
}
|
||||
if (EAIDBLogControl.isEnable()) {
|
||||
try {
|
||||
TerminalInfoDAO dao = ApplicationContextProvider.getContext().getBean(TerminalInfoDAO.class);
|
||||
TerminalInfoVO terminalInfoVO = new TerminalInfoVO(key);
|
||||
terminalInfoVO.setSocSessionStatus(TerminalInfoVO.Status.inactive);
|
||||
dao.upsertTerminalInfo(terminalInfoVO);
|
||||
} catch (Exception e) {
|
||||
logger.error(" insert Terminal DB ERROR. - " + key, e);
|
||||
}
|
||||
} else {
|
||||
logger.error(" DB 장애로 인해 업데이트 미수행 - " + key);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private CacheInfoVO convert(IgniteCache cache) {
|
||||
CacheInfoVO v = new CacheInfoVO();
|
||||
long timeToLive = 0;
|
||||
CacheConfiguration cf = (CacheConfiguration) cache.getConfiguration(CacheConfiguration.class);
|
||||
Factory factory = cf.getExpiryPolicyFactory();
|
||||
Object obj = factory.create();
|
||||
if (obj instanceof TouchedExpiryPolicy) {
|
||||
TouchedExpiryPolicy cep = (TouchedExpiryPolicy) obj;
|
||||
Duration dur = cep.getExpiryForCreation();
|
||||
timeToLive = dur.getTimeUnit().toMillis(dur.getDurationAmount());
|
||||
}
|
||||
v.setTimeToLive(timeToLive);
|
||||
v.setName(cache.getName());
|
||||
|
||||
List<String> keys = new ArrayList<>();
|
||||
QueryCursor<Cache.Entry<String, SessionVO>> cursor = cache.query(new ScanQuery<>());
|
||||
cursor.forEach(entry -> keys.add(entry.getKey()));
|
||||
v.setKeys(keys);
|
||||
v.setSize(keys.size());
|
||||
return v;
|
||||
}
|
||||
|
||||
public CacheInfoVO getLoginCache() {
|
||||
return convert(cacheLogin);
|
||||
}
|
||||
|
||||
public CacheInfoVO getHttpLoginCache() {
|
||||
return convert(httpLogin);
|
||||
}
|
||||
|
||||
public CacheInfoVO getEvictMasterCache() {
|
||||
return convert(evictMasterCache);
|
||||
}
|
||||
|
||||
public CacheInfoVO getTerminalCache() {
|
||||
return convert(cacheTerminal);
|
||||
}
|
||||
|
||||
public CacheInfoVO getConvertUserIdCache() {
|
||||
return convert(cacheConvertUserId);
|
||||
}
|
||||
|
||||
public CacheInfoVO getSocketCache() {
|
||||
return convert(cacheSocket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putWebSocketTimeout(String key, SessionVO value) {
|
||||
cacheWebSocketTimeout.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWebSocketTimeout(String key) {
|
||||
cacheWebSocketTimeout.remove(key);
|
||||
}
|
||||
|
||||
public String getMasterInstId() {
|
||||
try {
|
||||
return evictMasterCache.get(MASTER_KEY);
|
||||
} catch (Exception e) {
|
||||
logger.error("getMasterInstId null key=" + MASTER_KEY, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void closeManager() {
|
||||
if(localListener != null) {
|
||||
((IgniteEvent) localListener).shutdown();
|
||||
}
|
||||
manager.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCacheStatus() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Iterable<String> cacheNames = manager.cacheNames();
|
||||
sb.append("<Caches type=\"Ignite\">").append("\n");
|
||||
for (String cacheName : cacheNames) {
|
||||
IgniteCache<Object, Object> cache = manager.cache(cacheName);
|
||||
CacheMetrics metrics = cache.metrics();
|
||||
long cacheSize = metrics.getSize();
|
||||
sb.append("<Cache name=\"" + cacheName + "\" Size=\"" + cacheSize).append("\"/>\n");
|
||||
}
|
||||
sb.append("</Caches>");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.eactive.eai.common.logger.EAIDBLogControl;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoDAO;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoVO;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoVO.Status;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
@Component
|
||||
public class SessionStatusManager {
|
||||
|
||||
private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
|
||||
|
||||
// private static SessionStatusManager instance;
|
||||
|
||||
@Autowired
|
||||
SessionInfoDAO sessionInfoDAO;
|
||||
|
||||
private SessionStatusManager() {
|
||||
}
|
||||
|
||||
public static SessionStatusManager getInstance() {
|
||||
return ApplicationContextProvider.getContext().getBean(SessionStatusManager.class);
|
||||
}
|
||||
|
||||
public void manageStatus(SessionInfoVO sessionInfoVO) {
|
||||
|
||||
if (EAIDBLogControl.isEnable()) {
|
||||
try {
|
||||
sessionInfoDAO.upsertSessionInfo(sessionInfoVO);
|
||||
} catch (Exception e) {
|
||||
if (logger.isError()) {
|
||||
logger.error("Insert Session DB ERROR. - " + sessionInfoVO.getUserId(), e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger.isError()) {
|
||||
logger.error("EAIDBLogControl is not enable - " + sessionInfoVO.getUserId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void manageLoginStatus(String userId) {
|
||||
SessionVO login = SessionManager.getInstance().getLogin(userId);
|
||||
Status status = login == null ? SessionInfoVO.Status.inactive : SessionInfoVO.Status.active;
|
||||
SessionInfoVO sessionInfoVO = new SessionInfoVO(userId);
|
||||
sessionInfoVO.setSessionStatus(status);
|
||||
|
||||
/** upsert **/
|
||||
manageStatus(sessionInfoVO);
|
||||
}
|
||||
|
||||
public void manageLoginStatusWithUUID(SessionVO session) {
|
||||
|
||||
SessionVO login = SessionManager.getInstance().getHttpLogin(session.getUuid());
|
||||
Status status = login == null ? SessionInfoVO.Status.inactive : SessionInfoVO.Status.active;
|
||||
String userId = login == null ? session.getLoginUserId() : login.getLoginUserId();
|
||||
SessionInfoVO sessionInfoVO = new SessionInfoVO(session.getLoginUserId());
|
||||
sessionInfoVO.setSessionId(session.getUuid());
|
||||
sessionInfoVO.setUserId(userId);
|
||||
sessionInfoVO.setSessionStatus(status);
|
||||
|
||||
/** upsert **/
|
||||
manageStatus(sessionInfoVO);
|
||||
}
|
||||
public void manageWebSocketStatus(String userId, Status status) {
|
||||
SessionInfoVO sessionInfoVO = new SessionInfoVO(userId);
|
||||
sessionInfoVO.setWsocSessionStatus(status);
|
||||
|
||||
/** upsert **/
|
||||
manageStatus(sessionInfoVO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 1. 기능 : SessionVO 객체
|
||||
* 2. 처리 개요 :
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
* :
|
||||
*/
|
||||
public class SessionVO implements Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8397247737238565420L;
|
||||
|
||||
private String loginUserId;
|
||||
private String loginInstId;
|
||||
private String wsInstId;
|
||||
private String wsAdapterGroupName;
|
||||
private String uuid;
|
||||
private String primaryInst; // 싱글어댑터
|
||||
|
||||
//국코드 추가
|
||||
private String brncd;
|
||||
// private String sessionAES;
|
||||
// private String httpSessionId;
|
||||
private String terminalId;
|
||||
|
||||
public SessionVO() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
public SessionVO(String loginUserId, String loginInstId, String uuid) {
|
||||
super();
|
||||
this.loginUserId = loginUserId;
|
||||
this.loginInstId = loginInstId;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getLoginUserId() {
|
||||
return loginUserId;
|
||||
}
|
||||
public void setLoginUserId(String loginUserId) {
|
||||
this.loginUserId = loginUserId;
|
||||
}
|
||||
public String getLoginInstId() {
|
||||
return loginInstId;
|
||||
}
|
||||
public void setLoginInstId(String loginInstId) {
|
||||
this.loginInstId = loginInstId;
|
||||
}
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
// public String getSessionAES() {
|
||||
// return sessionAES;
|
||||
// }
|
||||
//
|
||||
// public void setSessionAES(String sessionAES) {
|
||||
// this.sessionAES = sessionAES;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public String getHttpSessionId() {
|
||||
// return httpSessionId;
|
||||
// }
|
||||
//
|
||||
// public void setHttpSessionId(String httpSessionId) {
|
||||
// this.httpSessionId = httpSessionId;
|
||||
// }
|
||||
|
||||
public String getWsInstId() {
|
||||
return wsInstId;
|
||||
}
|
||||
|
||||
public void setWsInstId(String wsInstId) {
|
||||
this.wsInstId = wsInstId;
|
||||
}
|
||||
|
||||
public String getWsAdapterGroupName() {
|
||||
return wsAdapterGroupName;
|
||||
}
|
||||
|
||||
public void setWsAdapterGroupName(String wsAdapterGroupName) {
|
||||
this.wsAdapterGroupName = wsAdapterGroupName;
|
||||
}
|
||||
|
||||
public String getBrncd() {
|
||||
return brncd;
|
||||
}
|
||||
|
||||
public void setBrncd(String brncd) {
|
||||
this.brncd = brncd;
|
||||
}
|
||||
|
||||
public String getTerminalId() {
|
||||
return terminalId;
|
||||
}
|
||||
|
||||
public void setTerminalId(String terminalId) {
|
||||
this.terminalId = terminalId;
|
||||
}
|
||||
|
||||
public String getPrimaryInst() {
|
||||
return primaryInst;
|
||||
}
|
||||
|
||||
public void setPrimaryInst(String primaryInst) {
|
||||
this.primaryInst = primaryInst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SessionVO [loginUserId=" + loginUserId + ", loginInstId=" + loginInstId + ", wsInstId=" + wsInstId
|
||||
+ ", wsAdapterGroupName=" + wsAdapterGroupName + ", uuid=" + uuid + ", brncd=" + brncd + ", terminalId="
|
||||
+ terminalId + ", primaryInst="+ primaryInst +"]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.mina.common.IoSession;
|
||||
|
||||
import com.eactive.eai.adapter.socket2.common.ExpiringMap;
|
||||
import com.eactive.eai.common.lifecycle.Lifecycle;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleException;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleListener;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleSupport;
|
||||
import com.eactive.eai.common.server.EAIServerManager;
|
||||
import com.eactive.eai.common.sessioninfo.SessionInfoVO;
|
||||
import com.eactive.eai.common.util.DatetimeUtil;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
/**
|
||||
* 1. 기능 : websocket session 정보를 관리하는 Manager 클래스
|
||||
* 2. 처리 개요 : ehcache 로 session 을 공유함.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
* :
|
||||
*/
|
||||
public class TcpSessionManager implements Lifecycle
|
||||
{
|
||||
/**
|
||||
* Default Logger
|
||||
*/
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
/**
|
||||
* SessionManager Single Instance
|
||||
*/
|
||||
private static TcpSessionManager instance;
|
||||
/**
|
||||
* cache 정보
|
||||
*/
|
||||
private static ExpiringMap<String,String> uidCache ; //<sessionString, uid>
|
||||
|
||||
private static ExpiringMap<String, IoSession> chnCache ; //<uid, session>
|
||||
|
||||
|
||||
/**
|
||||
* 기동 여부
|
||||
*/
|
||||
private boolean started;
|
||||
|
||||
/**
|
||||
* LifeccyleSupport object
|
||||
*/
|
||||
private LifecycleSupport lifecycle = new LifecycleSupport(this);
|
||||
|
||||
/**
|
||||
* 1. 기능 : Default Constructor
|
||||
* 2. 처리 개요 : 라우팅 Rule 정보를 저장하기 위한 HashMap을 초기화한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
**/
|
||||
private TcpSessionManager() {
|
||||
//init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : SessionManager Singleton Object를 반환하는 getter method
|
||||
* 2. 처리 개요 : SessionManager Singleton Object를 반환한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return SessionManager Singleton object
|
||||
**/
|
||||
public static TcpSessionManager getInstance() {
|
||||
if(instance == null) {
|
||||
synchronized(TcpSessionManager.class) {
|
||||
if(instance==null) {
|
||||
instance = new TcpSessionManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Lifecycle의 start 메서드로 RoutingMangaer를 초기화하는 메서드
|
||||
* 2. 처리 개요 : RoutingDAO를 이용해 추출 Rule 정보 모두를 가져와 초기화한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @exception LifecycleException 이미 시작되었거나(RECEAICBM201), RoutingDAO를 통해 Rule 정보를 가져오다 DAOExcepiton이 발생될 경우(RECEAICRT201)
|
||||
*
|
||||
**/
|
||||
public void start() throws LifecycleException {
|
||||
if (started)
|
||||
throw new LifecycleException("RECEAICRT201");
|
||||
|
||||
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
|
||||
|
||||
|
||||
this.uidCache = new ExpiringMap<String,String>(86400,600);
|
||||
this.chnCache = new ExpiringMap<String,IoSession>(86400,600);
|
||||
// this.uuidCache = new ExpiringMap<String,IoSession>(60,1);
|
||||
// this.chnCache = new ExpiringMap<String,IoSession>(60,1);
|
||||
|
||||
started = true;
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Lifecycle의 stop 메서드로 SessionManager를 종료하는 메서드
|
||||
* 2. 처리 개요 : 멤버에 캐싱한 라우팅 Rule 정보를 clear한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @exception LifecycleException 이미 종료된 경우 발생(RECEAICRT203)
|
||||
**/
|
||||
public void stop() throws LifecycleException {
|
||||
// Validate and update our current component state
|
||||
if (!started)
|
||||
throw new LifecycleException("RECEAICRT203");
|
||||
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
|
||||
|
||||
|
||||
|
||||
|
||||
started = false;
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : LifecycleListener를 등록하는 메서드
|
||||
* 2. 처리 개요 : LifecycleListener를 등록한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param listener LifecycleEvent를 수신한 LifecycleListener
|
||||
**/
|
||||
public void addLifecycleListener(LifecycleListener listener)
|
||||
{
|
||||
lifecycle.addLifecycleListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : 등록된 LifecycleListener 리스트를 반환하는 메서드
|
||||
* 2. 처리 개요 : 등록된 LifecycleListener 리스트를 반환하다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return 등록된 LifecycleListener 리스트
|
||||
**/
|
||||
public LifecycleListener[] findLifecycleListeners()
|
||||
{
|
||||
return lifecycle.findLifecycleListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : 등록된 LifecycleListener를 삭제하는 메서드
|
||||
* 2. 처리 개요 : 파라미터의 LifecycleListener를 삭제한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param listener 삭제할 LifecycleListener
|
||||
**/
|
||||
public void removeLifecycleListener(LifecycleListener listener)
|
||||
{
|
||||
lifecycle.removeLifecycleListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : SessionManager의 초기화 여부를 반환하는 getter 메서드
|
||||
* 2. 처리 개요 : SessionManager의 초기화 여부를 반환한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return 초기화 여부
|
||||
**/
|
||||
public boolean isStarted() {
|
||||
return this.started;
|
||||
}
|
||||
|
||||
public ExpiringMap getSessionList(){
|
||||
return chnCache;
|
||||
}
|
||||
public synchronized void sessionOpen(IoSession session){
|
||||
logger.warn("TcpSessionManager ] session Opened - [ " + session + "]");
|
||||
}
|
||||
|
||||
// public synchronized void sessionLogin(String uuid, String usrid, IoSession session){
|
||||
// if(usrid == null && session == null){
|
||||
// return;
|
||||
// }
|
||||
// this.uidCache.put(session.toString(), usrid);
|
||||
// this.chnCache.put(usrid, session);
|
||||
//
|
||||
// logger.warn("TcpSessionManager ] session saved " + uuid + "["+usrid+"] : " + session);
|
||||
//
|
||||
//
|
||||
// EAIServerManager eaiServerManager = EAIServerManager.getInstance();
|
||||
// String serverName = eaiServerManager.getLocalServerName();
|
||||
//
|
||||
// SessionVO sessionVo = new SessionVO();
|
||||
// sessionVo.setUuid(uuid);
|
||||
// sessionVo.setLoginUserId(usrid);
|
||||
// sessionVo.setLoginInstId(serverName);
|
||||
//
|
||||
// SessionInfoVO sessionInfoVO = new SessionInfoVO(usrid);
|
||||
// sessionInfoVO.setSessionId(uuid);
|
||||
// sessionInfoVO.setCreateTime(DatetimeUtil.getCurrentDateTime());
|
||||
//
|
||||
// SessionManager.getInstance().putLogin(session.toString(), sessionVo, sessionInfoVO);
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
public synchronized void sessionClose(IoSession session){
|
||||
try{
|
||||
String sessionId = session.toString();
|
||||
String userId = null;
|
||||
try{
|
||||
userId = this.uidCache.get(sessionId);
|
||||
this.uidCache.remove(sessionId);
|
||||
}catch(NullPointerException e){
|
||||
logger.error("TcpSessionManager ] tried to remove Cache , but UIDCache value of ["+sessionId+"] is null ");
|
||||
}
|
||||
try{
|
||||
if(userId != null) this.chnCache.remove(userId);
|
||||
}catch(NullPointerException e){
|
||||
logger.error("TcpSessionManager ] tried to remove Cache , but ChnCache value of ["+sessionId+"] is null ");
|
||||
}
|
||||
try{
|
||||
if(userId != null) {
|
||||
ChannelSessionFacade.getInstance().removeFromLoginCache(userId);
|
||||
}
|
||||
}catch(NullPointerException e){
|
||||
logger.error("TcpSessionManager ] tried to remove Cache , but ehCache value of ["+sessionId+"] is null ");
|
||||
}
|
||||
}catch(Exception e){
|
||||
logger.error("TcpSessionManager ] Error occured in removing Session Info - " + session);
|
||||
}
|
||||
}
|
||||
public synchronized String getUid(String sessionId){
|
||||
String uid = uidCache.get(sessionId);
|
||||
return uid;
|
||||
}
|
||||
public synchronized IoSession getSession(String sessionId){
|
||||
IoSession session = chnCache.get(sessionId);
|
||||
return session;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 1. 기능 : SessionVO 객체 2. 처리 개요 : 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since : :
|
||||
*/
|
||||
public class TerminalVO implements Serializable {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
private String terminalNo;
|
||||
private String rofcCd;// 청코드
|
||||
private String brncd;// 국코드
|
||||
private String brnName;// 국명
|
||||
private boolean isOpenTran;// 개국거래여부
|
||||
private boolean isOpen; //개국여부
|
||||
|
||||
public TerminalVO() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getTerminalNo() {
|
||||
return terminalNo;
|
||||
}
|
||||
|
||||
public void setTerminalNo(String terminalNo) {
|
||||
this.terminalNo = terminalNo;
|
||||
}
|
||||
|
||||
public String getRofcCd() {
|
||||
return rofcCd;
|
||||
}
|
||||
|
||||
public void setRofcCd(String rofcCd) {
|
||||
this.rofcCd = rofcCd;
|
||||
}
|
||||
|
||||
public String getBrncd() {
|
||||
return brncd;
|
||||
}
|
||||
|
||||
public void setBrncd(String brncd) {
|
||||
this.brncd = brncd;
|
||||
}
|
||||
|
||||
public String getBrnName() {
|
||||
return brnName;
|
||||
}
|
||||
|
||||
public void setBrnName(String brnName) {
|
||||
this.brnName = brnName;
|
||||
}
|
||||
|
||||
public boolean isOpenTran() {
|
||||
return isOpenTran;
|
||||
}
|
||||
|
||||
public void setOpenTran(boolean isOpenTran) {
|
||||
this.isOpenTran = isOpenTran;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
public void setOpen(boolean isOpen) {
|
||||
this.isOpen = isOpen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TerminalVO [terminalNo=" + terminalNo + ", rofcCd=" + rofcCd + ", brncd=" + brncd + ", brnName="
|
||||
+ brnName + ", isOpenTran=" + isOpenTran + ", isOpen=" + isOpen + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Copyright Terracotta, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.distribution.CachePeer;
|
||||
import net.sf.ehcache.distribution.RMICacheManagerPeerProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A provider of Peer RMI addresses based off manual configuration.
|
||||
* <p/>
|
||||
* Because there is no monitoring of whether a peer is actually there, the list of peers is dynamically
|
||||
* looked up and verified each time a lookup request is made.
|
||||
* <p/>
|
||||
*
|
||||
* @author Greg Luck
|
||||
* @version $Id: ManualRMICacheManagerPeerProvider.java 5594 2012-05-07 16:04:31Z cdennis $
|
||||
*/
|
||||
public final class TimeoutManualRMICacheManagerPeerProvider extends RMICacheManagerPeerProvider {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TimeoutManualRMICacheManagerPeerProvider.class.getName());
|
||||
|
||||
/**
|
||||
* Empty constructor.
|
||||
*/
|
||||
public TimeoutManualRMICacheManagerPeerProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final void init() {
|
||||
//nothing to do here
|
||||
}
|
||||
|
||||
/**
|
||||
* Time for a cluster to form. This varies considerably, depending on the implementation.
|
||||
*
|
||||
* @return the time in ms, for a cluster to form
|
||||
*/
|
||||
public long getTimeForClusterToForm() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new peer.
|
||||
*
|
||||
* @param rmiUrl
|
||||
*/
|
||||
public final synchronized void registerPeer(String rmiUrl) {
|
||||
peerUrls.put(rmiUrl, new Date());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return a list of {@link CachePeer} peers, excluding the local peer.
|
||||
*/
|
||||
public final synchronized List listRemoteCachePeers(Ehcache cache) throws CacheException {
|
||||
List remoteCachePeers = new ArrayList();
|
||||
List staleList = new ArrayList();
|
||||
for (Iterator iterator = peerUrls.keySet().iterator(); iterator.hasNext();) {
|
||||
String rmiUrl = (String) iterator.next();
|
||||
String rmiUrlCacheName = extractCacheName(rmiUrl);
|
||||
|
||||
if (!rmiUrlCacheName.equals(cache.getName())) {
|
||||
continue;
|
||||
}
|
||||
Date date = (Date) peerUrls.get(rmiUrl);
|
||||
if (!stale(date)) {
|
||||
CachePeer cachePeer = null;
|
||||
try {
|
||||
cachePeer = lookupRemoteCachePeer(rmiUrl);
|
||||
remoteCachePeers.add(cachePeer);
|
||||
} catch (Exception e) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Looking up rmiUrl " + rmiUrl + " through exception " + e.getMessage()
|
||||
+ ". This may be normal if a node has gone offline. Or it may indicate network connectivity"
|
||||
+ " difficulties", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG.debug("rmiUrl {} should never be stale for a manually configured cluster.", rmiUrl);
|
||||
staleList.add(rmiUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Remove any stale remote peers. Must be done here to avoid concurrent modification exception.
|
||||
for (int i = 0; i < staleList.size(); i++) {
|
||||
String rmiUrl = (String) staleList.get(i);
|
||||
peerUrls.remove(rmiUrl);
|
||||
}
|
||||
return remoteCachePeers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether the entry should be considered stale.
|
||||
* <p/>
|
||||
* Manual RMICacheManagerProviders use a static list of urls and are therefore never stale.
|
||||
*
|
||||
* @param date the date the entry was created
|
||||
* @return true if stale
|
||||
*/
|
||||
protected final boolean stale(Date date) {
|
||||
return false;
|
||||
}
|
||||
static String extractCacheName(String rmiUrl) {
|
||||
return rmiUrl.substring(rmiUrl.lastIndexOf('/') + 1);
|
||||
}
|
||||
public CachePeer lookupRemoteCachePeer(String url) throws MalformedURLException, NotBoundException, RemoteException {
|
||||
LOG.debug("Lookup URL {}", url);
|
||||
CachePeer cachePeer = (CachePeer) TimeoutNaming.lookup(url);
|
||||
return cachePeer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.rmi.AccessException;
|
||||
import java.rmi.AlreadyBoundException;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>Naming</code> class provides methods for storing and obtaining
|
||||
* references to remote objects in a remote object registry. Each method of
|
||||
* the <code>Naming</code> class takes as one of its arguments a name that
|
||||
* is a <code>java.lang.String</code> in URL format (without the
|
||||
* scheme component) of the form:
|
||||
*
|
||||
* <PRE>
|
||||
* //host:port/name
|
||||
* </PRE>
|
||||
*
|
||||
* <P>where <code>host</code> is the host (remote or local) where the registry
|
||||
* is located, <code>port</code> is the port number on which the registry
|
||||
* accepts calls, and where <code>name</code> is a simple string uninterpreted
|
||||
* by the registry. Both <code>host</code> and <code>port</code> are optional.
|
||||
* If <code>host</code> is omitted, the host defaults to the local host. If
|
||||
* <code>port</code> is omitted, then the port defaults to 1099, the
|
||||
* "well-known" port that RMI's registry, <code>rmiregistry</code>, uses.
|
||||
*
|
||||
* <P><em>Binding</em> a name for a remote object is associating or
|
||||
* registering a name for a remote object that can be used at a later time to
|
||||
* look up that remote object. A remote object can be associated with a name
|
||||
* using the <code>Naming</code> class's <code>bind</code> or
|
||||
* <code>rebind</code> methods.
|
||||
*
|
||||
* <P>Once a remote object is registered (bound) with the RMI registry on the
|
||||
* local host, callers on a remote (or local) host can lookup the remote
|
||||
* object by name, obtain its reference, and then invoke remote methods on the
|
||||
* object. A registry may be shared by all servers running on a host or an
|
||||
* individual server process may create and use its own registry if desired
|
||||
* (see <code>java.rmi.registry.LocateRegistry.createRegistry</code> method
|
||||
* for details).
|
||||
*
|
||||
* @author Ann Wollrath
|
||||
* @author Roger Riggs
|
||||
* @since JDK1.1
|
||||
* @see java.rmi.registry.Registry
|
||||
* @see java.rmi.registry.LocateRegistry
|
||||
* @see java.rmi.registry.LocateRegistry#createRegistry(int)
|
||||
*/
|
||||
public final class TimeoutNaming {
|
||||
/**
|
||||
* Disallow anyone from creating one of these
|
||||
*/
|
||||
private TimeoutNaming() {}
|
||||
|
||||
/**
|
||||
* Returns a reference, a stub, for the remote object associated
|
||||
* with the specified <code>name</code>.
|
||||
*
|
||||
* @param name a name in URL format (without the scheme component)
|
||||
* @return a reference for a remote object
|
||||
* @exception NotBoundException if name is not currently bound
|
||||
* @exception RemoteException if registry could not be contacted
|
||||
* @exception AccessException if this operation is not permitted
|
||||
* @exception MalformedURLException if the name is not an appropriately
|
||||
* formatted URL
|
||||
* @since JDK1.1
|
||||
*/
|
||||
public static Remote lookup(String name)
|
||||
throws NotBoundException,
|
||||
java.net.MalformedURLException,
|
||||
RemoteException
|
||||
{
|
||||
ParsedNamingURL parsed = parseURL(name);
|
||||
Registry registry = getRegistry(parsed);
|
||||
|
||||
if (parsed.name == null)
|
||||
return registry;
|
||||
return registry.lookup(parsed.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the specified <code>name</code> to a remote object.
|
||||
*
|
||||
* @param name a name in URL format (without the scheme component)
|
||||
* @param obj a reference for the remote object (usually a stub)
|
||||
* @exception AlreadyBoundException if name is already bound
|
||||
* @exception MalformedURLException if the name is not an appropriately
|
||||
* formatted URL
|
||||
* @exception RemoteException if registry could not be contacted
|
||||
* @exception AccessException if this operation is not permitted (if
|
||||
* originating from a non-local host, for example)
|
||||
* @since JDK1.1
|
||||
*/
|
||||
public static void bind(String name, Remote obj)
|
||||
throws AlreadyBoundException,
|
||||
java.net.MalformedURLException,
|
||||
RemoteException
|
||||
{
|
||||
ParsedNamingURL parsed = parseURL(name);
|
||||
Registry registry = getRegistry(parsed);
|
||||
|
||||
if (obj == null)
|
||||
throw new NullPointerException("cannot bind to null");
|
||||
|
||||
registry.bind(parsed.name, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the binding for the specified name that is associated
|
||||
* with a remote object.
|
||||
*
|
||||
* @param name a name in URL format (without the scheme component)
|
||||
* @exception NotBoundException if name is not currently bound
|
||||
* @exception MalformedURLException if the name is not an appropriately
|
||||
* formatted URL
|
||||
* @exception RemoteException if registry could not be contacted
|
||||
* @exception AccessException if this operation is not permitted (if
|
||||
* originating from a non-local host, for example)
|
||||
* @since JDK1.1
|
||||
*/
|
||||
public static void unbind(String name)
|
||||
throws RemoteException,
|
||||
NotBoundException,
|
||||
java.net.MalformedURLException
|
||||
{
|
||||
ParsedNamingURL parsed = parseURL(name);
|
||||
Registry registry = getRegistry(parsed);
|
||||
|
||||
registry.unbind(parsed.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebinds the specified name to a new remote object. Any existing
|
||||
* binding for the name is replaced.
|
||||
*
|
||||
* @param name a name in URL format (without the scheme component)
|
||||
* @param obj new remote object to associate with the name
|
||||
* @exception MalformedURLException if the name is not an appropriately
|
||||
* formatted URL
|
||||
* @exception RemoteException if registry could not be contacted
|
||||
* @exception AccessException if this operation is not permitted (if
|
||||
* originating from a non-local host, for example)
|
||||
* @since JDK1.1
|
||||
*/
|
||||
public static void rebind(String name, Remote obj)
|
||||
throws RemoteException, java.net.MalformedURLException
|
||||
{
|
||||
ParsedNamingURL parsed = parseURL(name);
|
||||
Registry registry = getRegistry(parsed);
|
||||
|
||||
if (obj == null)
|
||||
throw new NullPointerException("cannot bind to null");
|
||||
|
||||
registry.rebind(parsed.name, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the names bound in the registry. The names are
|
||||
* URL-formatted (without the scheme component) strings. The array contains
|
||||
* a snapshot of the names present in the registry at the time of the
|
||||
* call.
|
||||
*
|
||||
* @param name a registry name in URL format (without the scheme
|
||||
* component)
|
||||
* @return an array of names (in the appropriate format) bound
|
||||
* in the registry
|
||||
* @exception MalformedURLException if the name is not an appropriately
|
||||
* formatted URL
|
||||
* @exception RemoteException if registry could not be contacted.
|
||||
* @since JDK1.1
|
||||
*/
|
||||
public static String[] list(String name)
|
||||
throws RemoteException, java.net.MalformedURLException
|
||||
{
|
||||
ParsedNamingURL parsed = parseURL(name);
|
||||
Registry registry = getRegistry(parsed);
|
||||
|
||||
String prefix = "";
|
||||
if (parsed.port > 0 || !parsed.host.equals(""))
|
||||
prefix += "//" + parsed.host;
|
||||
if (parsed.port > 0)
|
||||
prefix += ":" + parsed.port;
|
||||
prefix += "/";
|
||||
|
||||
String[] names = registry.list();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = prefix + names[i];
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a registry reference obtained from information in the URL.
|
||||
*
|
||||
* jun's
|
||||
* Timeout RMI Socket Factory 를 추가함
|
||||
*/
|
||||
private static Registry getRegistry(ParsedNamingURL parsed)
|
||||
throws RemoteException
|
||||
{
|
||||
return LocateRegistry.getRegistry(parsed.host, parsed.port, new TimeoutRMISocketFactory(3*1000,10*1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissect Naming URL strings to obtain referenced host, port and
|
||||
* object name.
|
||||
*
|
||||
* @return an object which contains each of the above
|
||||
* components.
|
||||
*
|
||||
* @exception MalformedURLException if given url string is malformed
|
||||
*/
|
||||
private static ParsedNamingURL parseURL(String str)
|
||||
throws MalformedURLException
|
||||
{
|
||||
try {
|
||||
return intParseURL(str);
|
||||
} catch (URISyntaxException ex) {
|
||||
/* With RFC 3986 URI handling, 'rmi://:<port>' and
|
||||
* '//:<port>' forms will result in a URI syntax exception
|
||||
* Convert the authority to a localhost:<port> form
|
||||
*/
|
||||
MalformedURLException mue = new MalformedURLException(
|
||||
"invalid URL String: " + str);
|
||||
mue.initCause(ex);
|
||||
int indexSchemeEnd = str.indexOf(':');
|
||||
int indexAuthorityBegin = str.indexOf("//:");
|
||||
if (indexAuthorityBegin < 0) {
|
||||
throw mue;
|
||||
}
|
||||
if ((indexAuthorityBegin == 0) ||
|
||||
((indexSchemeEnd > 0) &&
|
||||
(indexAuthorityBegin == indexSchemeEnd + 1))) {
|
||||
int indexHostBegin = indexAuthorityBegin + 2;
|
||||
String newStr = str.substring(0, indexHostBegin) +
|
||||
"localhost" +
|
||||
str.substring(indexHostBegin);
|
||||
try {
|
||||
return intParseURL(newStr);
|
||||
} catch (URISyntaxException inte) {
|
||||
throw mue;
|
||||
} catch (MalformedURLException inte) {
|
||||
throw inte;
|
||||
}
|
||||
}
|
||||
throw mue;
|
||||
}
|
||||
}
|
||||
|
||||
private static ParsedNamingURL intParseURL(String str)
|
||||
throws MalformedURLException, URISyntaxException
|
||||
{
|
||||
URI uri = new URI(str);
|
||||
if (uri.isOpaque()) {
|
||||
throw new MalformedURLException(
|
||||
"not a hierarchical URL: " + str);
|
||||
}
|
||||
if (uri.getFragment() != null) {
|
||||
throw new MalformedURLException(
|
||||
"invalid character, '#', in URL name: " + str);
|
||||
} else if (uri.getQuery() != null) {
|
||||
throw new MalformedURLException(
|
||||
"invalid character, '?', in URL name: " + str);
|
||||
} else if (uri.getUserInfo() != null) {
|
||||
throw new MalformedURLException(
|
||||
"invalid character, '@', in URL host: " + str);
|
||||
}
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme != null && !scheme.equals("rmi")) {
|
||||
throw new MalformedURLException("invalid URL scheme: " + str);
|
||||
}
|
||||
|
||||
String name = uri.getPath();
|
||||
if (name != null) {
|
||||
if (name.startsWith("/")) {
|
||||
name = name.substring(1);
|
||||
}
|
||||
if (name.length() == 0) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
|
||||
String host = uri.getHost();
|
||||
if (host == null) {
|
||||
host = "";
|
||||
try {
|
||||
/*
|
||||
* With 2396 URI handling, forms such as 'rmi://host:bar'
|
||||
* or 'rmi://:<port>' are parsed into a registry based
|
||||
* authority. We only want to allow server based naming
|
||||
* authorities.
|
||||
*/
|
||||
uri.parseServerAuthority();
|
||||
} catch (URISyntaxException use) {
|
||||
// Check if the authority is of form ':<port>'
|
||||
String authority = uri.getAuthority();
|
||||
if (authority != null && authority.startsWith(":")) {
|
||||
// Convert the authority to 'localhost:<port>' form
|
||||
authority = "localhost" + authority;
|
||||
try {
|
||||
uri = new URI(null, authority, null, null, null);
|
||||
// Make sure it now parses to a valid server based
|
||||
// naming authority
|
||||
uri.parseServerAuthority();
|
||||
} catch (URISyntaxException use2) {
|
||||
throw new
|
||||
MalformedURLException("invalid authority: " + str);
|
||||
}
|
||||
} else {
|
||||
throw new
|
||||
MalformedURLException("invalid authority: " + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
int port = uri.getPort();
|
||||
if (port == -1) {
|
||||
port = Registry.REGISTRY_PORT;
|
||||
}
|
||||
return new ParsedNamingURL(host, port, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple class to enable multiple URL return values.
|
||||
*/
|
||||
private static class ParsedNamingURL {
|
||||
String host;
|
||||
int port;
|
||||
String name;
|
||||
|
||||
ParsedNamingURL(String host, int port, String name) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright Terracotta, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import net.sf.ehcache.distribution.CacheManagerPeerProvider;
|
||||
import net.sf.ehcache.distribution.RMICacheManagerPeerProvider;
|
||||
import net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory;
|
||||
import net.sf.ehcache.util.PropertyUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* RMICacheManagerPeerProviderFactory 상속받아서
|
||||
* CustomManualRMICacheManagerPeerProvider 로 벼경
|
||||
*
|
||||
*
|
||||
* @author jun's
|
||||
* @version
|
||||
*/
|
||||
public class TimeoutRMICacheManagerPeerProviderFactory extends RMICacheManagerPeerProviderFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TimeoutRMICacheManagerPeerProviderFactory.class.getName());
|
||||
|
||||
private static final String RMI_URLS = "rmiUrls";
|
||||
private static final String URL_DELIMITER = "|";
|
||||
|
||||
/**
|
||||
* peerDiscovery=manual, rmiUrls=//hostname:port/cacheName //hostname:port/cacheName //hostname:port/cacheName
|
||||
*/
|
||||
protected CacheManagerPeerProvider createManuallyConfiguredCachePeerProvider(Properties properties) {
|
||||
String rmiUrls = PropertyUtil.extractAndLogProperty(RMI_URLS, properties);
|
||||
if (rmiUrls == null || rmiUrls.length() == 0) {
|
||||
LOG.info("Starting manual peer provider with empty list of peers. " +
|
||||
"No replication will occur unless peers are added.");
|
||||
rmiUrls = "";
|
||||
}
|
||||
rmiUrls = rmiUrls.trim();
|
||||
StringTokenizer stringTokenizer = new StringTokenizer(rmiUrls, URL_DELIMITER);
|
||||
RMICacheManagerPeerProvider rmiPeerProvider = new TimeoutManualRMICacheManagerPeerProvider();
|
||||
while (stringTokenizer.hasMoreTokens()) {
|
||||
String rmiUrl = stringTokenizer.nextToken();
|
||||
rmiUrl = rmiUrl.trim();
|
||||
rmiPeerProvider.registerPeer(rmiUrl);
|
||||
|
||||
LOG.debug("Registering peer {}", rmiUrl);
|
||||
}
|
||||
return rmiPeerProvider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.eactive.eai.common.session;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.rmi.server.RMISocketFactory;
|
||||
|
||||
/**
|
||||
* 1. 기능 : RMISocketFactory를 상속받아서
|
||||
* connection Timeout 과 read Timeout 을 설정할수 있도록 구현
|
||||
* 2. 처리 개요 :
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
* :
|
||||
*/
|
||||
public class TimeoutRMISocketFactory extends RMISocketFactory
|
||||
{
|
||||
private int connectionTimeout;
|
||||
private int readTimeout;
|
||||
public TimeoutRMISocketFactory(int connectionTimeout,int readTimeout){
|
||||
super();
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.readTimeout =readTimeout;
|
||||
}
|
||||
public Socket createSocket(String host,int port) throws IOException{
|
||||
Socket socket = new Socket();
|
||||
socket.setSoTimeout(this.readTimeout);
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.connect(new InetSocketAddress(host,port), this.connectionTimeout);
|
||||
return socket;
|
||||
}
|
||||
public ServerSocket createServerSocket(int port) throws IOException{
|
||||
return new ServerSocket(port);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user