YARP Docsv2.3
Документация/Трафик и надёжность/Привязка сеансов

Привязка сеансов

Привязка сеансов — это механизм, который привязывает (аффинитизирует) причинно связанную последовательность запросов к

Концепция

Привязка сеансов (session affinity) — это механизм, который привязывает (аффинитизирует) причинно связанную последовательность запросов к тому узлу назначения, который обработал первый запрос, когда нагрузка балансируется между несколькими узлами назначения. Это полезно в сценариях, где большинство запросов в последовательности работают с одними и теми же данными, а стоимость доступа к данным различается для разных узлов (destinations), обрабатывающих запросы. Наиболее распространённый пример — временное кэширование (например, в памяти), когда первый запрос получает данные из более медленного постоянного хранилища в быстрый локальный кэш, а остальные запросы работают только с кэшированными данными, за счёт чего повышается пропускная способность.

Конфигурация

Регистрация служб и промежуточного ПО

Службы привязки сеансов автоматически регистрируются в контейнере DI вызовом AddReverseProxy() . Промежуточное ПО UseSessionAffinity() по умолчанию включено в вызов метода MapReverseProxy без параметров. Если вы настраиваете конвейер прокси самостоятельно, добавьте это промежуточное ПО раньше, чем UseLoadBalancing() .

Пример:

C#   app.MapReverseProxy(proxyPipeline =>
   {
          proxyPipeline.UseSessionAffinity();
          proxyPipeline.UseLoadBalancing();
   });
Note Some session affinity implementations depend on Data Protection, which will require
additional configuration for scenarios like multiple proxy instances. See Key Protection for
details.

Конфигурация кластера

Привязка сеансов настраивается для каждого кластера по следующей схеме конфигурации.

JSON"ReverseProxy": {
   "Clusters": {
      "<cluster-name>": {
         "SessionAffinity": {
             "Enabled": "(true|false)", // defaults to 'false'
             "Policy": "(HashCookie|ArrCookie|Cookie|CustomHeader)", // defaults to
'HashCookie'
             "FailurePolicy": "(Redistribute|Return503Error)", // defaults to
'Redistribute'
             "AffinityKeyName": "Key1",
             "Cookie": {
                "Domain": "localhost",
                "Expiration": "03:00:00",
                "HttpOnly": true,
                "IsEssential": true,
                "MaxAge": "1.00:00:00",
                "Path": "mypath",
                "SameSite": "Strict",
                "SecurePolicy": "Always"
             }
         }
      }
   }
}

Атрибуты для настройки cookie-файла, используемого политиками HashCookie, ArrCookie и Cookie, задаются с помощью SessionAffinityCookieConfig . Эти свойства можно указать в конфигурации JSON, как показано выше, либо в коде, как показано ниже:

C#new ClusterConfig
{
      ClusterId = "cluster1",
      SessionAffinity = new SessionAffinityConfig
      {
             Enabled = true,
             FailurePolicy = "Return503Error",
             Policy = "HashCookie",
             AffinityKeyName = "Key1",
             Cookie = new SessionAffinityCookieConfig
             {
                   Domain = "mydomain",
                   Expiration = TimeSpan.FromHours(3),
                   HttpOnly = true,
                   IsEssential = true,
                   MaxAge = TimeSpan.FromDays(1),
                      Path = "mypath",
                      SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict,
                      SecurePolicy =
Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest
                   }
   }
}

Ключ привязки

Привязка запроса к узлу назначения устанавливается с помощью ключа привязки, идентифицирующего целевой узел назначения. Этот ключ может храниться в разных частях запроса в зависимости от конкретной реализации привязки сеансов, но у каждого запроса не может быть более одного такого ключа. Точная семантика ключа зависит от реализации, но встроенные политики в настоящее время используют в качестве ключа привязки DestinationId.

Текущая архитектура не требует, чтобы ключ однозначно идентифицировал единственный привязанный узел назначения. Допускается устанавливать привязку к группе узлов назначения. В этом случае конкретный узел, который обработает данный запрос, определит балансировщик нагрузки.

Установление новой привязки или разрешение существующей

Когда запрос поступает и маршрутизируется в кластер с включённой привязкой сеансов, прокси автоматически решает, нужно ли установить новую привязку или разрешить существующую, на основании наличия и действительности ключа привязки в запросе:

  1. Запрос не содержит ключа. Разрешение пропускается, и новая привязка устанавливается к узлу назначения, выбранному балансировщиком нагрузки.

  2. Ключ привязки найден в запросе и действителен. Механизм привязки пытается найти все работоспособные узлы назначения, соответствующие этому ключу, и если находит их, передаёт запрос дальше по конвейеру. Если найдено несколько подходящих узлов назначения, для выбора одного целевого узла вызывается балансировщик нагрузки. Если найден только один подходящий узел назначения, балансировщик нагрузки ничего не делает.

  3. Ключ привязки недействителен либо не найдено ни одного работоспособного привязанного узла назначения. Это рассматривается как сбой, который обрабатывается политикой обработки сбоев, описанной ниже.

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

доставлен клиенту, именно клиент отвечает за то, чтобы прикладывать этот ключ ко всем последующим запросам в

рамках того же сеанса. Далее, когда следующий запрос с этим ключом поступает на прокси, он

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

ключ привязки содержится только в первом ответе.

Есть четыре встроенные политики привязки, которые по-разному форматируют и сохраняют ключ в запросах и ответах. Политика по умолчанию — HashCookie .

HashCookie , ArrCookie и Cookie сохраняют ключ в виде cookie-файла — соответственно хэшированного или зашифрованного, см. раздел «Защита ключа» ниже. Ключ запроса передаётся в виде cookie-файла с настроенным именем, и этот же cookie-файл устанавливается заголовком Set-Cookie в первом ответе привязанной последовательности. Имя cookie-файла необходимо явно задать через SessionAffinityConfig.AffinityKeyName . Остальные свойства cookie-файла настраиваются через SessionAffinityCookieConfig . CustomHeader хранит ключ в виде зашифрованного заголовка. Она ожидает, что ключ привязки будет передан в пользовательском заголовке с настроенным именем, и устанавливает тот же заголовок в первом ответе привязанной последовательности. Имя заголовка задаётся через SessionAffinityConfig.AffinityKeyName .

Примечание

Во избежание конфликтов значение AffinityKeyName должно быть уникальным для всех кластеров с включённой привязкой сеансов.

Защита ключа

Политика HashCookie использует хэш-функцию XxHash64, чтобы получить быстрый, компактный и обфусцированный формат значения cookie-файла.

Политика ArrCookie использует хэш-функцию SHA-256, чтобы получить обфусцированное значение cookie-файла в формате, совпадающем с форматом cookie-файла привязки ARR в IIS. ARR использует в качестве входного значения имя узла назначения, поэтому при совместном использовании с ARR идентификаторы узлов назначения YARP нужно настроить соответствующим образом.

HashCookie и ArrCookie не обеспечивают надёжную защиту конфиденциальности, поэтому конфиденциальные данные не следует включать в идентификаторы узлов назначения. Эти политики также не скрывают общее число уникальных узлов назначения за прокси, и их не следует использовать, если это критично.

Политики Cookie и CustomHeader шифруют ключ с помощью Data Protection. Это обеспечивает надёжную защиту ключа, но требует дополнительной настройки при использовании более одного экземпляра прокси.

Политика обработки сбоев привязки

Если ключ привязки не удаётся декодировать или не найдено ни одного работоспособного узла назначения, это считается

сбоем, для обработки которого вызывается политика обработки сбоев привязки. Эта политика имеет полный доступ к

HttpContext и может самостоятельно отправить ответ клиенту. Она возвращает логическое значение, указывающее,

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

Есть две встроенные политики обработки сбоев. Политика по умолчанию — Redistribute .

  1. Redistribute — пытается установить новую привязку к одному из доступных работоспособных узлов назначения, пропуская шаг поиска привязки и передавая все работоспособные узлы назначения балансировщику нагрузки так же, как это делается для запроса без привязки. Обработка запроса продолжается. Реализуется классом RedistributeAffinityFailurePolicy .

  2. Return503Error — отправляет клиенту ответ 503, и обработка запроса прекращается. Реализуется классом Return503ErrorAffinityFailurePolicy

Конвейер обработки запроса

Механизмы привязки сеансов реализуются службами (упомянутыми выше) и двумя следующими компонентами промежуточного ПО:

  1. SessionAffinityMiddleware — координирует процесс разрешения привязки запроса. Сначала вызывается политика, указанная для данного кластера в свойстве ClusterConfig.SessionAffinity.Policy. Затем проверяется статус разрешения привязки, возвращённый политикой, и в случае сбоя вызывается политика обработки сбоев, заданная в ClusterConfig.SessionAffinity.FailurePolicy. Этот компонент должен быть добавлен в конвейер до балансировщика нагрузки.

  2. AffinitizeTransform — устанавливает ключ в ответе, если для запроса была установлена новая привязка. В противном случае, если запрос следует существующей привязке, ничего не делает. Автоматически добавляется в качестве преобразования ответа.

Примечание

Эта статья создана автором при помощи ИИ. Подробнее.

Адаптировано из Microsoft Learn , лицензия CC BY 4.0 .