>  기사  >  Java  >  SpringBoot의 세션 시간 초과 문제의 원인에 대한 자세한 설명

SpringBoot의 세션 시간 초과 문제의 원인에 대한 자세한 설명

巴扎黑
巴扎黑원래의
2018-05-10 13:49:595525검색

이 글은 주로 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.