Перемещение 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. Прозрачный, не нужно менять основное приложение.
Ответ 3
Как ранее > , я использовал базу данных для хранения ViewState в прошлом. Хотя это работает для нас, мы не приближаемся к 2 миллионам уникальных посетителей в час.
Я думаю, что аппаратное решение, безусловно, способ пойти, используя StrangeLoop или другой продукт.
Ответ 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/