Когда именно истек срок действия HttpSession (начинает иметь право на уничтожение - еще не обязательно уничтожено)?

Я хотел бы знать, когда точно HttpSession будет истекать (не то же самое, что уничтожено)?

Я пытаюсь выяснить, даст ли session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) точное время истечения сеанса в миллисекундах каждый раз, когда приходит запрос с одним и тем же идентификатором сеанса!

Из javadocs:

длинный getLastAccessedTime()

  Returns the last time the client sent a request associated with this session, as the number of milliseconds since midnight January 1, 1970 GMT, and marked by the time the container received the request.    

интервал getMaxInactiveInterval()

  Returns the maximum time interval, in seconds, that the servlet container will keep this session open between client accesses.  

Допустим, у нас есть следующее:
Treq1 — the time the container received the 1st request (HttpSession.lastAccessedTime)
Tresp1 — the time the container sends the 1st response
Preq1 — the time period between Treq1 and Tresp1 (the time period that the server processes the 1st request
Treq2 — the time the container received the 2nd request (HttpSession.lastAccessedTime)
Preq1req2 — the time period between Treq1 and Treq2 (the time between requests entering the container)
Presp1req2 - the time period between Tresp1 and Treq2 (the time between the 1st response exiting the container and the 2nd request entering the container)

Итак, когда сервер считает сеанс просроченным? Когда:
1. Treq1 + maxInactiveInterval ‹ Treq1 + Preq1req2 => maxInactiveInterval ‹ Preq1req2
2 . Tresp1 + maxInactiveInterval ‹ Tresp1 + Presp1req2 => maxInactiveInterval ‹ Presp1req2

Эта часть, the servlet container will keep this session open between client accesses, немного сбивает с толку. Имеется ли в виду между запросами, поступающими в контейнер, или между исходящим ответом и входящими запросами?

Кроме того, я знаю, что сеанс может быть не уничтожен в точное время истечения срока действия, но пока не уверен, что он уничтожается до того, как в контейнере произойдет какая-либо логика обработки запроса. Я имею в виду запрос, который содержит идентификатор сеанса с истекшим сроком действия.

С уважением,
Деспот


person despot    schedule 04.01.2013    source источник
comment
Почему это имеет значение? Время запроса обычно составляет несколько миллисекунд. Время ожидания сеанса обычно составляет 30 минут. Какая разница, 30.000 или 30.002? Какова ваша конечная цель? В любом случае, ответ содержится в вопросе: и отмечен временем получения контейнером запроса   -  person JB Nizet    schedule 04.01.2013
comment
Это имеет значение, так как я хочу знать у клиента, во сколько именно истечет сессия. ответ находится в вопросе: и отмечен временем, когда контейнер получил запрос, это может относиться только к lastAccessedTime. Вы уверены, что время истечения срока действия будет равно session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) (1. case)? Есть ли какой-то источник, который мог бы это подтвердить? Спасибо за комментарий!   -  person despot    schedule 04.01.2013
comment
И вы хотите, чтобы это было с точностью до миллисекунды? Конечного пользователя волнует, через 30 минут или через 30 минут и 8 миллисекунд? В любом случае сеанс не будет уничтожен в это время, поскольку контейнер обычно использует фоновый поток, который уничтожает сеансы с истекшим сроком действия каждую минуту или около того.   -  person JB Nizet    schedule 04.01.2013
comment
Во-первых, обработка на сервере могла занять более 8 миллисекунд, а во-вторых, мне нужно убедиться, что я не отправляю запрос в некую конечную точку с просроченной сессией (а я хочу максимально увеличить время отправки запросов на эту конечная точка). сеанс не будет уничтожен в то время, как я это понимаю (см. часть «Примечание»). Это не отвечает на вопрос о времени истечения срока действия сервера (не уничтожая время). Я хочу сначала понять, как именно сервер рассчитывает время истечения срока действия.   -  person despot    schedule 04.01.2013
comment
Способ убедиться, что вы не отправляете запрос в сеанс с истекшим временем ожидания, заключается в том, чтобы отправить его и обработать возникшие ошибки. Что вы должны сделать в любом случае. Любой прогностический подход рано или поздно обречен на провал и в действительности представляет собой не что иное, как гадание.   -  person user207421    schedule 04.01.2013
comment
... и обрабатывать возникающие ошибки. Я делаю это. Но логика на стороне клиента диктует, что ему необходимо знать, истек ли срок действия сеанса на сервере (или, другими словами, в какой момент его можно будет уничтожить). Короче говоря, я отправляю запрос на endpoint1, получая JSESSIONID с датой истечения срока действия; отправка запросов в endpoint2 до истечения срока действия JSESSIONID. Мне просто нужно убедиться, что срок действия файлов cookie, которые я отправляю в endpoint2, еще не истек. Я имею дело с ошибками, но мне нужно быть уверенным, как сервер вычисляет время истечения срока действия.   -  person despot    schedule 04.01.2013


Ответы (3)


Механизм сеанса является частью спецификации сервлета, которая предписывает:

В протоколе HTTP нет явного сигнала завершения, когда клиент больше не активен. Это означает, что единственный механизм, который можно использовать для индикации того, что клиент больше не активен, — это период ожидания.

Период ожидания по умолчанию для сеансов определяется контейнером сервлета и может быть получен с помощью метода getMaxInactiveInterval интерфейса HttpSession. Это время ожидания может быть изменено разработчиком с помощью метода setMaxInactiveInterval интерфейса HttpSession. Периоды ожидания, используемые этими методами, определяются в секундах. По определению, если период времени ожидания для сеанса установлен на -1, срок действия сеанса никогда не истечет. Аннулирование сеанса не вступит в силу, пока все сервлеты, использующие этот сеанс, не выйдут из метода службы. После инициирования аннулирования сеанса новый запрос не должен иметь возможности видеть этот сеанс.

Метод getLastAccessedTime интерфейса HttpSession позволяет сервлету определить время последнего обращения к сеансу перед текущим запросом. Сеанс считается доступным, когда запрос, являющийся частью сеанса, впервые обрабатывается контейнером сервлета.

Вероятно, можно с уверенностью предположить, что «интервал неактивности» начинается с «lastAccessedTime».

person meriton    schedule 04.01.2013
comment
хорошо, поэтому время истечения сеанса должно быть рассчитано с помощью session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000), и случай 1. правильный?! - person despot; 08.01.2013
comment
Я собираюсь предположить вышеизложенное. - person despot; 09.01.2013
comment
Поскольку последняя часть цитирования содержит ..., определите время последнего доступа к сеансу перед текущим запросом. означает для меня, что на этот раз это не текущий запрос, а запрос до этого. Таким образом, чтобы определить время окончания сеанса, вы должны добавить текущее время в начале запроса к maxInactiveInterval, как в ответе @Subin. - person cyberbrain; 02.03.2017

Я пытаюсь выяснить, даст ли session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) точное время в миллисекундах истечения сеанса каждый раз, когда приходит запрос с одним и тем же идентификатором сеанса!

поскольку вы можете получить доступ к объекту сеанса только в потоке запросов, я предполагаю, что у вас есть приведенный выше код в сервлете для информирования клиента (браузера), сколько времени он может занять до своего следующего щелчка, может быть счетчик тайм-аута.

Я предполагаю, что System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000) будет более точным в этом случае.

person Subin Sebastian    schedule 04.01.2013
comment
для точного информирования клиента (браузера). Я предполагаю, что System.currentTimeMillis() + (session.getMaxInactiveInterval() * 1000), поэтому вы предполагаете, что это 2. случай?! Любой источник, чтобы мы могли быть уверены в этом? Спасибо за Ваш ответ! - person despot; 04.01.2013
comment
если вы хотите отобразить его в удобочитаемом формате, вы можете использовать: SimpleDateFormat sdf = new SimpleDateFormat(yyyy-MM-dd HH:mm:ss.SSS); Дата resultdate = новая дата (timeInMs); System.out.println(Дата в HRF: + sdf.format(resultdate)); - person Enrique San Martín; 08.11.2017

источник?

Я дважды отслеживал запросы, используя "org.springframework.boot:spring-boot-starter-web:1.5.6.RELEASE" spring и заключил:

В вашем обработчике службы (методы doGet, doXX или Controller) время истечения срока действия будет session.getLastAccessedTime() + (session.getMaxInactiveInterval() * 1000) (2. case)

Duration:        |<---------- Preq1req2 ---------->|
Duration:        |           |<---- Presp1req2 --->|
Time    :      Treq1       Tresp1                Treq2      Tresp2
Action  : req1-->|--service--|-->resp1 ...  req2-->|--service--|-->resp2
Duration:        |<- Preq1 ->|                     |<- Preq2 ->|
                 |           |                                 | 
Set :       creationTime     |                                 |   
          lastAccessedTime   |                                 |            
                      lastAccessedTime                  lastAccessedTime

Когда lastAccessedTime обновляется после службы: После службы HTTP

Фрагмент кода из C:/Users/ssfang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.16/tomcat-embed-core-8.5.16-sources.jar

package org.apache.catalina.session;
public class StandardSession implements HttpSession, Session, Serializable {
    /** The time this session was created, in milliseconds since midnight, January 1, 1970 GMT. */
    protected long creationTime = 0L;

    /**
     * We are currently processing a session expiration, so bypass
     * certain IllegalStateException tests.  NOTE:  This value is not
     * included in the serialized version of this object.
     */
    protected transient volatile boolean expiring = false;

    /** The last accessed time for this Session. */
    protected volatile long lastAccessedTime = creationTime;

    /** The session event listeners for this Session. */
    protected transient ArrayList<SessionListener> listeners = new ArrayList<>();

    /** Flag indicating whether this session is valid or not. */
    protected volatile boolean isValid = false;

    /** The current accessed time for this session. */
    protected volatile long thisAccessedTime = creationTime;


    /** The access count for this session. */
    protected transient AtomicInteger accessCount = null;

    /**
     * The maximum time interval, in seconds, between client requests before the servlet container may
     * invalidate this session.  A negative time indicates that the session should never time out.
     */
    protected volatile int maxInactiveInterval = -1;

    /**
     * Return the idle time from last client access time without invalidation check
     * @see #getIdleTime()
     */
    @Override
    public long getIdleTimeInternal() {
        long timeNow = System.currentTimeMillis();
        long timeIdle;
        if (LAST_ACCESS_AT_START) {
            timeIdle = timeNow - lastAccessedTime;
        } else {
            timeIdle = timeNow - thisAccessedTime;
        }
        return timeIdle;
    }

    /**
     * Set the creation time for this session.  This method is called by the
     * Manager when an existing Session instance is reused.
     *
     * @param time The new creation time
     */
    @Override
    public void setCreationTime(long time) {
        this.creationTime = time;
        this.lastAccessedTime = time;
        this.thisAccessedTime = time;
    }

    /** Return the <code>isValid</code> flag for this session. */
    @Override
    public boolean isValid() {
        if (!this.isValid) {
            return false;
        }
        if (this.expiring) {
            return true;
        }
        if (ACTIVITY_CHECK && accessCount.get() > 0) {
            return true;
        }
        if (maxInactiveInterval > 0) {
            int timeIdle = (int) (getIdleTimeInternal() / 1000L);
            if (timeIdle >= maxInactiveInterval) {
                expire(true);
            }
        }
        return this.isValid;
    }
}

Проверьте, действителен ли сеанс, прежде чем получить сеанс

Проверьте, действителен ли сеанс перед получением сеанса

Фоновый поток для сканирования всех сеансов на предмет их истечения.

фоновый поток для сканирования сеансов

person samm    schedule 15.11.2017