Support optional Redis sessions and heap dumps

This commit is contained in:
2026-06-01 13:26:44 +09:00
parent 0707f726b8
commit 4e1d15c574
9 changed files with 106 additions and 2 deletions
+4 -1
View File
@@ -27,13 +27,16 @@ ENV TZ=Asia/Seoul \
-XX:+UnlockExperimentalVMOptions \ -XX:+UnlockExperimentalVMOptions \
-XX:+UseStringDeduplication \ -XX:+UseStringDeduplication \
-XX:+HeapDumpOnOutOfMemoryError \ -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp \ -XX:HeapDumpPath=/heapdumps \
-XX:+ExitOnOutOfMemoryError \
-XX:+DisableExplicitGC \ -XX:+DisableExplicitGC \
-javaagent:/opt/opentelemetry-javaagent.jar" -javaagent:/opt/opentelemetry-javaagent.jar"
# 타임존 설정 # 타임존 설정
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
RUN mkdir -p /heapdumps && chown -R 1000:1000 /heapdumps
# OTEL 에이전트 복사 # OTEL 에이전트 복사
COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar
RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar
Vendored
+4
View File
@@ -162,6 +162,10 @@ spec:
done done
fi 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} kubectl -n ${APP_NS} set image deploy/${DEPLOY} ${DEPLOY}=${REG}/${IMAGE}:${IMAGE_TAG}
if [ "${IS_SESSION_JOB}" = "true" ]; then if [ "${IS_SESSION_JOB}" = "true" ]; then
@@ -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) {
}
}
}
}
@@ -154,6 +154,7 @@ ldap.username =uid=admin,ou=system
ldap.password =secret ldap.password =secret
# Spring Session Redis # Spring Session Redis
Session.Redis.Enabled=true
Session.Redis.Host=sayit-helpdesk-session-redis Session.Redis.Host=sayit-helpdesk-session-redis
Session.Redis.Port=6379 Session.Redis.Port=6379
Session.Redis.Database=0 Session.Redis.Database=0
@@ -152,6 +152,7 @@ ldap.username =uid=admin,ou=system
ldap.password =secret ldap.password =secret
# Spring Session Redis # Spring Session Redis
Session.Redis.Enabled=true
Session.Redis.Host=sayit-helpdesk-session-redis Session.Redis.Host=sayit-helpdesk-session-redis
Session.Redis.Port=6379 Session.Redis.Port=6379
Session.Redis.Database=0 Session.Redis.Database=0
@@ -147,6 +147,7 @@ ldap.username =uid=admin,ou=system
ldap.password =secret ldap.password =secret
# Spring Session Redis # Spring Session Redis
Session.Redis.Enabled=true
Session.Redis.Host=sayit-helpdesk-session-redis Session.Redis.Host=sayit-helpdesk-session-redis
Session.Redis.Port=6379 Session.Redis.Port=6379
Session.Redis.Database=0 Session.Redis.Database=0
@@ -152,3 +152,6 @@ ldap.url =ldap://localhost:10389
ldap.rootDn =c=kr ldap.rootDn =c=kr
ldap.username =uid=admin,ou=system ldap.username =uid=admin,ou=system
ldap.password =secret ldap.password =secret
# Spring Session Redis
Session.Redis.Enabled=false
@@ -8,6 +8,7 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 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"> http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<beans profile="redis-session">
<context:annotation-config/> <context:annotation-config/>
<util:constant id="redisFlushModeOnSave" <util:constant id="redisFlushModeOnSave"
@@ -35,4 +36,5 @@
<property name="cookiePath" value="/"/> <property name="cookiePath" value="/"/>
<property name="useHttpOnlyCookie" value="true"/> <property name="useHttpOnlyCookie" value="true"/>
</bean> </bean>
</beans>
</beans> </beans>
+1 -1
View File
@@ -3,7 +3,7 @@
<display-name>Default</display-name> <display-name>Default</display-name>
<filter> <filter>
<filter-name>springSessionRepositoryFilter</filter-name> <filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <filter-class>egovframework.main.web.OptionalSpringSessionFilter</filter-class>
</filter> </filter>
<filter-mapping> <filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name> <filter-name>springSessionRepositoryFilter</filter-name>