Проблемы с сессией в Asp.Net - PullRequest
1 голос
/ 24 мая 2011

У нас есть веб-ферма серверов IIS 6, на которой работает наше приложение.
Наш сеанс хранится на Sql Server 2005 на другом сервере.

Каждые пару месяцев мы получаем эту ошибку в одном из журналов веб-сервера: «Время ожидания истекло. Период ожидания истек до получения соединения из пула. Это могло произойти, потому что все соединения в пуле были использованы и максимальный размер пула был достигнут»

Трассировка стека: System.Data.ProviderBase.DbConnectionInternal GetConnection (System.Data.Common.DbConnection) в System.Data.ProviderBase.DbConnectionFactory.GetConnnection (DbConnection owningConnection) в System.Data.ProviderBase.DbConnectionClosed.OpenConnection (DbConnection outerConnection, DbConnectionFactory connectionFactory) в System.Data.SqlClient.SqlConnection.Open () в Systme.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor (SqlPartitionInfo sqlPartitionInfo)

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

Единственное решение, которое мы нашли, - это сброс IIS на этом сервере.

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

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 24 мая 2011

Это классика плохого управления ресурсами.Если вы используете пользовательский диспетчер сеансов (модуль) с SQL, то вы неправильно распределяете соединения, и в пуле приложений заканчиваются соединения.Затем все последующие соединения ожидают автоматического удаления соединения;и именно здесь происходит тайм-аут.

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

Тайм-ауты при большой нагрузке

Если ваши веб-серверы находятся под большой нагрузкой, может быть полезно увеличить время ожидания для доступа к состоянию сеанса.Вы можете добавить атрибут stateNetworkTimeout к настройкам sessionState в web.config и machine.config

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

http://idunno.org/articles/277.aspx

Кроме того Вы должны использовать SessionState только для базовых типов данных, таких как string, int, bool.хранят много информации или сложных типов данных, может быть, вам нужно пересмотреть, что и почему они там хранятся.

Вам следует изучить использование Cache или Viewstate.В Интернете есть много таких статей, например: http://www.codeproject.com/KB/session/exploresessionandcache.aspx

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

Еще одна полезная ссылка: http://devshop.wordpress.com/2008/04/10/how-to-choose-from-viewstate-sessionstate-cookies-and-cache/

0 голосов
/ 25 мая 2011

Поскольку ваши комментарии стали более конкретными, я также должен добавить следующее. Если вы создаете класс, подобный следующему:

    public class PartitionResolver : System.Web.IPartitionResolver
    {
        private String[] partitions;

        public void Initialize()
        {
            // create the partition connection string table
            //                           web1,            web2
            partitions = new String[] { "192.168.1.1", "192.168.1.2" }; // keep adding servers
        }

        public String ResolvePartition(Object key)
        {
            String oHost = System.Web.HttpContext.Current.Request.Url.Host.ToLower().Trim();

            if (oHost.StartsWith("10.0.0") || oHost.Equals("localhost"))
                return "tcpip=127.0.0.1:42424";

            String sid = (String)key;

            // hash the incoming session ID into
            // one of the available partitions
            Int32 partitionID = Math.Abs(sid.GetHashCode()) % partitions.Length;

            return ("tcpip=" + partitions[partitionID] + ":42424");
        }
    }

... и затем в вашем файле web.config вы добавляете что-то вроде следующего:

<sessionState mode="StateServer" 
              partitionResolverType="NameSpaceName.PartitionResolver" 
              cookieless="false" 
              timeout="60" />

... и следуйте инструкциям:

http://www.c -sharpcorner.com / UploadFile / gopenath / Page107182007032219AM / Page1.aspx

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

Все, что вам нужно будет сделать, это обновить эту строку:

partitions = new String[] { "192.168.1.1", "192.168.1.2" }; // keep adding servers

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

...