Alguns milhares de solicitações por minuto são um grande load, e a única maneira de fazer isso direito, é controlando e limitando o número máximo de threads que podem estar sendo executados a qualquer momento.
Como não há muita informação postada sobre como você implementou isso. Vou cobrir algumas circunstâncias possíveis.
Hora de experimentar...
As constantes:
- Itens a serem processados:
- 50 por segundo , ou em outras palavras...
- 3.000 por minuto , e mais uma maneira de ver isso...
- 180.000 por hora
As variáveis:
-
Taxas de transferência de dados:
-
A quantidade de dados que você pode transferir por segundo desempenhará um papel, não importa o que façamos, e isso varia ao longo do dia, dependendo da hora do dia.
A única coisa que podemos fazer é disparar mais solicitações de diferentes CPUs para distribuir o peso do tráfego que estamos enviando de volta.
-
-
Poder de processamento:
-
Estou assumindo que você tem isso em umWebJob
em vez de ter isso codificado dentro do site MVC, é ele mesmo. É altamente ineficiente e inadequado para o propósito que você está tentando alcançar. Ao usar um WebJob, podemos enfileirar itens de trabalho a serem processados por outrosWebJobs
. A fila em questão é o Azure Queue Armazenamento .
-
Os problemas:
- Estamos tentando concluir 50 transações por segundo, portanto, cada transação deve ser feita em menos de 1 segundo se estivermos utilizando 50 threads. Nosso tempo limite de 45 segundos não serve para nada neste momento.
- Esperamos que 50 threads sejam executados simultaneamente e todos sejam concluídos em menos de um segundo, a cada segundo, em uma única CPU. (Estou exagerando um ponto aqui, só para fazer um ponto... mas imagine baixar 50 arquivos de texto a cada segundo. Processá-lo e depois tentar enviá-lo de volta para um colega na esperança de que eles estejam prontos para pegue-o)
- Precisamos ter uma lógica de repetição, se após 3 tentativas o item não for processado, ele precisará ser colocado de volta na fila. Idealmente, devemos fornecer mais tempo para o servidor responder do que apenas um segundo a cada falha, digamos que demos uma pausa de 2 segundos na primeira falha, depois 4 segundos, depois 10, isso aumentará muito as chances de persistirmos / recuperando os dados que precisávamos.
- Estamos assumindo que nosso MongoDb pode lidar com esse número de solicitações por segundo. Se você ainda não o fez, comece a procurar maneiras de escaloná-lo, o problema não está no fato de ser um MongoDb, a camada de dados pode ter sido qualquer coisa, é o fato de estarmos fazendo esse número de solicitações de uma única fonte que será a causa mais provável de seus problemas.
A solução:
- Configurar um
WebJob
e nomeie-oEnqueueJob
. EsteWebJob
terá um único propósito, enfileirar itens de trabalho a serem processados noQueue Storage
. - Crie um
Queue Storage Container
chamadoWorkItemQueue
, essa fila funcionará como um gatilho para a próxima etapa e iniciará nossas operações de expansão. - Crie outro
WebJob
chamadoDequeueJob
. EsteWebJob
também terá um único propósito, desenfileirar os itens de trabalho doWorkItemQueue
e dispare as solicitações para seu armazenamento de dados. - Configure o
DequeueJob
para girar assim que um item for colocado dentro daWorkItemQueue
, inicie 5 encadeamentos separados em cada um e enquanto a fila não estiver vazia, desenfileirar itens de trabalho para cada encadeamento e tentar executar o trabalho desenfileirado.- Tentativa 1, se falhar, aguarde e tente novamente.
- Tentativa 2, se falhar, aguarde e tente novamente.
- Tentativa 3, se falhar, enfileira o item de volta para
WorkItemQueue
- Configure seu site para dimensionar automaticamente para x quantidade de CPU (observe que seu site e trabalhos da Web compartilham os mesmos recursos)
Aqui está um vídeo curto de 10 minutos que fornece uma visão geral sobre como utilizar armazenamentos de filas e trabalhos da web.
Editar:
Outra razão pela qual você pode estar recebendo esses erros pode ser por causa de dois outros fatores, novamente causados por estar em um aplicativo MVC ...
Se você estiver compilando o aplicativo com o
DEBUG
atributo aplicado, mas empurrando o RELEASE
em vez disso, você pode ter problemas devido às configurações em seu web.config
, sem o DEBUG
atributo, um aplicativo Web ASP.NET executará uma solicitação por no máximo 90 segundos, se a solicitação demorar mais do que isso, ela descartará a solicitação. Para aumentar o tempo limite para mais de 90 segundos você precisará alterar o
[httpRuntime][3]
propriedade em seu web.config
... <!-- Increase timeout to five minutes -->
<httpRuntime executionTimeout="300" />
A outra coisa que você precisa estar ciente são as configurações de tempo limite de solicitação do seu navegador> aplicativo da web, eu diria que se você insistir em manter o código no MVC em vez de extraí-lo e colocá-lo em um WebJob, então você pode usar o código a seguir para disparar uma solicitação para seu aplicativo Web e compensar o tempo limite da solicitação.
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();
}