System.Net.Http различное поведение в службах Windows и консольных приложениях

#c# #system.net.webexception #system.net.httpwebrequest

#c# #system.net.webexception #system.net.httpwebrequest

Вопрос:

Я пытаюсь создать службу Windows, которая выполняет HTTP-запросы по таймеру. После развертывания приложения в рабочей среде я заметил, что определенная конечная точка не может получать данные. После ручной проверки я, конечно, знаю, что могу выполнить ping, выполнить POST-запрос к этой конечной точке.

Я заметил, что если я запускаю точно такой же код в той же версии .NET 4.7.2, консольное приложение будет успешным, а служба Windows — нет. Он выдает это исключение:

Консольное приложение:

 using (HttpClient httpClient = new HttpClient())
 {
     httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", "xxxxxxxxxxxxxxx");
     var content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
     Console.WriteLine(await content.ReadAsStringAsync());
     var response = await httpClient.PostAsync("http://xx.xx.xx.xx:8080/zzz/xx.svc/InsertData", content);
     Console.WriteLine(response.StatusCode);
}
 

Служба Windows:

 using (HttpClient httpClient = new HttpClient())
{
    httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(endpoint.AuthScheme, endpoint.AuthKey);
    var content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
                        try
                        {
                            var response = await httpClient.PostAsync(endpoint.UrlAddress, content);
                            response.EnsureSuccessStatusCode();
                            logger.Info($"Duomenys perduoti gavėjui:{endpoint.Name}");
                        }
                        catch (Exception ex)
                        {
                            logger.Warn($"Nepavyko perduoti duomenų šaltiniui: {endpoint.Name}; Adresas:{endpoint.UrlAddress}; Duomenų kiekis:{endpoint.Tags.Count}", ex);
                        }   
}
 

Исключение:

 System.Net.Http.HttpRequestException: An error occurred while sending the request. 
---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. 
---> System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 
---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   at System.Net.PooledStream.EndRead(IAsyncResult asyncResult)
   at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at HistorianPusher.Service.<Timer_Elapsed>d__5.MoveNext() in C:Usersalaburda_esourcereposHistorianPusherHistorianPusherService.cs:line 120
 

Я могу заверить, что проверяю адрес, ключ аутентификации, схему — все соответствует 100%. Я отключил прокси, брандмауэр.

Конфигурация установщика службы:

             // 
            // serviceProcessInstaller1
            // 
            this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
            this.serviceProcessInstaller1.Password = null;
            this.serviceProcessInstaller1.Username = null;
            // 
            // serviceInstaller1
            // 
            this.serviceInstaller1.ServiceName = "Historian Pusher";
            this.serviceInstaller1.DisplayName = "Historian Pusher";
            this.serviceInstaller1.Description = "Procesas skirtas perduoti Historian duomenis į išorinius šaltinius naudojantis HTTP/HTTPS protokolu";
            this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
 

Комментарии:

1. В качестве примечания я рекомендую прочитать, что вы используете HttpClient неправильно, и это дестабилизирует ваше программное обеспечение, и вы (вероятно, все еще) используете HttpClient неправильно, и это дестабилизирует ваше программное обеспечение.

2. @John Спасибо, я видел ту первую ссылку, которую вы любезно предоставили. Это довольно простое, но полезное решение. Это следующее, что нужно сделать в моем списке, но сначала мне нужно разобраться с этой огромной проблемой. 🙁

3. Запустите Fiddler и проверьте, нет ли различий в сетевых запросах.