diff --git a/Dockerfile b/Dockerfile index 80fb859..0906462 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,13 +27,16 @@ ENV TZ=Asia/Seoul \ -XX:+UnlockExperimentalVMOptions \ -XX:+UseStringDeduplication \ -XX:+HeapDumpOnOutOfMemoryError \ --XX:HeapDumpPath=/tmp \ +-XX:HeapDumpPath=/heapdumps \ +-XX:+ExitOnOutOfMemoryError \ -XX:+DisableExplicitGC \ -javaagent:/opt/opentelemetry-javaagent.jar" # 타임존 설정 RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime +RUN mkdir -p /heapdumps && chown -R 1000:1000 /heapdumps + # OTEL 에이전트 복사 COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar diff --git a/Jenkinsfile b/Jenkinsfile index e513db6..f8b193e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -162,6 +162,10 @@ spec: done fi + if [ "${TARGET_ENV}" = "dev" ]; then + kubectl -n ${APP_NS} patch deploy ${DEPLOY} --type=strategic -p '{"spec":{"template":{"spec":{"containers":[{"name":"'${DEPLOY}'","env":[{"name":"SPRING_PROFILES_ACTIVE","value":"redis-session"}],"volumeMounts":[{"name":"heapdumps","mountPath":"/heapdumps"}]}],"volumes":[{"name":"heapdumps","nfs":{"server":"192.168.0.120","path":"/volume2/NFS/helpdesk-dev/heapdumps"}}]}}}}' + fi + kubectl -n ${APP_NS} set image deploy/${DEPLOY} ${DEPLOY}=${REG}/${IMAGE}:${IMAGE_TAG} if [ "${IS_SESSION_JOB}" = "true" ]; then diff --git a/src/main/java/egovframework/main/web/OptionalSpringSessionFilter.java b/src/main/java/egovframework/main/web/OptionalSpringSessionFilter.java new file mode 100644 index 0000000..6f3a5fd --- /dev/null +++ b/src/main/java/egovframework/main/web/OptionalSpringSessionFilter.java @@ -0,0 +1,89 @@ +package egovframework.main.web; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +public class OptionalSpringSessionFilter implements Filter { + + private static final String PROPERTIES_PATH = "egovframework/egovProps/globals.properties"; + private static final String ENABLED_KEY = "Session.Redis.Enabled"; + private static final String TARGET_BEAN_NAME = "springSessionRepositoryFilter"; + + private ServletContext servletContext; + private boolean enabled; + private volatile Filter delegate; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + this.servletContext = filterConfig.getServletContext(); + this.enabled = Boolean.parseBoolean(loadProperty(ENABLED_KEY, "false")); + if (this.enabled) { + this.servletContext.log("Spring Session Redis filter is enabled."); + } else { + this.servletContext.log("Spring Session Redis filter is disabled."); + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + if (!this.enabled) { + chain.doFilter(request, response); + return; + } + getDelegate().doFilter(request, response, chain); + } + + @Override + public void destroy() { + this.delegate = null; + } + + private Filter getDelegate() throws ServletException { + Filter current = this.delegate; + if (current != null) { + return current; + } + synchronized (this) { + current = this.delegate; + if (current == null) { + WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(this.servletContext); + current = context.getBean(TARGET_BEAN_NAME, Filter.class); + this.delegate = current; + } + return current; + } + } + + private String loadProperty(String key, String defaultValue) { + InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(PROPERTIES_PATH); + if (input == null) { + return defaultValue; + } + try { + Properties properties = new Properties(); + properties.load(input); + return properties.getProperty(key, defaultValue).trim(); + } catch (IOException e) { + this.servletContext.log("Failed to load " + PROPERTIES_PATH + ". Using default for " + key + ".", e); + return defaultValue; + } finally { + try { + input.close(); + } catch (IOException ignored) { + } + } + } +} diff --git a/src/main/resources/egovframework/egovProps/globals-dev.properties b/src/main/resources/egovframework/egovProps/globals-dev.properties index 6a58aeb..b0c9f4f 100644 --- a/src/main/resources/egovframework/egovProps/globals-dev.properties +++ b/src/main/resources/egovframework/egovProps/globals-dev.properties @@ -154,6 +154,7 @@ ldap.username =uid=admin,ou=system ldap.password =secret # Spring Session Redis +Session.Redis.Enabled=true Session.Redis.Host=sayit-helpdesk-session-redis Session.Redis.Port=6379 Session.Redis.Database=0 diff --git a/src/main/resources/egovframework/egovProps/globals-prod.properties b/src/main/resources/egovframework/egovProps/globals-prod.properties index ca2cec8..430bdf1 100644 --- a/src/main/resources/egovframework/egovProps/globals-prod.properties +++ b/src/main/resources/egovframework/egovProps/globals-prod.properties @@ -152,6 +152,7 @@ ldap.username =uid=admin,ou=system ldap.password =secret # Spring Session Redis +Session.Redis.Enabled=true Session.Redis.Host=sayit-helpdesk-session-redis Session.Redis.Port=6379 Session.Redis.Database=0 diff --git a/src/main/resources/egovframework/egovProps/globals-stage.properties b/src/main/resources/egovframework/egovProps/globals-stage.properties index e605343..293d946 100644 --- a/src/main/resources/egovframework/egovProps/globals-stage.properties +++ b/src/main/resources/egovframework/egovProps/globals-stage.properties @@ -147,6 +147,7 @@ ldap.username =uid=admin,ou=system ldap.password =secret # Spring Session Redis +Session.Redis.Enabled=true Session.Redis.Host=sayit-helpdesk-session-redis Session.Redis.Port=6379 Session.Redis.Database=0 diff --git a/src/main/resources/egovframework/egovProps/globals.properties b/src/main/resources/egovframework/egovProps/globals.properties index 4f61ab4..08d1a3e 100644 --- a/src/main/resources/egovframework/egovProps/globals.properties +++ b/src/main/resources/egovframework/egovProps/globals.properties @@ -152,3 +152,6 @@ ldap.url =ldap://localhost:10389 ldap.rootDn =c=kr ldap.username =uid=admin,ou=system ldap.password =secret + +# Spring Session Redis +Session.Redis.Enabled=false diff --git a/src/main/resources/egovframework/spring/com/context-session.xml b/src/main/resources/egovframework/spring/com/context-session.xml index bb11ebc..2d03ee8 100644 --- a/src/main/resources/egovframework/spring/com/context-session.xml +++ b/src/main/resources/egovframework/spring/com/context-session.xml @@ -8,6 +8,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> + + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index cb95042..c9442a4 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -3,7 +3,7 @@ Default springSessionRepositoryFilter - org.springframework.web.filter.DelegatingFilterProxy + egovframework.main.web.OptionalSpringSessionFilter springSessionRepositoryFilter