Изменение идентификатора сеанса в разных экземплярах в Azure (и, вероятно, в веб-ферме)

У меня проблема с проектом Azure с одной WebRole, но с несколькими экземплярами, использующими сеансы без файлов cookie. Приложение не Мне нужно хранилище сеансов, поэтому он не использует какого-либо поставщика хранилища сеансов, но мне нужно отслеживать идентификатор сеанса. Очевидно, SessionID должен быть одинаковым во всех экземплярах WebRole , но он внезапно меняется без объяснения причин. Мы используем SessionID для отслеживания некоторых данных, поэтому это очень важно.

Чтобы воспроизвести проблему:

  1. Создайте Cloud Project .

  2. Добавьте ASP.NET Веб-роль . Код, уже содержащийся в нем, подойдет.

  3. Откройте Default.aspx

  4. Добавьте элемент управления, чтобы увидеть текущий SessionID и кнопку, чтобы вызвать обратную передачу

      

    SessionID должен быть одинаковым для всех экземпляров WebRole , но он внезапно изменяется без объяснения причин. Мы используем SessionID для отслеживания некоторых данных, поэтому это очень важно.

    Чтобы воспроизвести проблему:

    1. Создайте Cloud Project .

    2. Добавьте ASP.NET Веб-роль . Код, уже содержащийся в нем, подойдет.

    3. Откройте Default.aspx

    4. Добавьте элемент управления, чтобы увидеть текущий SessionID и кнопку, чтобы вызвать обратную передачу

        

      SessionID должен быть одинаковым для всех экземпляров WebRole , но он внезапно изменяется без объяснения причин. Мы используем SessionID для отслеживания некоторых данных, поэтому это очень важно.

      Чтобы воспроизвести проблему:

      1. Создайте Cloud Project .

      2. Добавьте ASP.NET Веб-роль . Код, уже содержащийся в нем, подойдет.

      3. Откройте Default.aspx

      4. Добавьте элемент управления, чтобы увидеть текущий SessionID и кнопку, чтобы вызвать обратную передачу

          

      5. Добавьте обработчик события для кнопки, которая немного задерживает ответ:

         protected void Button1_Click (объект-отправитель, EventArgs e)
        {
         System.Threading.Thread.Sleep (150);
        }
        
      6. Открыть Web.Config

      7. Включить сеансы без файлов cookie:

         
      8. Запустите проект и некоторое время нажимайте кнопку «PostBack» , обращая внимание на идентификатор сеанса в адресной строке. Ничего не происходит, идентификатор сеанса всегда один и тот же :). Остановите его.

      9. Откройте ServiceConfiguration.csfg

      10. Включите четыре экземпляра:

         
      11. Убедитесь, что в Web.config есть строка, связанная с машинным ключом, который был автоматически добавлен Visual Studio. (в конце system.web).

      12. Перезапустите проект, быстро и постоянно нажимайте кнопку «Postback» на некоторое время и обратите внимание на идентификатор сеанса в адресной строке. Вы увидите, как SessionID изменится через некоторое время.

      Почему это происходит? Насколько мне известно, если все машины используют machineKey , сеанс между ними должен быть одинаковым. С файлами cookie проблем нет, проблема, по-видимому, возникает только тогда, когда используются сеансы без файлов cookie.

      Я предполагаю, что что-то не так, когда есть несколько экземпляров, когда SessionID генерируется в одном WebRole переходит к другому, отклоняется и восстанавливается. Это не имеет смысла, так как все WebRole имеют одинаковый machineKey .

      Чтобы выяснить проблему и увидеть ее более четко, я создал свой собственный SessionIDManager :

      public class MySessionIDManager : SessionIDManager
      {
          public override string CreateSessionID(HttpContext context)
          {
              if (context.Items.Contains("AspCookielessSession"))
              {
                  String formerSessionID = context.Items["AspCookielessSession"].ToString();
      
                 // if (!String.IsNullOrWhiteSpace(formerSessionID) && formerSessionID != base.CreateSessionID(context))
                     // Debugger.Break();
      
                  return formerSessionID;
              }
              else
              {
                  return base.CreateSessionID(context);
              }
          }
      }
      

      Чтобы использовать его, измените эту строку в WebConfig:

          
      

      Теперь вы можете видеть, что SessionID не меняется, независимо от того, как быстро и как долго ты ударил. Если вы раскомментируете эти две строки, вы увидите, как ASP.NET создает новый идентификатор сеанса, даже если он уже существует.

      Чтобы заставить ASP.NET создать новый сеанс, просто перенаправьте на абсолютный URL-адрес в ваш сайт:

       Response.Redirect(Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath, String.Empty));
      

      Почему это происходит с сеансами без файлов cookie?

      Насколько надежно мое решение в MySessionIDManager ?

      С уважением.

      ОБНОВЛЕНИЕ :

      • I ' Машинные ключи, определяемые пользователем Заменено автоматической установкой на уровне сайта Конфигурация , но проблема все еще остается.

         public override bool OnStart ()
        {
         // Для информации по обработке изменений конфигурации
         // см. тему MSDN по адресу http://go.microsoft.com/fwlink/?LinkId=166357.
        
         используя (var server = new ServerManager ())
         {
         пытаться
         {
         // получаем веб-конфигурацию сайта
        var siteNameFromServiceModel = "Интернет"; // обновить название этого сайта для вашего сайта.
         var siteName =
         string.Format ("{0} _ {1}", RoleEnvironment.CurrentRoleInstance.Id, siteNameFromServiceModel);
         var siteConfig = server.Sites [имя сайта] .GetWebConfiguration ();
        
         // получаем раздел appSettings
         var appSettings = siteConfig.GetSection ("appSettings"). GetCollection ()
         .ToDictionary (e => (строка) e ["ключ"], e => (строка) e ["значение"]);
        
         // перенастраиваем машинный ключ
         var machineKeySection = siteConfig.GetSection ("system.web / machineKey");
         machineKeySection.SetAttributeValue ("ключ проверки", appSettings ["ключ проверки"]);
         machineKeySection.SetAttributeValue («проверка», appSettings [«проверка»]);
         machineKeySection.SetAttributeValue ("decryptionKey", appSettings ["decryptionKey"]);
         machineKeySection.SetAttributeValue («расшифровка», appSettings [«расшифровка»]);
        
         server.CommitChanges ();
         _init = true;
         }
         улов
         {
         }
         }
         вернуть base.OnStart ();
        }
        
      • Я тоже пробовал поставить обработчик начала сеанса и добавьте некоторые данные, но не повезло.

         void Session_Start (отправитель объекта, EventArgs e)
        {
         Session.Add ("dummyObject", "dummy");
        }
        

      Баунти!

6
задан vtortola 28 February 2011 в 18:18
поделиться