2016-02-23 2 views
0

У меня есть приложение MVC, развернутое на 3 отдельных серверах (тестовая, промежуточная и производственная среда). Тестирование и сервер Балетмейстера делают хорошо, но время от времени, сервер производства вытаскивает эту ошибкуNhibernate, SQL Server и IIS 7.5 Утечка соединения: время ожидания до получения соединения из пула приложений

System.InvalidOperationException таймаута. Период ожидания истекает до получения соединения> из пула. Возможно, это произошло из-за того, что все объединенные соединения были в> использовании и максимальный размер пула.

Полная трассировка стека, зафиксированная elmah, показана ниже.

Timeout error message

Сервер производства на SQL Server 2008 и IIS 7.5.

разъем Driver My Nhibernate является, как показано ниже

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> 
<session-factory> 
    <property name="dialect">NHibernate.Dialect.MsSql2008Dialect,NHibernate</property> 
    <property name="adonet.batch_size">0</property> 
    <property name="show_sql">true</property> 
    <mapping assembly="BusinessLogic"/> 
</session-factory> 
</hibernate-configuration> 

Вот мой Получить текущий сеанс Метод

public static ISession GetCurrentSession() 
     { 
      HttpContext context = HttpContext.Current; 
      ISession currentSession = context.Items[CURRENT_NHIBERNATE_SESSION_KEY] as ISession; 

      if (currentSession == null) 
      { 
       currentSession = sessionFactory.OpenSession(); 
       context.Items[CURRENT_NHIBERNATE_SESSION_KEY] = currentSession; 
      } 
      if (currentSession.Connection.State == System.Data.ConnectionState.Closed) 
      { 
       currentSession = sessionFactory.OpenSession(); 
      } 
      if (!currentSession.IsConnected) 
      { 
       currentSession = sessionFactory.OpenSession(); 
      } 
      if (!currentSession.IsOpen) 
      { 
       currentSession = sessionFactory.OpenSession(); 
      } 
      if (currentSession.IsDirty()) 
      { 
       currentSession.Clear(); 
      } 

      return currentSession; 
     } 

Я использовал IRepository образец для всей моей бизнес-логики. Один из моих методов показан здесь:

public IList<CourseRequirement> getCourseRequirement(int requirementId) 
      { 
       ISession session = _courseRequirment.CurrentSession; 
       var cr = session.QueryOver<CourseRequirement>().Where(x => x.RequirementId == requirementId); 
       return cr.List<CourseRequirement>(); 
      } 

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

System.InvalidOperationException: при попытке создать контроллер типа «ASSEMBLY.Controllers.AccountController» произошла ошибка. Удостоверьтесь, что контроллер имеет безкоммертный публичный конструктор. ---> Autofac.Core.DependencyResolutionException: Исключение было выбрано при вызове конструктора 'Void .ctor()' для типа 'NHibernateRepository`2'. ---> Истекло время ожидания. Период таймаута истек до получения соединения из пула. Это может иметь , потому что все объединенные соединения использовались, и был достигнут максимальный размер пула . (См. Внутреннее исключение для деталей.) ---> System.InvalidOperationException: время ожидания истекло. Период таймаута истек до получения соединения из пула. Это может иметь , потому что все объединенные соединения использовались, и был достигнут максимальный размер пула .

То, что я сделал

Я проверил эти link, link и многое другое. Другие, такие как how-to-fix-sql-connection-leaks-in-this-code, предложили использовать sql с помощью операторов. Почти все ссылки предполагают утечку соединения в приложении и рекомендуют помещать всю транзакцию в оператор using.

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

Я волнуюсь, потому что это не единственное приложение, которое я написал таким образом, и, кроме того, тестовая и промежуточная среда в порядке.Из отчета о регистрации это часто происходит, когда сайт находится на низком трафике, например, 6:00 утра, 3.00 утра, но время не фиксировано.

Просьба помочь

Update Это мой autofac Dependency распознаватель (я могу видеть из внутреннего исключения, что autofac не может создать экземпляр некоторые услуги иногда

public class FormDependencyResolver 
    { 
     public static void RegisterDependencies() 
     { 

      var builder = new ContainerBuilder(); 

      builder.RegisterControllers(typeof(MvcApplication).Assembly); 


      builder.Register(c => 
       //register FakeHttpContext when HttpContext is not available 
       HttpContext.Current != null ? 
       (new HttpContextWrapper(HttpContext.Current) as HttpContextBase) : 
       (new FakeHttpContext("~/") as HttpContextBase)) 
       .As<HttpContextBase>() 
       .InstancePerLifetimeScope(); 
      builder.Register(c => c.Resolve<HttpContextBase>().Request) 
       .As<HttpRequestBase>().InstancePerLifetimeScope(); 

      builder.Register(c => c.Resolve<HttpContextBase>().Response) 
       .As<HttpResponseBase>() 
       .InstancePerLifetimeScope(); 
      builder.Register(c => c.Resolve<HttpContextBase>().Server) 
       .As<HttpServerUtilityBase>() 
       .InstancePerLifetimeScope(); 
      builder.Register(c => c.Resolve<HttpContextBase>().Session) 
       .As<HttpSessionStateBase>() 
       .InstancePerLifetimeScope(); 



      builder.RegisterGeneric(typeof(NHibernateRepository<,>)).As(typeof(IRepository<,>)).InstancePerLifetimeScope(); 
      builder.RegisterType<AsyncService>().As<IAsyncService>().InstancePerLifetimeScope();//.InstancePerLifetimeScope(); 
      builder.RegisterType<SMSSender>().As<ISMSSender>().InstancePerLifetimeScope(); 
      builder.RegisterType<SMSAccount>().As<ISMSAccount>().InstancePerLifetimeScope(); 
      builder.RegisterType<BusinessLogic.Services.AuthenticationService>().As<IAuthenticationService>().InstancePerLifetimeScope(); 
      builder.RegisterType<PageHelper>().As<IPageHelper>().InstancePerLifetimeScope(); 

      builder.RegisterType<UtilityService>().As<IUtilityService>().InstancePerLifetimeScope(); 
      builder.RegisterType<WebWorker>().As<IWebWorker>().InstancePerLifetimeScope(); 
      builder.RegisterType<DateTimeHelper>().As<IDateTimeHelper>().InstancePerLifetimeScope(); 
      builder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope(); 
      builder.RegisterType<AuditService>().As<IAuditService>().InstancePerLifetimeScope(); 
      builder.RegisterType<HtmlHelper>().InstancePerDependency(); 
      builder.RegisterType<PaymentService>().As<IPaymentService>().InstancePerLifetimeScope(); 

      IContainer container = builder.Build(); 
      DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

     } 
    } 

ответ

0

Вы открываете новые экземпляры сессии в каждый из этих операторов if. Некоторые из них могут быть выполнены сразу, поскольку нет операторов else. Ранее открытый сеанс выходил за пределы области действия без вызова Dispose().

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

private static readonly object syncObject = new Object(); 

public static ISession GetCurrentSession() 
{ 
    lock (syncObject) 
    { 
     HttpContext context = HttpContext.Current; 
     ISession currentSession = context.Items[CURRENT_NHIBERNATE_SESSION_KEY] as ISession; 

     if (currentSession == null) 
     { 
      currentSession = sessionFactory.OpenSession(); 
     } 

     context.Items[CURRENT_NHIBERNATE_SESSION_KEY] = currentSession;  

     return currentSession; 
    } 
} 
+0

Спасибо за это @Dmitry S, но текущая сессия была инициирована вне оператора if. Я имею в виду, что у нас есть только один экземпляр, но множественное назначение в выражении if. –

+1

'sessionFactory.OpenSession()' инициализирует новый сеанс для каждого присваивания. –

Смежные вопросы