Ответ 1
Несколько тысяч запросов в минуту - это большая загрузка, и единственный способ сделать это правильно - это контролировать и ограничивать максимальное количество потоков, которые могут быть запущены в любой момент времени.
Как не так много информации о том, как вы это сделали. Я собираюсь прикрыть несколько возможных обстоятельств.
Время эксперимента...
Константы:
- Элементы для обработки:
- 50 в секунду, или другими словами...
- 3000 в минуту и еще один способ взглянуть на него...
- 180 000 в час
Переменные:
-
Скорость передачи данных:
-
Сколько данных, которые вы можете перенести в секунду, будет играть роль независимо от того, что мы делаем, и это будет меняться в течение дня в зависимости от времени суток.
Единственное, что мы можем сделать, это слить больше запросов с разных процессоров, чтобы распределить вес трафика, который мы отправляем обратно.
-
-
Мощность обработки:
-
Я предполагаю, что у вас есть это в
WebJob
, а не на том, что это закодировано внутри сайта MVC. Он очень неэффективен и не подходит для цели, которую вы пытаетесь достичь. Используя WebJob, мы можем поставить в очередь рабочие элементы, которые будут обрабатываться другимиWebJobs
. В очереди находится Azure Queue Storage.Хранилище очереди Azure - это служба для хранения большого количества сообщений к которым можно получить доступ из любой точки мира посредством аутентификации звонки с использованием HTTP или HTTPS. Одно сообщение о очереди может быть до 64 КБ в размере, и очередь может содержать миллионы сообщений, вплоть до общей суммы ограничение емкости учетной записи хранения. Аккаунт хранилища может содержать до 200 ТБ данных blob, queue и table. См. Лазурное хранилище Масштабируемость и целевые показатели производительности для получения подробной информации об учетной записи хранилища емкость.
Общее использование хранилища очереди включает:
- Создание отставания в работе для асинхронного процесса
- Передача сообщений с роли Azure Web в роль Azure Worker
-
Проблемы:
- Мы пытаемся выполнить 50 транзакций в секунду, поэтому каждая транзакция должна выполняться менее чем за 1 секунду, если мы используем 50 потоков. Наш 45-й тайм-аут не имеет никакой цели на данный момент.
- Мы ожидаем, что 50 потоков будут выполняться одновременно, и все будет выполнено через секунду, каждую секунду, на одном процессоре. (Я преувеличиваю точку здесь, просто чтобы понять... но представьте, что вы загружаете 50 текстовых файлов каждую секунду. Обработайте ее, а затем попытайтесь отдать ее обратно коллеге в надежде, что они даже будут готовы к поймать его)
- Нам нужно иметь логику повтора, если после трех попыток элемент не обрабатывается, их нужно поместить обратно в очередь. В идеале мы должны уделять больше времени серверу, чтобы ответить, чем одна секунда с каждой неудачей, скажем, что мы дали ему 2-секундный перерыв при первом провале, затем 4 секунды, затем 10, это значительно увеличит шансы на то, что мы продолжим/получение необходимых нам данных.
- Мы полагаем, что наш MongoDb может обрабатывать это количество запросов в секунду. Если вы еще этого не сделали, начните смотреть на способы его масштабирования, проблема заключается не в том, что это MongoDb, слой данных мог быть чем угодно, это тот факт, что мы делаем это количество запросов от единственный источник, который будет наиболее вероятной причиной ваших проблем.
Решение:
- Настройте
WebJob
и назовите егоEnqueueJob
. ЭтотWebJob
будет иметь одну единственную цель - поставить в очередь элементы работы, которые будут выполняться вQueue Storage
. - Создайте
Queue Storage Container
с именемWorkItemQueue
, эта очередь будет действовать как триггер следующего шага и начнет выполнять операции масштабирования. - Создайте еще один
WebJob
с именемDequeueJob
. ЭтотWebJob
также будет иметь одну единственную цель - отключить рабочие элементы изWorkItemQueue
и запустить запросы в хранилище данных. - Сконфигурируйте
DequeueJob
, чтобы разворачиваться, как только элемент был помещен внутриWorkItemQueue
, запустите по 5 отдельных потоков на каждом и пока очередь не пуста, деактивируйте рабочие элементы для каждого потока и попытайтесь выполнить заданное задание,- Попытка 1, если вы не можете, подождите и повторите попытку.
- Попытка 2, если вы не можете, подождите и повторите попытку.
- Попытка 3, если не удается, вернуть объект обратно в
WorkItemQueue
- Настройте свой веб-сайт на автоматическое масштабирование до x объема процессора (обратите внимание, что ваш веб-сайт и веб-задания имеют одни и те же ресурсы).
Вот короткое 10-минутное видео, в котором дается обзор использования хранилищ очередей и веб-заданий.
Edit:
Другая причина, по которой вы можете получить эти ошибки, может быть связана с двумя другими факторами, опять-таки вызванными тем, что она находится в приложении MVC...
Если вы компилируете приложение с приложенным атрибутом DEBUG
, но вместо этого нажимаете версию RELEASE
, вы можете столкнуться с проблемами из-за настроек в вашем web.config
, без атрибута DEBUG
, Веб-приложение ASP.NET выполнит запрос в течение не более 90 секунд, если запрос займет больше времени, он избавится от запроса.
Чтобы увеличить тайм-аут дольше, чем 90 секунд, вам нужно будет изменить свойство [httpRuntime][3]
в web.config
...
<!-- Increase timeout to five minutes -->
<httpRuntime executionTimeout="300" />
Другая вещь, о которой вам нужно знать, - это настройки тайм-аута запроса вашего браузерa > веб-приложения, я бы сказал, что если вы настаиваете на сохранении кода в MVC, а не на его извлечении и вводе в WebJob, то вы можете использовать следующий код, чтобы отправить запрос в свое веб-приложение и компенсировать время ожидания запроса.
string html = string.Empty;
string uri = "http://google.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Timeout = TimeSpan.FromMinutes(5);
using (HttpWebResponse response = (HttpWebResonse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
html = reader.ReadToEnd();
}