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

Сценарий:

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

    

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

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

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

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

Есть идеи? Я действительно озадачен этим.

1 ответ

Решение

Итак, этот был просто потрясающим.

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

  • Вы используете 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 шифровать и / или хэшировать все данные сеанса, которые будут сохранены (я не знаю, шифрование это или хэширование, или и то и другое, но это не является важным отличием для этого обсуждения). Это связано с тем, что когда любой рабочий процесс запрашивает данные у службы, используя идентификатор сеанса, он может быть уверен, что данные не были подделаны во время их хранения во внешнем источнике данных.

Если вы находитесь на веб-ферме, то, вероятно, у вас есть статический machineKey определены в вашем web.config файл, и эта проблема не возникает. Но для сценария с одним сервером веб-сада вы, вероятно, полагаетесь на 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 запись существует (на самом деле, она даже не может ее прочитать), генерирует свою собственную и начинает использовать ее для хеширования данных, отправляемых в службу состояний ASP.NET. Он пытается сохранить этот новый ключ компьютера в записи реестра, но молча завершается неудачей. Рабочий процесс B раскручивается, видит, что нет AutoGenKey запись существует, генерирует свою собственную и начинает использовать это для хеширования данных... вы видите, куда это идет.

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

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

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

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


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

Другие вопросы по тегам