이 글은 주로 SpringBoot의 Session timeout 원리에 대한 자세한 설명을 소개하는 글인데 편집자가 꽤 좋다고 생각해서 지금 공유하고 참고용으로 올려보겠습니다. 편집자를 따라가서 살펴보자
1: 서문:
최근 결제 백그라운드에서 로그인 후 일정 기간 동안 작업이 없는 경우, 항상 다시 로그인해야 작업이 가능합니다. 이 문제의 원인은 세션 시간이 초과되었기 때문입니다. 코드를 디버깅한 후 세션 시간 초과가 1800초인 것으로 나타났습니다. 즉, 1800초 이내에 작업이 없으면 세션 시간이 초과됩니다. 그렇다면 이 제한 시간은 어떻게 설정됩니까? 그렇다면 이 시간 초과를 어떻게 재설정하나요? 세션 시간이 초과된 시기를 시스템은 어떻게 결정합니까? 다음으로 하나씩 답변해드리겠습니다.
2: 시스템 세션 시간 초과는 기본적으로 어떻게 설정되나요?
설명: 세션 시간 초과를 가져오는 방법은 "request.getSession().getMaxInactiveInterval()"이지만 tomcat에서 시간 초과를 설정하는 매개 변수는 "sessionTimeout"인데 어떻게 연결됩니까?
1단계: sessionTimeout 매개변수를 로드합니다.
1. 프로젝트 작업 초기화는 "@ConfigurationProperties" 주석을 통해 "org.springframework.boot.autoconfigure.web.ServerProperties" 클래스를 로드합니다.
//springBoot中默认的配置文件为"application.yml"或者"application.perties"文件,也就是说server是其中的一个配置参数。 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered { //代码 }
2. 위 클래스의 "ServerProperties"는 "EmbeddedServletContainerCustomizer" 인터페이스에서 상속됩니다. 사용자 정의 메소드를 다시 작성한 다음 이 메소드를 "푸시업"하여 "AbstractConfigurableEmbeddedServletContainer" 클래스를 찾으십시오.
@Override public void customize(ConfigurableEmbeddedServletContainer container) { //多个参数判断,如果在application中没配置的情况下都是null if (getPort() != null) { container.setPort(getPort()); } ...//n多个参数判断, //以下的代码就是重点,因为是tomcat容器,所以以下条件为“真”,经过一系列的查找父类或者实现接口即可找到抽象类“AbstractConfigurableEmbeddedServletContainer” //public class TomcatEmbeddedServletContainerFactory extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware //public abstract class AbstractEmbeddedServletContainerFactory extends AbstractConfigurableEmbeddedServletContainer implements EmbeddedServletContainerFactory if (container instanceof TomcatEmbeddedServletContainerFactory) { getTomcat().customizeTomcat(this, (TomcatEmbeddedServletContainerFactory) container); } //以上代码执行完成之后,实际上已经有对应的session所有的默认参数,之后通过下面方法,将所有参数放入对应的容器中。第3、4步就是设置过程 container.addInitializers(new SessionConfiguringInitializer(this.session)); }
3 "AbstractConfigurableEmbeddedServletContainer" 클래스에서 "timeout time" 관련 설정을 찾을 수 있습니다
//重要代码 //45行 private static final int DEFAULT_SESSION_TIMEOUT = (int) TimeUnit.MINUTES .toSeconds(30); //66行 private int sessionTimeout = DEFAULT_SESSION_TIMEOUT; @Override public void setSessionTimeout(int sessionTimeout) { this.sessionTimeout = sessionTimeout; } //171-188行 @Override public void setSessionTimeout(int sessionTimeout, TimeUnit timeUnit) { Assert.notNull(timeUnit, "TimeUnit must not be null"); this.sessionTimeout = (int) timeUnit.toSeconds(sessionTimeout); } /** * Return the session timeout in seconds. * @return the timeout in seconds */ public int getSessionTimeout() { return this.sessionTimeout; }
4. "Container.addInitializers(new SessionConfiguringInitializer(this.session))"의 2단계를 실행하여 모든 구성을 로드합니다. 매개변수 .
public static class Session { /** * Session timeout in seconds. */ private Integer timeout; public Integer getTimeout() { return this.timeout; } //将session超时时间设置进来 public void setTimeout(Integer sessionTimeout) { this.timeout = sessionTimeout; }
2단계: 위의 시간 초과 기간을 "MaxInactiveInterval" 매개변수에 할당합니다.
참고: 위의 tomcat에 필요한 모든 매개변수가 로드되었으므로 다음에는 tomcat이 실행됩니다. 여기에서는 자세한 내용을 다루지 않고 바로 tomcat 시작 및 매개변수 로딩 설명으로 이동합니다. "TomcatEmbeddedServletContainerFactory" 클래스의 메소드 호출 프로세스는 다음과 같습니다:
getEmbeddedServletContainer--》prepareContext--》configureContext--》configureSession--》getSessionTimeoutInMinutes.
1 tomcat
//以下代码 private void configureSession(Context context) { long sessionTimeout = getSessionTimeoutInMinutes(); context.setSessionTimeout((int) sessionTimeout); Manager manager = context.getManager(); if (manager == null) { manager = new StandardManager(); //此处即为设置相应的参数的位置。之后会调用StandardContext类的setManger(Manager)方法,在setManger中会调用"manager.setContext(this)" context.setManager(manager); } } //计算超时时间为分钟(注意:此处会将之前的1800秒,转换为30分钟)。可以看出最终的时间结果是个整数的分钟类型,也就是说如果设置的超时时间(单位为秒)不是60的倍数,也会最终转换为60的倍数,并且最小超时时间设置的是60秒。 private long getSessionTimeoutInMinutes() { long sessionTimeout = getSessionTimeout(); if (sessionTimeout > 0) { sessionTimeout = Math.max(TimeUnit.SECONDS.toMinutes(sessionTimeout), 1L); } return sessionTimeout; }
2의 세션 구성 매개변수를 설정하려면configureSession을 호출하세요. 마지막으로 MaxInactiveInterval에 SessionTimeout을 할당하세요. 드디어 세션 시간 초과 설정이 완료되었습니다.
//以下代码 @Override public void setContext(Context context) { //省略其余设置代码,直接重新设置Session超时时间,此时又将上面的分钟单位转为秒。此时终于给Sesseion设置了默认超时时间。 if (this.context != null) { setMaxInactiveInterval(this.context.getSessionTimeout() * 60); this.context.addPropertyChangeListener(this); } }
Three: 시간 초과를 맞춤 설정하면 어떻게 되나요?
사실 위의 과정을 보면 "org.springframework.boot.autoconfigure.web.ServerProperties" 클래스에서 해당 Session 매개변수만 찾아 초기화하고 놔두면 어렵지 않다는 것을 알 수 있다. 로드하면 설정이 완료됩니다.
/** * Get the session timeout. * @return the session timeout * @deprecated since 1.3.0 in favor of {@code session.timeout}. */ @Deprecated @DeprecatedConfigurationProperty(replacement = "server.session.timeout") public Integer getSessionTimeout() { return this.session.getTimeout(); }
그러므로 애플리케이션에서 "server.session.timeout"을 구성하면 됩니다. 매개변수 유형은 long 유형이고 단위는 "초"입니다.
4: 실행 중인 프로그램은 세션 시간 초과를 어떻게 결정하나요?
실제로는 매우 간단합니다. 매번 동일한 세션 요청 시간을 이전 요청 시간과 비교하여 두 값의 차이가 MaxInactiveInterval 값보다 크다는 것을 알아내기만 하면 됩니다.
//判断是否超时 @Override public boolean isValid() { //省略多个条件判断 if (maxInactiveInterval > 0) { //判断此session空闲时间是否比maxInactiveInterval大,如果大的情况下,session就超时 int timeIdle = (int) (getIdleTimeInternal() / 1000L); if (timeIdle >= maxInactiveInterval) { expire(true); } } return this.isValid; } //将上次访问时间和当前时间比较,拿到空闲时间值 @Override public long getIdleTimeInternal() { long timeNow = System.currentTimeMillis(); long timeIdle; if (LAST_ACCESS_AT_START) { timeIdle = timeNow - lastAccessedTime; } else { timeIdle = timeNow - thisAccessedTime; } return timeIdle; }
설명:
따라서 세션 시간 초과를 더 길게 유지하려면 애플리케이션 구성 파일에서 "server.session.timeout" 매개변수를 구성할 수 있습니다. 매개변수 단위는 "초"입니다. 60의 정수 배수가 아니라 60의 정수 배수로 변환됩니다(2: 시스템이 2단계의 "1"에서 시간 초과 및 알고리즘을 설정하는 방법 참조). 1분 미만일 경우 60초로 변환됩니다.
확장:
실제로 할당을 위해 EmbeddedServletContainerCustomizer의 사용자 정의 메서드를 직접 재정의할 수도 있습니다.
아아아아위 내용은 SpringBoot의 세션 시간 초과 문제의 원인에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!