Обновление с .NET 3.0 до 3.5: сайты, для которых установлен StateServer, возвращаются к InProc в веб-саду - PullRequest
5 голосов
/ 09 февраля 2009

Сценарий:

Возьмем сервер, на котором работает .NET 3.0, и веб-сайт ASP.NET, работающий в пуле приложений с включенными веб-садами (количество процессов: 3). Конфигурация web.config выглядит следующим образом:

    <sessionState
      cookieless="UseCookies"
      cookieName=".authz"
      mode="StateServer"
      regenerateExpiredSessionId="true"
      stateConnectionString="tcpip=127.0.0.1:42424"
      timeout="60"
      useHostingIdentity="true" />

Теперь обновите машину до .NET 3.5 SP1. Перезагрузите сервер. Результат: сеансы больше не поддерживаются между экземплярами w3wp.exe, как если бы все они вернулись в InProc. Текущее решение - сокращение до 1 рабочего процесса.

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

Сравнение двух machine.configs и web.configs двух серверов: идентично.

Кто-то еще сталкивался с этой проблемой , но ответа там нет.

Есть идеи? Я на самом деле в тупик.

1 Ответ

11 голосов
/ 09 февраля 2009

Итак, этот был просто восхитителен.

Проблема возникает, когда выполняются все следующие условия:

  • Вы используете Windows Server 2003 (IIS 6.0) и веб-сайт ASP.NET 2.0.
  • Веб-сайт настроен на использование веб-садов, где максимальное количество рабочих процессов превышает 1. Из-за этого вы настроили свое приложение на использование хранилища сеансов вне процесса; в этом случае служба состояний ASP.NET работает на локальном компьютере.
  • Идентификатор пула приложений установлен не для NETWORK SERVICE, а для настраиваемой учетной записи пользователя с низким уровнем привилегий, которую вы создали в соответствии с рекомендациями по развертыванию .
  • Вы запускаете установщик, который обновляет .NET Framework; в моем случае это было обновление с .NET 3.0 до .NET 3.5 SP1.

Когда обновление завершается и вы перезагружаете сервер, вы обнаруживаете, что переменные сеанса часто теряются при обновлении страницы, поскольку есть только 1 из 3 шансов получить исходный рабочий процесс, который обработал ваш первоначальный запрос. Но это не должно иметь значения, так как вы используете службу состояний ASP.NET. Что сломалось?

При использовании службы состояний ASP.NET ASP.NET использует значение, называемое machineKey, для шифрования и / или хеширования всех данных сеанса, которые должны быть сохранены (я не знаю, шифрование это или хеширование, или и то и другое, но это не важное различие для этой дискуссии). Это связано с тем, что когда любой рабочий процесс запрашивает данные у службы, используя идентификатор сеанса, он может быть уверен, что данные не были подделаны во время их хранения во внешнем источнике данных.

Если вы находитесь в веб-ферме, возможно, в вашем файле web.config определен статический machineKey, и эта проблема не возникает. Но для сценария с односерверным веб-садом вы, вероятно, полагаетесь на параметр по умолчанию machineKey, который установлен на AutoGenerate,IsolateApps для приложений ASP.NET 2.0. Это означает, что ASP.NET автоматически генерирует машинный ключ, который является уникальным для вашего пула приложений. Он восстанавливает этот ключ согласно некоторому алгоритму, но это не важно для этого обсуждения.

Сгенерированное значение обычно хранится в реестре в HKLM\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0\AutoGenKeys\{SID of the Application Pool Identity}. Но установщик .NET Framework неправильно (я считаю, что это ошибка) уничтожает этот раздел реестра и, чтобы добавить оскорбление травмы, сбрасывает разрешения для этого ключа, так что ваша личная учетная запись пула приложений не может записать в запись реестра, когда он идет создать свой новый машинный ключ.

Результатом является то, что каждый рабочий процесс, который запускается в веб-саду, использует свою собственную копию в памяти ключа компьютера, сгенерированную им вовремя, что эффективно создает сценарий веб-фермы случайно. Например, рабочий процесс A раскручивается, видит, что запись AutoGenKey не существует (действительно, он даже не может прочитать it), генерирует свою собственную и начинает использовать ее для хеширования данных, отправляемых в состояние ASP.NET. Обслуживание. Он пытается сохранить этот новый ключ компьютера в записи реестра, но молча завершается неудачей. Рабочий процесс B раскручивается, видит, что запись AutoGenKey не существует, генерирует свою собственную запись и начинает использовать , что , для хеширования данных ... вы видите, куда это идет.

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

Вы можете обойти это, явно указав пользовательский machineKey в своем файле web.config.

Или вы можете перезапустить aspnet_regiis.exe -ga MachineName\ApplicationPoolUserName в командной строке, чтобы исправить нарушенные разрешения.

Ваша проблема решена. Время ложиться спать.

<ч />

ОБНОВЛЕНИЕ 30 июня: Согласно моему сообщению об этой проблеме на Microsoft Connect , Microsoft указала, что они установили установщик так, что это поведение не произойдет, начиная с обновлений до .NET 4. Это может произойти для всех будущих обновлений 3.0 / 3.5, поэтому я оставлю этот вопрос / ответ без ответа.

...