- Вопрос
- Я занимаюсь разработкой сайтов на платформе ASP.NET и мне нужно измерить производительность страниц. Если я добавлю счетчики, это ухудшит производительность? А отслеживание их показателей? Я читал, что это замедляет приложение.
- Ответ
- ASP.NET и Microsoft .NET Framework передают информацию счетчикам независимо от того, считываете вы ее или нет. Однако процесс чтения данных нагружает процессор, требует дополнительного переключения контекста и т. д. В большинстве промышленных систем за счетчиками ведется наблюдение, так что это можно считать частью производственной среды, которую вам все равно нужно контролировать.
- Альтернатива — использовать средство, измеряющее TTLB (число миллисекунд, прошедших до получения последнего байта ответа) на клиентской стороне. Его можно комбинировать со средствами мониторинга на серверной стороне, чтобы оценить, какая часть задержки вносится сервером, а какая — сетью.
- Более подробные сведения см. в статьях «Analyze ASP.NET Web Application Performance by Using the Performance Administration Tool» (support.microsoft.com/kb/815159) и «Measuring .NET Application Performance» (msdn.microsoft.com/library/en-us/dnpag/html/scalenetchapt15.asp).
- Вопрос
- Я создаю систему, которая предоставляет Web-сервис без поддержки состояний для интеграции с партнерами. В целом, каждый партнер обращается к сервису раз в день, а сервис пересылает запрос серверу для обработки. Обработка запроса занимает длительное время, а системе партнера требуется определять, успешно ли прошла обработка. Как этого добиться?
- Ответ
- Иногда кажется, что самый простой способ — сделать вызов синхронным. Но тогда возникает вопрос, нормален ли для Web-сервиса перебой в приеме других запросов на один или два часа?
- Вы могли бы сразу возвращать код успешного выполнения, предоставив партнеру возможность запросить настоящий результат позже (на основе какого-либо контекстного маркера, присвоенного запросу). Кроме того, партнер мог бы реализовать обратный вызов.
- На самом деле два последних варианта лучше, чем увеличение таймаута. Так как операция выполняется лишь раз в сутки, это уже своего рода пакетный вызов. Такие вещи лучше обрабатывать асинхронно. Если партнер не может реализовать механизм уведомлений (второй вариант), уместно возвращать некий идентификатор задачи в контекстном маркере. Если партнер собирается периодически запрашивать результат, имеет смысл поместить в маркер интервал опроса, исходя из текущей нагрузки на систему.
- Вопрос
- У меня на Web-форме размещен DataGrid, поддерживающий редактирование и сортировку. Если после сортировки столбца щелкнуть кнопку Edit, выбираются строки в исходном порядке сортировки. Как это исправить?Код обработчика Page_Load выглядит так:
private void Page_Load(object sender, System.EventArgs e)
{
PubAdapter.Fill(publisherDataSet1);
if (!IsPostBack)
{
MyGrid.DataSource =
publisherDataSet1.publishers.DefaultView;
MyGrid.DataBind();
}
}
Код сортировки таков:
private void MyGrid_SortCommand(object source,
System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
DataView SortView =
publisherDataSet1.publishers.DefaultView;
SortView.Sort = e.SortExpression;
MyGrid.DataSource = SortView;
MyGrid.DataKeyField = «pub_id»;
MyGrid.DataBind();
}
Наконец, следующий код реализует редактирование:
private void MyGrid_EditCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
MyGrid.DataSource =
publisherDataSet1.publishers.DefaultView;
MyGrid.DataKeyField = «pub_id»;
MyGrid.EditItemIndex = e.Item.ItemIndex;
MyGrid.DataBind();
}
- Ответ
- Единственное место, где вы настраиваете сортировку DataView, — событие sort. А значит, когда пользователь выполнит следующую отправку данных, DataView снова будет заполнен данными из хранилища, и после вызова DataBind сортировка пропадает, так как произойдет связывание с несортированными данными. Так что вам самому придется поддерживать сортировку в DataView. Для этого надо все время сортировать DataView. Обратите внимание: если данных мало, удобнее применять состояние отображения для хранения отсортированных данных вместо Session, так как оно работает в Web-формах без сервера состояний и в случаях, когда состояние сессии отключено. Но не забудьте, сортировка данных в ViewState может представлять угрозу безопасности, так как оно не шифруется, а просто кодируется. Так что кто-нибудь может подсмотреть контент (хотя и не сможет его подменить).
- Создать правильно вызываемый SortExpression можно так:
private string SortExpression {
get {
object o = ViewState[«SortExpression»];
return o == null ? «» : (string)o;
}
set {
ViewState[«SortExpression»] = value;
}
}
Затем создайте вспомогательный метод, выполняющий связывание с данными (рис. 1).
- Вопрос
- Мое ASP.NET-приложение соединяется с OLAP-кубом на другом компьютере. Если пользователь зарегистрировался на Web-сервере (локально или через терминал), соединение проходит успешно. В противном случае соединение установить не удается несмотря на то, что в коде пользователь подменяется до установки соединения. Все работало замечательно, пока база данных и кубы находились на одном компьютере с IIS. Что здесь не так?
- Ответ
- Это обычная проблема соединения из трех звеньев. Нельзя просто перепрыгнуть с одного компьютера на другой, притворившись другим пользователем. Используйте делегирование Kerberos или на время прекращайте подмену (восстанавливая идентификацию процесса при условии, что у него есть нужные разрешения), устанавливайте соединение и вновь возвращайте подмену (олицетворение). Иначе придется входить на Web-сервер как другой пользователь и устанавливать соединение.
- Так что у вас есть следующие варианты.
- Применять делегирование Kerberos.
- Не подменять пользователя и соединиться с удаленным ресурсом от имени рабочего процесса.
- Вызвать LogonUser, передать учетные данные пользователя с разрешениями на доступ к удаленному ресурсу, а затем выполнить подмену, используя полученный маркер.
Хороший ресурс по данной тематике — Web-передача в MSDN «Getting Delegation to Work with IIS and ASP.NET: The Ins and Outs of Protocol Transition» по ссылке msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032267262&EventCategory=5.
- Вопрос
- Мои Web-методы периодически исчезают со страницы описания Web-сервиса с ошибкой «Server did not recognize the value of HTTP Header SOAPAction» («серверу не удалось распознать значение HTTP-заголовка SOAPAction»). Это происходит и с неактивным приложением. Что делать?
- Ответ
- Проверьте, не используется ли в Web-сервисе в других зависимых ссылках или каталогах in одинаковые пространство имен и класс. Если используется, класс-дубликат может загружаться раньше настоящего класса Web-сервиса и Web-методы становятся недоступны.
- Следует проверить, нет ли в зависимой сборке класса с таким же именем. Это может случится, когда проект Web-сервиса ссылается на зависимую вспомогательную сборку, в свою очередь ссылающуюся обратно на Web-сервис, — в итоге она получает прокси-класс для Web-сервиса, созданного с тем же именем, но другим пространством имен («localhost»). Тогда, если изменить пространство имен на совпадающее с пространством имен класса — потомка Web-сервиса, возникнет конфликт. Если проекты компилируются раздельно, этот конфликт останется незамеченным на этапе компиляции, но, поскольку они оба загружаются в AppDomain (как и все сборки в каталоге in), а файл .asmx просто содержит имя файла, возникнут проблемы при использовании прокси-объекта.
- Вопрос
- Я пытаюсь обратиться к листу Excel через OLE DB. Мне удается отображать данные листа в GridView, но обновление данных и вставка не срабатывают. Я всегда получаю сообщение об ошибке «Operation must use an updateable query» («для операции необходим обновляемый запрос»). Проблема в Excel?
- Ответ
- При попытке сделать это с Web-сайта у вас будут серьезные проблемы. При открытии листа через OLE DB появляется монопольная блокировка, так что все равно одновременно записывать данные сможет только один пользователь. Кроме того, необходимо отключить пул, так как пул пытается оставлять соединение открытым, что тоже вызывает проблемы, связанные с монопольной блокировкой. Excel — это не многопользовательская база данных.
- Лучше по возможности переключиться на SQL Server, предлагающий гораздо больше возможностей. Но в любом случае попробуйте код, приведенный на рис. 2. Он поможет, если вы все равно хотите работать с Excel. Обратите внимание, что открытие файла book1.xls в Excel тоже монопольно заблокирует файл, нарушив работу кода, — Excel одновременно позволяет работать только одному пользователю.
- Вопрос
- У меня есть DLL, не выгружаемая при создании объекта методами JavaScript и ActiveX. Установка объекта в NULL не вызывает выгрузку класса. Почему она выгружается, только когда я закрываю Microsoft Internet Explorer?
- Ответ
- Что стало бы с миром, если бы COM на самом деле загружал и выгружал компоненты так, как вам хочется?
for (x = 1; x < 1000 ; ++x){ var wuwebObj = new ActiveXObject( «SoftwareDistribution.WebControl»); wuwebObj = null;}
Этот код мог бы загрузить и выгрузить DLL тысячу раз. Агрессивная выгрузка — кошмар с точки зрения производительности, и именно поэтому COM этого не делает. COM предполагает, что DLL загрузили для использования ее кода! COM хранит DLL, пока отделение (apartment) существует и пока вы не попросили COM выгрузить эту DLL.
Кроме того, вы используете JScript, язык с недетерминированным сборщиком мусора. Даже если бы COM агрессивно выгружал DLL, установка объекта в null не освободила бы его в JScript. В этом языке объект помечается как «доступный для освобождения», а это совсем другое дело. Объект не будет освобожден, пока не запустится сборщик мусора, что может произойти спустя некоторое время.
Если коротко, то вы используете неподходящий язык. Если вам нужен детерминированный контроль за сроками жизни COM DLL, переходите на язык вроде C++, который позволяет управлять временем жизни всех экземпляров объектов и где в любой момент можно вызвать CoFreeUnusedLibraries. (Подробнее о CoFreeUnusedLibraries и о том, когда она освобождает объекты см. msdn.microsoft.com/library/en-us/com/htm/cmf_a2c_3p2r.asp. Остальную информацию о COM можно найти на msdn.microsoft.com/library/en-us/com/htm/comportal_3qn9.asp.)
Есть несколько способов решения проблемы. Один из них — написать две DLL, первая из которых содержит объект, а вторая — фабрику классов. COM создает библиотеку-фабрику, и эта библиотека никогда не выгружается. Зато она может управлять временем жизни объектной DLL — когда ей поступает запрос на создание экземпляра, она загружает объектную DLL и создает этот экземпляр. Объектная DLL, вероятно, должна уметь как-то взаимодействовать с фабрикой и сообщать ей о том, что освобожден последний объект. Тогда фабрика сможет агрессивно выгружать объектную DLL.
По-видимому, существуют и более изящные способы. Например, файлы с теневым копированием. Или вызов функции CollectGarbage, принудительно запускающей сбору мусора. Вызывать эту функцию приходится в очень редких случаях, но, похоже, что это один из них.
Благодарю за техническую информацию следующих разработчиков Microsoft: Francisco Arreciado, Sanjiv Banerjee, Jamie Brigden, Todd Carter, Jim Cheshire, Michael Evans, Alan Gao, Mark Haas, Zhaojie Huang, Bas Hugenholtz, Chris Jackson, Rajive Kumar, Eric Lippert, Christer Ljung, David Lovell, Carlos Aguilar Mares, Wade Mascia, Matt Neerincx, Nikola Penkov, Don Smith, Josh Twist, Murugesan Vivekananthan и Peter Williams.