KeepAlive auf falsch setzen, wenn Sie mit externen Hosts in einem Plug-in interagieren
Artikel
Kategorie: Leistung
Wirkungspotential: Hoch
Symptome
Wenn ein Plug-in externe Web-Anfragen stellt und versucht, KeepAlive auf einer geschlossenen Verbindung zu verwenden, kann das Plug-in die Web-Anfrage letztendlich nicht ausführen. Wenn das Plug-in registriert ist:
Synchron können die Benutzer Folgendes erleben:
Nicht reaktionsfähige, modellgetriebene Anwendungen
Langsame Kundeninteraktionen
Der Browser reagiert nicht mehr.
Asynchron können Plug-in-Ausführungen einen längeren Zeitraum in Anspruch nehmen, bevor sie fehlschlagen.
Anleitung
In HTTP 1.1 gelten alle Verbindungen als persistent (KeepAlive ist wahr), sofern nicht anders angegeben. Da Plug-Ins isoliert laufen, übersetzt der Sandbox-Dienst sie in kurzlebige Ausführungen, die im Allgemeinen nicht von KeepAlive profitieren würden. Um Probleme bei der Verbindung zu externen Diensten zu vermeiden, empfehlen wir, KeepAlive innerhalb von Plug-Ins zu deaktivieren. Wenn Ihr spezieller externer Dienst aus Performance-Gründen von der Verwendung persistenter Sitzungen profitieren würde, senden Sie aktiv eine KeepAlive im Abstand von der Hälfte des Leerlauf-Timeout (30 Sekunden), damit die Verbindung nicht geschlossen wird.
Die folgenden Beispiele zeigen, wie Sie KeepAlive explizit auf false definieren, je nachdem, mit welcher Methode Sie eine Verbindung zu einem externen Dienst herstellen:
HttpWebRequest
HttpWebRequest req = WebRequest.Create("https://www.contoso.com/api/stuff") as HttpWebRequest;
if (req != null)
{
req.KeepAlive = false;
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
}
WebClient
private string RequestString(Uri location)
{
using (var client = new MyWebClient())
{
return client.DownloadString(location);
}
}
internal class MyWebClient : WebClient
{
// Overrides the GetWebRequest method and sets keep alive to false
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
req.KeepAlive = false;
return req;
}
}
WCF ClientBase< T >-Instanz
OrganizationServiceClient client = null;
try
{
var address = new EndpointAddress("https://www.contoso.com/Custom.svc");
var transport = new HttpsTransportBindingElement();
transport.KeepAliveEnabled = false;
var binding = new CustomBinding(transport);
client = new OrganizationServiceClient(binding, address);
WhoAmIResponse response = client.Execute(new WhoAmIRequest()) as WhoAmIResponse;
}
catch (Exception ex)
{
client.Abort();
}
finally
{
client.Close();
}
WCF ChannelFactory< TChannel > Static-Methode
IRequestChannel channel = null;
try
{
var address = new EndpointAddress("https://www.contoso.com/Custom.svc");
var transport = new HttpsTransportBindingElement();
transport.KeepAliveEnabled = false;
var binding = new CustomBinding(transport);
channel = ChannelFactory<IRequestChannel>.CreateChannel(binding, address);
Message request = Message.CreateMessage(MessageVersion.Soap12, "some action", "message body");
Message response = channel.Request(request);
}
catch (Exception ex)
{
channel.Abort();
}
finally
{
channel.Close();
}
WCF ChannelFactory< TChannel >-Instanz
ChannelFactory<IRequestChannel> factory = null;
IRequestChannel channel = null;
try
{
var address = new EndpointAddress("https://www.contoso.com/Custom.svc");
var transport = new HttpsTransportBindingElement();
transport.KeepAliveEnabled = false;
var binding = new CustomBinding(transport);
factory = new ChannelFactory<IRequestChannel>(binding, address);
channel = factory.CreateChannel();
Message request = Message.CreateMessage(MessageVersion.Soap12, "some action", "message body");
Message response = channel.Request(request);
}
catch (Exception ex)
{
channel.Abort();
factory.Abort();
}
finally
{
channel.Close();
factory.Close();
}
Problematische Muster
Um den Standardwert von KeepAlive für die Nicht-WCF-Interaktionen zu überschreiben, sollte der Ansatz gewählt werden, HttpWebRequest zu nutzen, um die Interaktionen mit dem Webserver durchzuführen, aber zuerst die Eigenschaft KeepAlive auf false zu setzen.
Die folgenden Beispiele zeigen das problematische Muster basierend auf der Methode, mit der Sie eine Verbindung zu einem externen Dienst herstellen:
Warnung
Diese Muster sollten vermieden werden.
HttpWebRequest
WebRequest request = WebRequest.Create("https://www.contoso.com/api/stuff");
//KeepAlive not explicitly defined as true. However, default behavior is KeepAlive = true.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
response.Close();
WebClient
using (var client = new WebClient())
{
string url = "https://www.contoso.com/api/stuff";
//KeepAlive not explicitly defined as true. However, default behavior is KeepAlive = true.
string result = client.DownloadString(url);
}
WCF ClientBase< T >-Instanz
OrganizationServiceClient client = null;
try
{
var address = new EndpointAddress("https://www.contoso.com/Custom.svc");
var binding = new BasicHttpsBinding();
//KeepAlive not explicitly defined as true. However, default behavior is KeepAlive = true.
client = new OrganizationServiceClient(binding, address);
WhoAmIResponse response = client.Execute(new WhoAmIRequest()) as WhoAmIResponse;
}
catch (Exception ex)
{
client.Abort();
}
finally
{
client.Close();
}
WCF ChannelFactory< TChannel > Static-Methode
IRequestChannel channel = null;
try
{
var address = new EndpointAddress("https://www.contoso.com/Custom.svc");
var binding = new BasicHttpsBinding();
//KeepAlive not explicitly defined as true. However, default behavior is KeepAlive = true.
channel = ChannelFactory<IRequestChannel>.CreateChannel(binding, address);
Message request = Message.CreateMessage(MessageVersion.Soap12, "some action", "message body");
Message response = channel.Request(request);
}
catch (Exception ex)
{
channel.Abort();
}
finally
{
channel.Close();
}
WCF ChannelFactory< TChannel >-Instanz
ChannelFactory<IRequestChannel> factory = null;
IRequestChannel channel = null;
try
{
var address = new EndpointAddress("https://www.contoso.com/Custom.svc");
var binding = new BasicHttpsBinding();
//KeepAlive not explicitly defined as true. However, default behavior is KeepAlive = true.
factory = new ChannelFactory<IRequestChannel>(binding, address);
channel = factory.CreateChannel();
Message request = Message.CreateMessage(MessageVersion.Soap12, "some action", "message body");
Message response = channel.Request(request);
}
catch (Exception ex)
{
channel.Abort();
factory.Abort();
}
finally
{
channel.Close();
factory.Close();
}
Weitere Informationen
Plug-Ins, die mit externen Diensten interagieren, können zu ungewöhnlich verlängerten Ausführungszeiten führen. Das Problem ist auf die (KeepAlive-Eigenschaft) von HTTP-Anfragen zurückzuführen, die an externe Webserver ausgegeben werden. Wenn die Eigenschaft KeepAlive auf true gesetzt oder gar nicht definiert ist (Standardverhalten ist wahr), kann der Sandbox-Client auf dem Server weiterhin versuchen, eine persistente Sitzung zu verwenden, obwohl die Sitzung aufgrund der Konfiguration des Netzwerkgeräts abgelaufen ist. Die Ursache für die verlängerte Ausführungszeit liegt darin, dass das Netzwerk die Anfrage erneut versucht, bis die Verbindung letztendlich zurückgesetzt wird.
Dieses Verhalten ist für Endbenutzer und die traditionelle Protokollierung transparent, da die Ausführung auf Verzögerungen im Netzwerk zurückzuführen ist. Wenn das Plug-in als synchrones Ereignis registriert wurde, konnten Benutzer während der registrierten Vorgänge intermittierende Performance-Probleme auftreten, die zu einer mangelnden Reaktionsfähigkeit modellgetriebener Anwendungen führen konnten. Wenn das Plug-in asynchron registriert ist, wird das Problem nur beobachtet, wenn die Ausführungszeiten des Plug-ins überprüft werden und die Ausführung länger dauert als normal oder erwartet.
Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)
Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).
Ziel dieses Moduls ist es, einen detaillierten Überblick über Plug-Ins in Zusammenhang mit der Microsoft Power Platform-Entwicklung zu geben. In diesem Modul wird überprüft, wie und wann Plug-Ins implementiert werden, wie sie registriert und bereitgestellt werden und welche verschiedenen Konfigurationsoptionen während der Plug-In-Registrierung verfügbar sind.