Максимальный размер пула, связанный с платформой Entity 4.3

Это будет длинный пост, поэтому, пожалуйста, держитесь со мной.

Один из рабочих мест, которые мы реализовали здесь на работе несколько месяцев назад, я начал так часто видеть сообщение об ошибке утечки соединения в наших журналах ELMAH.

"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached."

Это озадачило меня, поскольку мы используем EF, и обработка соединений должна была быть автоматической.

Итак, я начал рыть. Первым потенциальным виновником, который я рассматривал, был MiniProfiler (или, я бы сказал, наша реализация использования минипрофилера). Мы использовали это, и он работает хорошо, но я беспокоился о возможных утечках соединений.

    public OurContext() : base(GetProfilerConnection(), true)
    {}

    private static DbConnection GetProfilerConnection()
    {
        return new EFProfiledDbConnection(new SqlConnection(ConfigurationManager.ConnectionStrings["Database"].ConnectionString),
                                          MiniProfiler.Current);
    }       

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

enter image description here

В нашей ветке расширения DEV я удалил miniprofiler, поскольку он не был обновлен для поддержки EF5, и мы собираемся мигрировать в какой-то момент в недалеком будущем, поэтому это должно быть устранено как проблема.

Вторая проблема заключалась в том, что "мы правильно распоряжаемся нашими данными"? Поэтому я загрузил Entity Framework Profiler на пробную версию и взял нашу самую тяжелую страницу и проверил тест.

enter image description here

Результаты явно показали, что какой-либо контекст, который мы открыли, был закрыт, а часть, относящаяся ко мне, - это число контекстов, которые мы открываем. У нас есть наша установка контейнера DI (Ninject 2), чтобы установить один контекст на веб-http-запрос, который я бы считайте правильным. Проблема заключается в том, как мы обрабатываем изображения в нашем приложении. Эта страница, в частности, может содержать до семи изображений в базе данных. Каждое из этих изображений включено в страницу посредством действия MVC. Например:

[<img src="/Controller/GetPhotoAction/[ImageId] />]

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

Причина хранения изображений в базе данных двоичная. Во-первых, наше административное приложение для управления данными для этого приложения находится на Западном побережье США, но серверы, на которых размещено приложение, находятся на восточном побережье США. Eсть VPN-туннель между нашей сетью здесь, на работе на Западном побережье и серверах на Восточном побережье. Приложение также сбалансировано по нагрузке (2 веб-интерфейса). Было принято решение сохранить изображения в БД, чтобы избежать копирования изображений через туннель VPN, а затем с разрешениями на запись изображений в местоположение файла в веб-приложении на каждом сервере (эти два местоположения также являются полностью разными доменами).

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

Итак, мои вопросы:

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

2) Если контексты нескольких данных на этой странице оказались виновниками, предложения о том, как записать образ на два сервера по всей стране, имея в виду разрешения, будут пересекать домены? Реально, я бы хотел сделать это в ожидании, но технические препятствия немного больше, чем мы готовы сделать в это время перед праздниками.

3) Если вы считаете, что ни одно из перечисленных проблем не является проблемой, что я могу потерять? Неужели это действительно так, что запросы достаточно высоки, и мы сталкиваемся с этой ошибкой, и нам нужно масштабироваться? Я могу выкопать журналы, чтобы просматривать статистику использования, но это кажется маловероятным. Эта страница кэшируется в течение часа (есть переменная по параметру)

Ответ 1

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

  • с использованием профайлера SQL (вы можете видеть, сколько соединений открыто/закрыто)
  • контролировать пул подключений на IIS - посмотрите здесь больше - http://msdn.microsoft.com/en-us/library/aa175863%28SQL.80%29.aspx
  • установить максимальный размер пула в строке подключения до максимального значения подключений, ожидаемых для одного запроса. Я попытался запустить приложение, которое использует тот же подход, что и для хранения и получения изображений с помощью Максимальный размер пула = 1 на странице с более чем 10 изображениями, и это не удалось с тем же исключением, что и у вас. Когда я удалил ошибку с вложенными соединениями для каждого запроса, это было нормально даже с этими подзапросами на изображениях.

И на ваш вопрос. Вы должны быть в порядке с одним контекстом данных для запроса. Когда он будет запрашивать область видимости, он будет удален в конце запроса (фактически он задерживается до тех пор, пока сборщик мусора не соберет объект запроса). Но будьте осторожны, если вы не используете свой datacontext напрямую (например, у вас есть обертка шаблона репозитория вокруг него), потому что могут быть некоторые скрытые (утечки) ошибок.