package com.eactive.eai.common.session; import com.eactive.eai.authserver.service.BearerTokenInfo; 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 CAGATEWAY_TOKEN_CACHE_NAME = "CAGatewayToken"; 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); //CA Token Cache public abstract BearerTokenInfo getCAToken(String key); public abstract void putCAToken(String key, BearerTokenInfo value); public abstract void removeCAToken(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(); }