C # Threadpooling HttpWebRequests
-
05-07-2019 - |
Pergunta
Eu li e parecia um muito poucos exemplos para Threadpooling mas eu simplesmente não consigo entender que eles maneira eu preciso. O que eu conseguir ter trabalho não é realmente o que eu preciso. Ele só executa a função em seu próprio segmento.
public static void Main()
{
while (true)
{
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
Console.WriteLine("ID has been queued for fetching");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
Console.ReadLine();
}
}
public static void Process(object state)
{
var s = StatsFecther("byId", "0"); //returns all player stats
Console.WriteLine("Account: " + s.nickname);
Console.WriteLine("ID: " + s.account_id);
Console.ReadLine();
}
O que estou tentando fazer é ter cerca de 50 tópicos de ir (talvez mais) que buscar dados PHP serializado contendo as estatísticas dos jogadores. A partir de usuário 0 todo o caminho até um ID de usuário i especificar (300.000). A minha pergunta não é sobre como buscar as estatísticas que eu sei como obter as estatísticas e lê-los, mas como eu escrever um pool de threads que irá manter buscar estatísticas até que chega a 300000 ID de usuário sem pisar os dedos dos outros segmentos e salva as estatísticas, uma vez que recupera-los para um banco de dados.
Solução
static int _globalId = 0;
public static void Process(object state)
{
// each queued Process call gets its own player ID to fetch
processId = InterlockedIncrement(ref _globalId);
var s = StatsFecther("byId", processId); //returns all player stats
Console.WriteLine("Account: " + s.nickname);
Console.WriteLine("ID: " + s.account_id);
Console.ReadLine();
}
Esta é a coisa mais simples de fazer. Mas está longe de ser ideal. Você está usando chamadas síncronas, você está contando com o ThreadPool para estrangular a sua taxa de chamada, você não tem nenhuma política de repetição para chamadas falhadas e sua aplicação vai se comportar extemamente ruim sob condições de erro (quando as chamadas web estão falhando).
Em primeiro lugar você deve considerar usando os métodos assíncronos de WebRequest: BeginGetRequestStream (se você postar e ter um corpo de solicitação) e / ou BeginGetResponse . Estes métodos escala muito melhor e você vai ter um troughput maior para menos CPU (se o back-end pode manter-se, é claro).
Em segundo lugar você deve considerar a auto-throthling. Em um projeto similar eu usei uma contagem solicitação pendente. Em caso de sucesso, cada chamada iria apresentar mais 2 chamadas, tampado com a contagem throtling. Em caso de falha a chamada não iria apresentar qualquer coisa. Se nenhuma chamada estão pendentes, uma nova tentativa com base temporizador envia uma nova chamada a cada minuto. Desta forma você só tentar uma vez por minuto quando o serviço é baixo, poupando seus próprios recursos de girar w / o de tração, e você aumentar o rendimento backup para a tampa throtling quando o serviço é para cima.
Você também deve saber que o framework .Net irá limitar o número de conncetions concurent faz a qualquer recurso. Você deve encontrar o seu destino ServicePoint e mudança ConnectionLimit de seu valor padrão (2 ) para o valor máximo que está disposto a estrangular por diante.
Sobre a parte de atualização de banco de dados, há maneira de muitas variáveis ??em jogo e muito pouca informação para dar qualquer conselho meaningfull. Alguns conselhos gerais seria usar métodos assíncronos na chamada de banco de dados também, o tamanho yoru conneciton piscina para permitir o seu boné throtling, certifique-se suas atualizações de usar o ID do jogador como uma chave para que você não impasse sobre como atualizar o mesmo registro de segmentos diferentes .
Outras dicas
Como você determina o ID do usuário? Uma opção é segmentar todos os fios de modo que os fios X lida com ID de entre 0 -. N, e assim por diante, como uma fração de quantas linhas você tem