wake-up-neo.com

Singleton httpclient im Vergleich zur Erstellung einer neuen httpclient-Anforderung

Ich versuche, einen Layer für den Webservice mit HttpClient in meiner Xamarin.Forms-App zu erstellen.

  1. ohne singlton pattern
  2. mit Singleton-Muster

in first approach Ich erstelle in jeder neuen Anfrage ein neues http-Client-Objekt durch mobile Anwendung.

hier ist mein code

  public HttpClient GetConnection()
        {

            HttpClient httpClient = new HttpClient();
            httpClient.BaseAddress = new Uri(baseAddress); 
            httpClient.Timeout = System.TimeSpan.FromMilliseconds(timeout);


            return httpClient;

        }

anforderungscode posten 

 public async Task<TResult> PostAsync<TRequest, TResult>(String url, TRequest requestData)
        {
            HttpClient client = GetConnection();
            String responseData = null;
            if (client != null)
            {

                String serializedObject = await Task.Run(() => JsonConvert.SerializeObject(requestData, _jsonSerializerSettings));
                var jsonContent = new StringContent(serializedObject, System.Text.Encoding.UTF8, "application/json");
                HttpResponseMessage response = await client.PostAsync(new Uri(url, UriKind.Relative), jsonContent);
                responseData = await HandleResponse(response);


                return await Task.Run(() => JsonConvert.DeserializeObject<TResult>(responseData, _jsonSerializerSettings));


            }
            else
            {

                throw new NullReferenceException("NullReferenceException @ PostAsync  httpclient is null WebRequest.cs");

            }

        }

der Client verwendet folgenden Code, um die Anforderung auszuführen

new LoginService(new WebRequest()).UserLogin(userRequest);

innerhalb der Klasse, die IWebRequest implementiert

_webRequest.PostAsync<UserRequest,bool>(Constants.USER_LOGIN, userRequest);

in second approach verwende ich dasselbe http-Client-Objekt in jeder neuen Anfrage Hier ist meine Singleton-Klasse auch threadsicher.

private static readonly Lazy<HttpService> lazy =
        new Lazy<HttpService>(() => new HttpService());

        public static HttpService Instance { get { return lazy.Value; } }



        private HttpClient getConnection()
        {

            client = new HttpClient();
            client.Timeout = System.TimeSpan.FromMilliseconds(timeout);

            //client.MaxResponseContentBufferSize = 500000;
            client.BaseAddress = new Uri(baseAddress);
            return client;
        }

anforderungscode posten 

public Task<HttpResponseMessage> sendData(String url,String jsonData)
        {

            var jsonContent = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");

            return getConnection().PostAsync(new Uri(url, UriKind.Relative), jsonContent);
        }

der Client verwendet folgenden Code zur Ausführung 

HttpService.Instance.sendData(...)

ich bin durch viele Bibliotheken wie RestSharp über das Web gegangen, um das Beste zu erkunden, und ich habe festgestellt, dass die meisten von ihnen neue Objekte pro Anfrage erstellen. Ich bin verwirrt, welches Muster am besten passt.

11
Hunt

Update: Es scheint, dass die Verwendung einer einzelnen statischen Instanz von HttpClient keine DNS-Änderungen berücksichtigt. Daher besteht die Lösung in der Verwendung von HttpClientFactory. Unter hier finden Sie Microsoft-Dokumente.


Singleton ist die richtige Art, HttpClient zu verwenden. Bitte sehen Sie this article für vollständige Details.

Microsoft docs state:

HttpClient soll einmalig instanziiert werden und während der gesamten Lebensdauer einer Anwendung wiederverwendet werden. Durch das Instanziieren einer HttpClient-Klasse für jede Anforderung wird die Anzahl der unter schwerer Last verfügbaren Steckdosen erschöpft. Dies führt zu SocketException-Fehlern. Unten ist ein Beispiel, das HttpClient korrekt verwendet.

Und tatsächlich haben wir dies in unserer Anwendung gefunden. Wir haben Code, der potenziell Hunderte von API-Anforderungen in einer foreach-Schleife auslösen kann. Für jede Iteration haben wir eine HttpClient erstellt, die in eine using eingeschlossen ist. Schon bald bekamen wir rote Heringsfehler von unserer MongoClient und sagten, dass es beim Versuch, eine Verbindung zur Datenbank herzustellen, abgelaufen war. Nachdem wir den verlinkten Artikel gelesen hatten, stellten wir fest, dass HttpClient entsorgt wurde, und stellten fest, dass wir die verfügbaren Sockel erschöpften. 

Das einzige, was zu beachten ist, ist, dass Dinge wie DefaultRequestHeaders und BaseAddress überall dort angewendet werden, wo HttpClient verwendet wird. Als Singleton gilt dies möglicherweise für die gesamte Anwendung. Sie können immer noch mehrere HttpClient-Instanzen in Ihrer Anwendung erstellen. Beachten Sie jedoch, dass sie jedes Mal einen neuen Verbindungspool erstellen und daher sparsam erstellt werden sollten.

Wie von hvaughan3 hervorgehoben, können Sie auch die vom HttpClient verwendete Instanz von HttpMessageHandler nicht ändern. Wenn dies für Sie wichtig ist, müssen Sie mit diesem Handler eine separate Instanz verwenden.

20
John

Während HttpClient wiederverwendet werden soll, bedeutet dies nicht notwendigerweise, dass wir Singleton verwenden müssen, um unseren Code zu organisieren. Bitte beziehen Sie sich auf meine Antwort hier .

PS: Nicht sicher, ob ich diese Antwort hier kopieren und einfügen soll. Gib mir Bescheid.

0
RayLuo

Wie bereits erwähnt, sollte meist HttpClient als Singleton verwendet werden, es gibt jedoch eine Ausnahme - Sie sollten HttpClient nicht als Singleton verwenden, wenn Sie die HTTP long polling-Technik verwenden, da Sie die Ausführung anderer Anforderungen blockieren.

Für lange Abrufanfragen sollten Sie eine separate HttpClient erstellen.

0
mkul