Перемещение ViewState со страницы?

Мы стараемся максимально облегчить загрузку страницы. Поскольку ViewState иногда может раздуваться до 100 тыс. Страниц, я бы хотел полностью устранить ее.

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

Тем не менее, несколько предостережений:

  • Мы обслуживаем в среднем 2 миллиона уникальных посетителей в час.
  • Из-за этого, чтение базы данных было серьезной проблемой в производительности, поэтому я не хочу хранить ViewState в базе данных.
  • Мы также находимся за балансировщиком нагрузки, поэтому любое решение должно работать с пользователем, отскакивающим от машины к машине за обратную передачу.

Идеи?

Ответ 1

Как вы обрабатываете состояние сеанса? Существует встроенный "store the viewstate в состоянии состояния сеанса". Если вы сохраняете состояние сеанса в какой-то быстрой, из системы proc, это может быть лучшим вариантом для viewstate.

edit: для этого добавьте следующий код в базовый класс вашей страницы/глобальной страницы

    protected override PageStatePersister PageStatePersister {
        get { return new SessionPageStatePersister(this); }
    }

Также... это далеко не идеальное (или даже хорошее) решение для большого viewstate. Как всегда, максимально уменьшите размер viewstate. Тем не менее SessionPageStatePersister является относительно интеллектуальным и позволяет избежать неограниченного количества просмотров на сеанс, а также избегать хранения только одного состояния просмотра за сеанс.

Ответ 2

Я проверил множество способов удалить нагрузку состояния представления со страницы и между всеми хаками и некоторым программным обеспечением, там единственное, что действительно масштабируемо, это Устройство StrangeLoops As10000. Прозрачный, не нужно менять основное приложение.

Ответ 4

Для меня хорошо работает следующее:

string vsid;

protected override object LoadPageStateFromPersistenceMedium()
{
  Pair vs = base.LoadPageStateFromPersistenceMedium() as Pair;
  vsid = vs.First as string;
  object result = Session[vsid];
  Session.Remove(vsid);
  return result;
}

protected override void SavePageStateToPersistenceMedium(object state)
{
  if (vsid == null)
  {
    vsid = Guid.NewGuid().ToString();
  }
  Session[vsid] = state;
  base.SavePageStateToPersistenceMedium(new Pair(vsid, null));
}

Ответ 5

Вы всегда можете сжимать ViewState, чтобы получить преимущества ViewState без большого раздувания:

public partial class _Default : System.Web.UI.Page {

  protected override object LoadPageStateFromPersistenceMedium() {
    string viewState = Request.Form["__VSTATE"];
    byte[] bytes = Convert.FromBase64String(viewState);
    bytes = Compressor.Decompress(bytes);
    LosFormatter formatter = new LosFormatter();
    return formatter.Deserialize(Convert.ToBase64String(bytes));
  }

  protected override void SavePageStateToPersistenceMedium(object viewState) {
    LosFormatter formatter = new LosFormatter();
    StringWriter writer = new StringWriter();
    formatter.Serialize(writer, viewState);
    string viewStateString = writer.ToString();
    byte[] bytes = Convert.FromBase64String(viewStateString);
    bytes = Compressor.Compress(bytes);
    ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
  }

  // ...

}

using System.IO;
using System.IO.Compression;

public static class Compressor {

  public static byte[] Compress(byte[] data) {
    MemoryStream output = new MemoryStream();
    GZipStream gzip = new GZipStream(output, 
                      CompressionMode.Compress, true);
    gzip.Write(data, 0, data.Length);
    gzip.Close();
    return output.ToArray();
  }

  public static byte[] Decompress(byte[] data) {
    MemoryStream input = new MemoryStream();
    input.Write(data, 0, data.Length);
    input.Position = 0;
    GZipStream gzip = new GZipStream(input, 
                      CompressionMode.Decompress, true);
    MemoryStream output = new MemoryStream();
    byte[] buff = new byte[64];
    int read = -1;
    read = gzip.Read(buff, 0, buff.Length);
    while(read > 0) {
      output.Write(buff, 0, read);
      read = gzip.Read(buff, 0, buff.Length);
    }
    gzip.Close();
    return output.ToArray();
  }
}

Ответ 6

Из-за типичного организационного раздувания, запрос на новое оборудование занимает много времени, и запрашивающее оборудование, которое будет включать полный пересмотр нашей текущей настройки, вероятно, получит некоторое серьезное сопротивление со стороны инженерного отдела.

Мне действительно нужно придумать программное решение, потому что это единственный мир, в котором я контролирую.

Yay for Enterprise: (

Ответ 7

Я пытался найти некоторые из продуктов, которые я исследовал в прошлом, которые работают так же, как StrangeLoops (но на основе программного обеспечения). похоже, что они вышли из бизнеса, единственное, что из моего списка, которое все еще существует, ScaleOut, но они специализированы в состоянии сеанса кэширование.

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

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

Сообщите мне, если вы найдете другое решение на базе программного обеспечения.

Ответ 8

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

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

Ответ 9

О нет, волокита. Ну, это будет высокий порядок заполнения. Вы упомянули здесь, что вы используете государственный сервер для обслуживания своего состояния сеанса. Как у вас есть эта настройка? Может быть, вы тоже можете сделать что-то подобное?

Изменить

Awh @Jonathan, вы отправили, когда я вводил этот ответ. Я думаю, что этот маршрут может быть многообещающим. Одно дело, что это определенно будет интенсивным в памяти.

@Mike Я не думаю, что сохранение его в информации о сеансе будет хорошей идеей из-за интенсивности памяти в представлении, а также сколько раз вы будете необходимо получить доступ к представлению. SessionState обращается гораздо реже, чем к viewstate. Я бы сохранил два отдельных.

Я думаю, что окончательное решение будет хранить ViewState на клиенте, как и, возможно, стоит посмотреть. С Google Gears это возможно сейчас.

Ответ 10

Считаете ли вы, действительно ли вам нужно все это viewstate? Например, если вы заполняете datagrid из базы данных, все данные будут сохранены в viewstate по умолчанию. Однако, если сетка предназначена только для представления данных, вам не нужна форма a и, следовательно, нет viewstate.

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

У вас очень специальный интерфейс, если вам действительно нужно 100K viewstate. Если вы уменьшите viewstate до абсолютно необходимого, он может оказаться самым простым и наиболее масштабируемым, чтобы сохранить viewstate на странице.

Ответ 11

У меня может быть простое решение для вас в другом посте. Это простой класс для включения в ваше приложение и несколько строк кода на самой странице asp.net. Если вы объедините его с распределенной системой кеширования, вы можете сэкономить много теста, так как просмотр будет большим и дорогостоящим. Скорость Microsoft может быть хорошим продуктом для присоединения этого метода. Если вы будете использовать его и сэкономить массу денег, хотя я бы хотел немного упомянуть об этом. Также, если вы не знаете ни о чем, дайте мне знать, и я могу поговорить с вами лично.

Вот ссылка на мой код. текст ссылки

Если вы заинтересованы в масштабировании, то использование токена сеанса как уникального идентификатора или сохранение состояния в сеансе более или менее гарантировано работает в сценарии веб-фермы.

Ответ 12

Храните представление в объекте сеанса и используйте распределенный кеш или государственную службу для хранения сеанса отдельно от наших серверов, таких как скорость Microsoft.

Ответ 13

Я знаю, что это немного устарело, но я пару дней работал на "виртуальном устройстве" с открытым исходным кодом, используя squid и ecap для:

1.) gzip 2.) обрабатывать ssl 3.) заменить viewstate на токен по запросу/ответ 4.) memcache для кэширования объектов

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

Ответ 14

Я писал об этом некоторое время назад - решение находится на http://www.adverseconditionals.com/2008/06/storing-viewstate-in-memcached-ultimate.html

Это позволяет вам изменить поставщика ViewState по вашему выбору, не изменяя каждый из ваших классов страниц, используя специальный PageAdapter. Я сохранил ViewState в memcached. В ретроспективе я думаю, что лучше хранить его в базе данных или на диске - мы очень быстро заполнили memcached. Его решение с очень низким трением.

Ответ 15

Не нужно ничего покупать или продавать, чтобы устранить вздутие животного. Просто нужно расширить HiddenFieldPageStatePersister. 100-200 Кбайт ViewState останется на сервере и отправит вместо него только токен на 62 байт.

Вот подробная статья о том, как это можно сделать:

http://ashishnangla.com/2011/07/21/reducing-size-of-viewstate-in-asp-net-webforms-by-writing-a-custom-viewstate-provider-pagestatepersister-part-12/