SpringSession+Redis реализует совместное использование сеансов кластера

Redis Nginx балансировки нагрузки Tomcat

0) Предисловие

После разработки веб-приложения оно развертывается в Tomcat или других контейнерах для доступа пользователей.Для небольших приложений Tomcat устанавливается на сервер, а веб-приложение развертывается.По мере увеличения трафика нагрузка на Tomcat будет увеличиваться до тех пор, пока он не выйдет из строя. Чтобы обеспечить пропускную способность WEB-приложений, необходимо выполнить кластерную обработку WEB-приложений.

С развитием современных технологий балансировка кластера/нагрузки стала относительно простой.Давайте познакомим с этими двумя понятиями студентов, которые только начинают работу, на простом языке:

Когда KFC открылся, было только одно окно заказа (сервер Tocmat, который может сэкономить затраты) для предоставления услуги заказа.Нет проблем с ежедневным заказом, и будет длинная очередь в одном окне (высокий параллелизм) во время еды время или выходные.. Жалобы есть не только у клиентов (долгое время ответа на запрос, плохое взаимодействие с пользователем), но и официант будет очень уставшим, и, наконец, в один прекрасный день он устанет (Tomcat кладет трубку).

В настоящее время сбоку добавляется окно (добавляется сервер Tomcat) для предоставления услуг по размещению заказов, но многие клиенты не знают новое окно, и в исходном окне все еще есть длинные очереди (пользователи по-прежнему имеют доступ к исходному Tomcat). ), затем человек стоит у двери и указывает покупателям, к какому окну заказывать в соответствии с ситуацией в очереди каждого окна (балансировщик нагрузки). Роль этого человека состоит в том, чтобы сделать количество заказов в каждом окне примерно равным, поэтому чтобы избежать того, чтобы некоторые окна были очень заняты, а некоторые очень заняты.Простоя.По мере увеличения количества клиентов окно заказа также будет соответственно увеличиваться (все больше и больше Tomcats).

  • Кластер: группа серверов собирается вместе для предоставления услуг.В приведенном выше примере несколько окон заказов (несколько Tomcats) совместно предоставляют услуги заказа, что является кластером.
  • Балансировка нагрузки. Поддерживайте сбалансированную нагрузку каждого окна заказа (каждого Tomcat) в кластере и не допускайте чрезмерного бездействия одного или нескольких из них.

Эти две концепции появляются одновременно: балансировка нагрузки для службы без кластера (один Tomcat) невозможна, а кластерная служба без балансировки нагрузки будет тратить ресурсы впустую.

Существует множество веб-решений для балансировки нагрузки,Nginx+TomcatЭто одно из наиболее часто используемых решений.Nginx действует как балансировщик нагрузки для разгрузки в соответствии с нагрузкой каждого Tomcat.

  • Каждый Tomcat эквивалентен окну заказа и может предоставлять услуги заказа.
  • Каждый раз, когда вы заказываете еду, вы должны сначала пройти через Nginx
  • Nginx назначит пользователю, в какое окно заказывать еду, в зависимости от доступности каждого окна.
  • Заказ в окне 1 в первый раз, повторный заказ сразу после заказа может быть назначен окну 2.

Давайте создадим веб-приложение для балансировки нагрузки.

1) Создать веб-приложение

Подготовьте веб-приложение, разверните его с двумя Tomcat и верните номер порта Tomcat в качестве результата, чтобы определить, какой Tomcat обрабатывает запрос во время тестирования.

/**
 * 获取部署项目的Tomcat端口号
 */
@RequestMapping("/port/get")
@ResponseBody
public String getPort(HttpServletRequest request) {
    return String.valueOf(request.getLocalPort());
}

В этом примере используйте5677, 5688Два порта развертывают проект./port/getЗапрос возвращает номер порта Tomcat

  • http:// localhost:5677/port/get: возврат 5677
  • http:// localhost:5688/port/get: возврат 5688

2) Nginx настроить балансировку нагрузки

Установка Nginx под Window относительно проста, студенты, которые не знают, как установить Baidu, могут кратко представить файл конфигурации Nginx:nginx.conf

# Nginx进程数
worker_processes  1;
 
events {
    # 最大并发链接数
    worker_connections  1024;
}
 
# Nginx处理HTTP请求相关的配置
# http不能重复, 全局唯一
http {
 
    # 虚拟主机, 可配置多个虚拟主机
    # Nginx监听88,89,90三个端口, 可配置三个server
    server {
        # 端口号, 访问88端口会都按照该server下的配置进行处理
        listen       88;
        # 主机名称
        server_name  localhost;
        # 根据正则表达式匹配URL, 匹配到的URL按照该location下的配置进行处理
        # /代表访问88端口的所有请求
        location / {
            # 静态资源所在根目录, 会从该目录下查找静态资源
            # 例: 访问/a.html, 找到D:/a.html并返回
            root  D:/;
        }
    }
 
}

Самая базовая конфигурация Nginx из приведенного выше файла конфигурации, когда мы посещаемhttp://localhost:88Это будет обрабатываться Nginx.Далее мы настроим балансировку нагрузки Nginx.

  • Настройте двух котов, определенных в 1), вhttpДобавьте следующий код под узел:
# 定义需要进行负载均衡的服务器信息
# upstream为关键字, springsession为自定义的名称
# server为关键字, 代表一个服务或服务(一个tomcat)
# server的内容为服务器的信息, 形式为ip:端口
# weight定义了服务器负载的权重, 每4次请求有3次转发到5688, 1次到5677
upstream springsession { 
    server localhost:5677 weight=1; 
    server localhost:5688 weight=3; 
}
  • Настройте, когда все запросы на доступ к Nginx перенаправляются на два сервера для обработки
location / {
    # root  D:/;
    # 转发至名称为springsession的upstream处理
    proxy_pass http://springsession; 
}

3) Проверка балансировки нагрузки

доступhttp://localhost:88/port/get, Nginx перенаправляет запрос на обработку одному из двух котов, можно обнаружить, что результаты, возвращаемые запросом, отличаются

  • В соответствии с настроенным весом каждые 4 посещения имеют 3 доступа по5688вкл., 1 раз по5677иметь дело с.
  • Конфигурация веса - это только окончательное среднее значение 3/4 и 1/4, не обязательно первые три посещения будут5688иметь дело с.
  • Когда вес не настроен, вероятность того, что два кота будут выделены одновременно, составляет 50% каждый.

Балансировка нагрузки настроена, есть такая проблема:

Когда вы заказываете еду в окне 1, вы временно сохраняете ключ в этом окне, и в следующий раз, когда вы заказываете еду, она может быть назначена окну 2 или другим окнам (она также может быть назначена окну 1), тогда, очевидно, можно получить ключ в других окнах Это не работает.Потому что в других окнах нет вашего ключа.В это время вы можете только молиться,чтобы вас быстро назначили на окно 1.

Если операция по сохранению ключа изменится на сохранение информации в СЕССИИ, то при выполнении вашего запросаTomcat1При обработке,Tomcat1СЕССИЯ будет сгенерирована для вас, вы задаете информацию в СЕССИИ, в следующий раз, когда ваш запрос будет назначенTomcat2иметь дело с,Tomcat2СЕССИЯ будет сгенерирована для вас снова. Это две независимые и не общие СЕССИИ, поэтому вы не можетеTomcat2получить вас вTomcat1информация, хранящаяся в .

Принцип входа в систему фактически заключается в сохранении статуса входа в SESSION.Согласно приведенному выше анализу, вход в службу, развернутую в кластере, будет недействительным.Если вы входите в Tomcat1, при следующем посещении Tomcat2 статус входа полученный SESSION должен быть недействителен. Войдите в систему, вам нужно войти снова. Пользователь сошел с ума, вы с ума сошли, босс будет с ума...


Если есть общее место для хранения вещей, и все окна заказов имеют доступ к вещам клиентов в общем месте, то вышеописанная проблема будет решена.

Вот смысл этой статьи:Унифицированное управление СЕССИЯ каждого WEB-приложения в рамках кластера.

  • выбор контейнера: Нам нужен контейнер, который может хранить SESSION единообразно. Из следующих трех пунктов,RedisНесомненно самый подходящий. СЕССИЯ часто читается, поэтому база данных, файловая система не подходят, лучше всего работать с памятью. СЕССИЯ имеет идентификатор, идентификатор соответствует СЕССИИ, предпочтительно контейнеру K/V. СЕССИЯ чувствительна ко времени (долго не используется и нуждается в удалении) Лучше всего установить время истечения

  • Механизм доступа SESSION: Поскольку SESSION генерируется Tomcat, первое, что приходит на ум, это модифицировать механизм Tomcat SESSION, начиная сRedisЭто принесет проблему. Предположим, что Tocmat обновлен, нам нужно повторно изменить Tomcat. Следовательно, это решение менее осуществимо. Мы можем рассмотреть это, даже если Tomcat генерирует SESSION, мы все еще находимся в веб-приложении. Почему бы не перегенерировать a СЕССИЯ в ВЕБ-приложении, напишите такой фильтр, перед входом в ВЕБ-приложение откажитесь от СЕССИИ Томкэта, отRedisПолучить СЕССИИ в.


Так уж получилось, что есть такая структура, которая поможет нам реализовать вышеуказанную идею, и нам нужно только настроить ее для достижения унифицированного управления SESSION.Spring Session.

чтобыSpring SessionФункция впечатляет, давайте сначала проверим, как наше кластерное приложение обрабатывает SESSION без Spring Session.

Добавьте метод контроллера в наше веб-приложение для балансировки нагрузки, поместите каждыйSESSION IDВыведите его.

/**
  * 获取部署项目的SESSION ID
  */
@RequestMapping("/sessionid/get")
@ResponseBody
public String getPort(HttpServletRequest request, HttpSession session) {
    int port = request.getLocalPort(); // 端口
    String sessionId = request.getSession().getId(); // SESSION ID
 
    return "port: " + port + ", session id: " + sessionId;
}

Начать проект, множественный доступhttp://localhost:88/sessionid/get

  • Оба посещения находятся под одним и тем же TomcatSESSOIN IDпостоянно
  • Два визита под разными TomcatSESSION IDменяется
  • После доступа к другому Tomcat при повторном доступе к тому же TomcatSESSION IDтакже меняется

Причины вышеописанной ситуации следующие:

  1. доступ5677, поскольку СЕССИИ нет,Tomcat5677Создать SESSION, идентификатор1, и воля1Вернуться к клиенту
  2. доступ5677, переносимый браузеромSESSION_ID=1, Tomcat5677Найдите соответствующий SESSION. Таким образом, SESSION_ID равен1
  3. доступ5688, переносимый браузеромSESSION_ID=1, Tomcat5688Не удалось найти соответствующий SESSION, повторно сгенерировать SESSION, идентификатор2, и воля2Вернуться к клиенту
  4. доступ5677, переносимый браузеромSESSION_ID=2, Tomcat5677Не удалось найти соответствующий SESSION, повторно сгенерировать SESSION, идентификатор3, и воля3Вернуться к клиенту
  5. доступ5688, переносимый браузеромSESSION_ID=3, Tomcat5688Не удалось найти соответствующий SESSION, повторно сгенерировать SESSION, идентификатор4, и воля4Вернуться к клиенту

4) Единое управление СЕССИЯ

Давайте использоватьSpring SessionДля управления СЕССИЯ ВЕБ-приложения

1) Установите Redis и включите его

см. статьюhttp://www.cnblogs.com/jaign/articles/7920588.html

2) Добавить зависимости Spring Session

// Spring Session依赖
"org.springframework.session:spring-session-data-redis:2.0.5.RELEASE",
// Redis依赖
"io.lettuce:lettuce-core:5.0.4.RELEASE"

3) Настроить фильтры сеанса Spring

существуетWeb.xmlСредняя конфигурацияSpring SessionПредоставленный фильтр, который в основном отвечает за замену СЕССИИ, сгенерированной Tomcat, на СЕССИЯ, сохраненную в Redis.

<!-- Spring Session过滤器 -->
<!-- 负责在进入WEB应用之前将Tomcat生成的SESSION替换为Redis中的SESSION -->
<filter>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

4) Конфигурация SpringSession/Redis

Добавить в файл конфигурации SpringSpring Sessionнастроить иRedisнастроить

beans {
 
    xmlns context: "http://www.springframework.org/schema/context"
 
    // 启动注解方式
    context.'annotation-config'()
 
    // 配置Spring Session
    // 实际上是配置Web.xml中使用的Spring Session过滤器
    // 将Tomcat的Session替换为Redis中管理的Session
    sessionConfig(RedisHttpSessionConfiguration)
 
    // 配置Redis客户端连接
    // 默认连接本地6379端口
    lettuce(LettuceConnectionFactory)
 
}

5) Тест

Начать проект, множественный доступhttp://localhost:88/sessionid/get, посетить в любом случаеSESSION IDвсе так же.

в то же времяRedisЗапись текущей СЕССИИ также появляется в .

использоватьSpring SessionПроцесс обработки SESSION при доступе к WEB-приложению в рамках кластера:

  1. доступ5677, из-заRedisНет вSESSION, поэтому будет генерироватьсяSESSIONи депозитRedis, идентификатор1, и воля1Вернуться к клиенту
  2. доступ5677, переносимый браузеромSESSION_ID=1, Tomcat5677существуетRedisнайти вSESSION. следовательноSESSION_IDза1
  3. доступ5688, переносимый браузеромSESSION_ID=1, Tomcat5688существуетRedisнайти вSESSION. следовательноSESSION_IDза1
  4. ЧистоRedis, посетить снова5677, из-заRedisне имеет идентификатора в1изSESSION, поэтому он будет перегенерирован, и идентификатор изменится соответственно

5) Пример кода

На данный момент мы реализовали унифицированное управление SESSION, и вы можете найти один и тот же SESSION независимо от того, посещаете ли вы какой-либо TOMCAT.

Когда наше приложение сгруппировано, единое управление SESSION является обязательным. Существует много способов добиться единого управления SESSION. Эта статья — лишь один из них. Цель состоит в том, чтобы позволить учащимся понять важность единого управления SESSION и его основных принципов. .

  • Пример кода адреса:https://github.com/atd681/alldemo
  • Пример названия проекта:atd681-springsession