Я работаю над проектом утилизации и использую .NET Core 2.0.Мой клиент предоставил около 1 миллиона доменов, и клиент попросил меня проверить, активен ли домен, и убедиться, что ответ в порядке.Мой код ниже.Когда я читаю домен из файла, у меня нет никаких проблем, и производительность отличная.
Моя проблема: когда я использую PLINQ и проверяю, активен ли домен, он использует только один поток, а для 25000 доменов это занимает около часа.Когда я использую метод семафоров, производительность хорошая, и иногда количество доменов в результате не совпадает с входным.Например, из 25000 доменов я получаю результат, подобный 24798, и я не знаю, где остальные 202 домена.Как улучшить производительность и что мне не хватает в коде?Пожалуйста помоги.Здесь я предоставляю версию кода PLINQ и семафора.
Версия семафора
var semaphore = new Semaphore(200, 225);
var allDomains = new List<BsonDocument>();
try
{
foreach (var domain in domainList)
{
var cT1 = Task.Factory.StartNew(() =>
{
try
{
semaphore.WaitOne();
Interlocked.Increment(ref countThreads);
var active = IsDomainActive(domain) ? true : false;
lock (allDomains) allDomains.Add(
new BsonDocument
{
{"Url", domain},
{"Active", active},
{"CreatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)},
{"UpdatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)}
}
);
}
finally
{
semaphore.Release();
Interlocked.Decrement(ref countThreads);
}
}, TaskCreationOptions.LongRunning);
}
}
finally
{
if (semaphore != null)
{
semaphore.Dispose();
semaphore = null;
}
}
Версия PLINQ
var allDomains = (
from domain in domainList.AsParallel().WithCancellation(cancellationToken).WithDegreeOfParallelism(7).WithExecutionMode(ParallelExecutionMode.ForceParallelism)
where IsDomainActive(domain)
select new BsonDocument
{
{"Url", domain},
{"CreatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)},
{"UpdatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)}
}).ToList();
private static bool IsDomainActive(string url)
{
var domain = new StringBuilder();
domain.Append("http://");
domain.Append(url);
Console.WriteLine($"IsDomainActive: {url:00} - On Thread " + $"{Thread.CurrentThread.ManagedThreadId:00}. Concurrent: {countThreads}");
try
{
var request = (HttpWebRequest) WebRequest.Create(new Uri(domain.ToString()));
request.Timeout = 5000;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
var response = (HttpWebResponse)request.GetResponse();
return (response == null || response.StatusCode != HttpStatusCode.OK) ? false : true;
}
catch (Exception e)
{
return false;
}
}
Моя конфигурация компьютера ниже, и проблема появляется в обеих средах.
- RAM: 64 ГБ
- Процессор: 8Core
- Windows 10
Моя конфигурация сервера Linux ниже
- ОЗУ: 4 ГБ
- HDD: 80 ГБ SSD
- ОС: Ubuntu 16.04
- Процессор:4Core
@ edit1
Я обновил код с помощью HttpClient.GetAsync, но производительность по-прежнему низкая, и даже для 1000 доменов это занимает много времени.
private static async Task<bool> IsDomainActive(string url)
{
var domain = new StringBuilder();
domain.Append("http://");
domain.Append(url);
Console.WriteLine("Processing Domain: " + url);
try
{
var sessionId = (new Random()).Next().ToString();
var netProxy = new WebProxy("<proxyserver>", port);
login = "<login>";
password = "<password>";
netProxy.Credentials = new NetworkCredential(login, password);
var handler = new HttpClientHandler()
{
Proxy = netProxy,
UseProxy = true,
};
var httpClient = new HttpClient(handler);
var request = new HttpRequestMessage() {
RequestUri = new Uri(domain.ToString()),
Method = HttpMethod.Get
};
request.Headers.Add("Timeout","5000");
request.Headers.Add("UserAgent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2");
var response = await httpClient.SendAsync(request).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return true;
}
catch (Exception e)
{
return false;
}
}
@ edit2 Изменен список <> на одновременный.
private static List<BsonDocument> ProcessFile(ConcurrentBag<string> domains, IProgress<string> progress,
CancellationToken cancellationToken)
{
var allDomains = (from domain in domains.AsParallel().WithCancellation(cancellationToken)
.WithDegreeOfParallelism(Environment.ProcessorCount)
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
where IsDomainActive(domain).Result
select new BsonDocument
{
{"Url", domain},
{"Protocol", "http"},
{"CreatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)},
{"UpdatedOn", DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local)}
}).ToList();
return allDomains;
}