C# - производительность HttpWebRequest / GetResponse

У меня есть API на основе HTTPS, который мне нужно вызывать много раз. Использование HttpWebRequest.Create(uri).GetResponse() для выполнения занимает от 50 мс до 500 мс или более. Чтобы проверить время отклика, я реализовал это так:

private void Action()
{
    WebRequest request = HttpWebRequest.Create("https://.....");
    using (WebResponse response = request.GetResponse()) { }
}

и затем вызывая это:

private long getTime()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    Action();
    return sw.ElapsedMilliseconds;
}

Выход за несколько звонков:

Time: 746 ms
Time: 51 ms
Time: 50 ms
Time: 50 ms
Time: 51 ms
Time: 49 ms
Time: 2417 ms ???
Time: 52 ms
Time: 52 ms
Time: 51 ms
Time: 50 ms
Time: 201 ms
Time: 234 ms
Time: 204 ms
Time: 51 ms
Time: 50 ms
Time: 50 ms
Time: 52 ms
Time: 280 ms
Time: 264 ms

Первый вопрос: мне было интересно, есть ли способ ускорить GetResponse, чтобы он занимал как можно меньше времени?

Теперь... потому что мне нужно сделать МНОГО разных запросов с разными URL, чтобы ускорить процесс, который я решил использовать TPL Dataflow Block (вместо Parallel.Foreach), поскольку Parallel.Foreach в основном используется для CPU bound работа, и то, что я делаю, I/O bound (есть также обработка ответа, так же немного работы процессора). И когда я использую блокировку потока данных TPL, обработка 250 URL-адресов занимает до 7 секунд, в то время как параллельный прогон занимает 15 секунд или более, так что я уверен, что использование блока потока данных TPL - правильный путь. Как я это реализовал:

//CALL:
var block = new ActionBlock<string>(uri => Action(uri), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 200 });
foreach (var URL in urlArray)
{
    block.Post(URL);
}
block.Complete();
await block.Completion;

//Action(uri):
private void Action(string uri)
{
    WebRequest request = HttpWebRequest.Create(uri);
    using (WebResponse response = request.GetResponse()) { }
}

И так как я не доволен выполнением 7 s, я попытался настроить ServicePointManager чтобы ускорить это, я уже пробовал, но ничего из этого не сработало:

ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.Expect100Continue = false;
ServicePointManager.SetTcpKeepAlive(false, 0, 0);
ServicePointManager.DefaultConnectionLimit = 1000;

Второй ВОПРОС: Если это не возможно, ускорение GetResponse() чтобы добиться более быстрого исполнения, есть ли способ настроить TPL Dataflow Block в лучшую производительность?

РЕДАКТИРОВАТЬ: Моя цель состоит в том, чтобы выполнить все вызовы как можно быстрее.

1 ответ

Решение

Вы можете ускорить решение, используя GetResponseAsync. Смотрите также это пошаговое руководство Micorsoft, где оба метода (синхронный и асинхронный) подробно описаны.

Другие вопросы по тегам