Example #1
0
        public async Task ConsumeAsync(AsyncMessageConsumer <byte[]> consumer,
                                       CancellationToken cancellationToken)
        {
            if (consumer.Registered)
            {
                throw new ApplicationException("This consumer is already registered");
            }

            if (!DeclareQueue(consumer.Queue))
            {
                throw new ApplicationException("Declare queue failed");
            }

            var channel = _channelDict[consumer.Queue];

            consumer.Register();
            consumer.OnClosing += x => { CloseQueue(x.Queue); };

            await Task.Factory.StartNew(async() =>
            {
                while (await channel.Reader.WaitToReadAsync(cancellationToken))
                {
                    var bytes = await channel.Reader.ReadAsync(cancellationToken);
                    Task.Factory.StartNew(async() =>
                    {
                        await consumer.InvokeAsync(bytes);
                    }, cancellationToken)
                    .ConfigureAwait(false).GetAwaiter();
                }
            }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
Example #2
0
        private async Task RegisterConsumerAsync(CancellationToken stoppingToken)
        {
            var topic = string.Format(TopicNames.Spider, Id.ToUpper());

            Logger.LogInformation($"{Id} register topic {topic}");
            _consumer           = new MessageQueue.AsyncMessageConsumer <byte[]>(topic);
            _consumer.Received += async bytes =>
            {
                var message = await bytes.DeserializeAsync(stoppingToken);

                if (message == null)
                {
                    Logger.LogWarning("{Id} received empty message");
                    return;
                }

                if (message is Exit exit)
                {
                    Logger.LogInformation($"{Id} receive exit message {JsonConvert.SerializeObject(exit)}");
                    if (exit.SpiderId == Id.ToUpper())
                    {
                        await ExitAsync();
                    }
                }
                else if (message is Response response)
                {
                    // 1. 从请求队列中去除请求
                    var request = _requestedQueue.Dequeue(response.RequestHash);

                    if (request == null)
                    {
                        Logger.LogWarning($"{Id} dequeue {response.RequestHash} failed");
                    }
                    else
                    {
                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            if (_services.IsDistributed)
                            {
                                Logger.LogInformation($"{Id} download {request.RequestUri}, {request.Hash} success");
                            }

                            request.Agent = response.Agent;
                            await _services.StatisticsClient.IncreaseAgentSuccessAsync(response.Agent,
                                                                                       response.ElapsedMilliseconds);
                            await HandleResponseAsync(request, response, bytes);
                        }
                        else
                        {
                            await _services.StatisticsClient.IncreaseAgentFailureAsync(response.Agent,
                                                                                       response.ElapsedMilliseconds);

                            var exception = Encoding.UTF8.GetString(response.Content.Data);
                            Logger.LogError(
                                $"{Id} download {request.RequestUri}, {request.Hash} status code: {response.StatusCode} failed: {exception}");
                            // 每次调用添加会导致 Requested + 1, 因此失败多次的请求最终会被过滤不再加到调度队列
                            await AddRequestsAsync(request);

                            OnError?.Invoke(request, response);
                        }
                    }
                }
                else
                {
                    Logger.LogError($"{Id} receive error message {JsonConvert.SerializeObject(message)}");
                }
            };
            await _services.MessageQueue.ConsumeAsync(_consumer, stoppingToken);
        }