http HEAD vs GET Leistung

111

Ich richte einen REST-Webdienst ein, der nur so schnell wie möglich mit JA oder NEIN antworten muss.

Das Entwerfen eines HEAD-Dienstes scheint der beste Weg zu sein, aber ich würde gerne wissen, ob ich wirklich etwas Zeit gewinnen werde, anstatt eine GET-Anfrage zu stellen.

Ich nehme an, dass der Body-Stream auf meinem Server nicht geöffnet / geschlossen wird (ca. 1 Millisekunde?). Kann ich beim Transport jederzeit die IP-Paketnummer gewinnen, da die Anzahl der zurückzugebenden Bytes sehr gering ist?

Vielen Dank im Voraus für Ihre Antwort!

Bearbeiten:

Um den Kontext weiter zu erklären:

  • Ich habe eine Reihe von REST-Services, die einige Prozesse ausführen, wenn sie sich in einem aktiven Zustand befinden.
  • Ich habe einen anderen REST-Service, der den Status all dieser ersten Services angibt.

Da dieser letzte Dienst sehr oft von einer sehr großen Anzahl von Clients aufgerufen wird (ein Anruf wird alle 5 ms erwartet), habe ich mich gefragt, ob die Verwendung einer HEAD-Methode eine wertvolle Optimierung sein kann. Im Antworttext werden ca. 250 Zeichen zurückgegeben. Die HEAD-Methode erhält mindestens den Transport dieser 250 Zeichen, aber wie wirkt sich das aus?

Ich habe versucht, den Unterschied zwischen den beiden Methoden (HEAD vs GET) zu messen, indem ich das 1000-fache der Aufrufe ausgeführt habe, aber überhaupt keinen Gewinn gesehen (<1 ms) ...

Asterius
quelle
2
Dies hängt auch von dem Ansatz ab, den Sie serverseitig verwenden. Die Verarbeitung einer GET-Anforderung oder einer HEAD-Anforderung kann normalerweise dieselbe Serverzeit in Anspruch nehmen, da der Server möglicherweise den endgültigen Hauptteil zur Berechnung des Content-LengthHeader-Werts kennen muss. Dies ist eine wichtige Information in einer Antwort auf eine HEAD-Anforderung. Sofern es keinen anderen optimierten serverseitigen Ansatz gibt, besteht der einzige Vorteil darin, dass Bandbreite gespart wird und der Client den Antworttext nicht analysieren muss. Grundsätzlich hängen die Optimierungsgewinne sowohl von der Server- als auch von der Client-Implementierung ab.
itsjavi

Antworten:

173

Ein RESTful-URI sollte eine "Ressource" auf dem Server darstellen. Ressourcen werden häufig als Datensatz in einer Datenbank oder einer Datei im Dateisystem gespeichert. Wenn die Ressource nicht groß ist oder nur langsam auf dem Server abgerufen werden kann, wird möglicherweise kein messbarer Gewinn erzielt, wenn Sie HEADanstelle von verwenden GET. Es kann sein, dass das Abrufen der Metadaten nicht schneller ist als das Abrufen der gesamten Ressource.

Sie könnten beide Optionen implementieren und sie vergleichen, um festzustellen, welche schneller sind, aber anstatt sie zu optimieren, würde ich mich darauf konzentrieren, die ideale REST-Schnittstelle zu entwerfen. Eine saubere REST-API ist auf lange Sicht normalerweise wertvoller als eine kludgey API, die möglicherweise schneller ist oder nicht. Ich entmutige nicht die Verwendung von HEAD, sondern schlage nur vor, dass Sie es nur verwenden, wenn es das "richtige" Design ist.

Wenn die Informationen, die Sie wirklich benötigen, Metadaten zu einer Ressource sind, die in den HTTP-Headern gut dargestellt werden können, oder um zu überprüfen, ob die Ressource vorhanden ist oder nicht, HEADfunktionieren sie möglicherweise gut.

Angenommen, Sie möchten überprüfen, ob die Ressource 123 vorhanden ist. A 200bedeutet "Ja" und A 404bedeutet "Nein":

HEAD /resources/123 HTTP/1.1
[...]

HTTP/1.1 404 Not Found
[...]

Wenn jedoch das von Ihrem REST-Service gewünschte "Ja" oder "Nein" Teil der Ressource selbst ist und nicht Metadaten, sollten Sie es verwenden GET.

Und Rot
quelle
2
Die besten Dinge sind immer einfach, genau wie diese Antwort. Voila!
Afzal SH
Wunderbare Antwort! Ich habe eine Frage: Wie wäre es, wenn Sie es als touchBefehl verwenden, um die Anzahl der Aufrufe eines Posts auf dem Server zu aktualisieren? Die Post-Daten wurden bereits über einen normalen /postsAnruf abgerufen , daher möchte ich nur die Anzahl der Aufrufe aktualisieren, nachdem der Benutzer auf irgendeine Weise mit dem Post interagiert hat.
Aalaap
1
@aalaap Wenn Sie einen Ansichtszähler für HEADAnforderungen aktualisieren möchten , sollten Sie dies auch für GETAnforderungen tun . Die Entscheidung für GEToder HEADist letztendlich Sache des HTTP-Clients. Ihr Server sollte sich für beide Anforderungstypen gleich verhalten, außer dass bei der Beantwortung kein Antworttext vorhanden ist HEAD. Ich bin mir nicht sicher, ob dies ein guter Weg ist, um so etwas wie einen Ansichtszähler zu implementieren.
Andre D
-1 Alle Informationen, die benannt werden können, können eine Ressource sein. Daher Uniform Resource Locator. Die Idee, dass die Verwendung eines Teils des HTTP-Protokolls wie geplant "kludgey" oder "unrein" ist, ist bizarr.
Fraser
1
@Siddhartha, das stimmt sehr oft, aber nicht immer. Content-Lengthkann bei der Verwendung weggelassen werden Transfer-Encoding: chunked. Trotzdem Content-Lengthist es möglich, dass der Server die Ressourcengröße und andere in Headern verwendete Metadaten abruft, ohne die tatsächliche Ressource abzurufen. Möglicherweise werden diese Metadaten sogar für einen sehr schnellen Zugriff im Speicher zwischengespeichert. Das ist alles sehr implementierungsspezifisch.
Andre D
38

Ich habe diese Antwort gefunden, als ich nach derselben Frage gesucht habe, die der Antragsteller gestellt hat. Ich fand dies auch unter http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html :

Die HEAD-Methode ist identisch mit GET, außer dass der Server in der Antwort KEINEN Nachrichtentext zurückgeben darf. Die in den HTTP-Headern als Antwort auf eine HEAD-Anforderung enthaltenen Metainformationen MÜSSEN mit den Informationen identisch sein, die als Antwort auf eine GET-Anforderung gesendet wurden. Diese Methode kann verwendet werden, um Metainformationen über die durch die Anforderung implizierte Entität zu erhalten, ohne den Entitätskörper selbst zu übertragen. Diese Methode wird häufig zum Testen von Hypertext-Links auf Gültigkeit, Zugänglichkeit und aktuelle Änderungen verwendet.

Es scheint mir, dass die richtige Antwort auf die Frage des Antragstellers darin besteht, dass es davon abhängt, was durch das REST-Protokoll dargestellt wird. In meinem speziellen Fall wird beispielsweise mein REST-Protokoll verwendet, um ziemlich große Bilder (wie in mehr als 10 KB) abzurufen. Wenn eine große Anzahl solcher Ressourcen ständig überprüft wird und ich die Anforderungsheader verwende, ist es sinnvoll, die HEAD-Anforderung gemäß den Empfehlungen von w3.org zu verwenden.

Charles Thomas
quelle
14

Ich rate dringend von einem solchen Ansatz ab.

Ein RESTful-Dienst sollte die Semantik der HTTP-Verben berücksichtigen. Das GET-Verb soll den Inhalt der Ressource abrufen, während das HEAD-Verb keinen Inhalt zurückgibt und beispielsweise verwendet werden kann, um festzustellen, ob sich eine Ressource geändert hat, um ihre Größe oder ihren Typ zu kennen und um zu überprüfen, ob sie sich geändert hat existiert und so weiter.

Und denken Sie daran: Frühe Optimierung ist die Wurzel allen Übels.

Eric Citaire
quelle
8

Ihre Leistung wird sich kaum ändern, wenn Sie eine HEAD-Anforderung anstelle einer GET-Anforderung verwenden.

Wenn Sie möchten, dass es REST-voll ist und Daten abrufen möchten, sollten Sie außerdem eine GET-Anforderung anstelle einer HEAD-Anforderung verwenden.

jabbink
quelle
8

GET holt Kopf + Körper, HEAD holt nur Kopf. Es sollte keine Ansichtssache sein, welche schneller ist. Ich verstehe die oben genannten Antworten nicht. Wenn Sie nach META-Informationen suchen, wählen Sie HEAD, das für diesen Zweck bestimmt ist.

Viktor Joras
quelle
3

Ich verstehe Ihre Besorgnis nicht, dass der Körperstrom offen / geschlossen ist. Der Antworttext befindet sich über demselben Stream wie die http-Antwortheader und erstellt KEINE zweite Verbindung (die übrigens eher im Bereich von 3 bis 6 ms liegt).

Dies scheint ein sehr vorzeitiger Optimierungsversuch für etwas zu sein, das keinen signifikanten oder sogar messbaren Unterschied macht. Der wirkliche Unterschied ist die Konformität mit REST im Allgemeinen, die die Verwendung von GET zum Abrufen von Daten empfiehlt.

Meine Antwort lautet NEIN. Verwenden Sie GET, wenn es sinnvoll ist. Mit HEAD wird kein Leistungsgewinn erzielt.

smassey
quelle
Angenommen, der Inhalt beträgt 100 MB. Sicherlich wird der Kopf kleiner als der Inhalt sein. Wenn wir diese Ressource Ihrer Meinung nach nach der GET- oder HEAD-Methode anfordern, gibt es keinen Leistungsunterschied zwischen ihnen?!
Mohammad Afrashteh
3
Das OP gab 250 Zeichen im Hauptteil der Antwort an. Nicht 100 MB. Das ist eine ganz andere Frage.
Smassey
1

HEAD- Anforderungen sind genau wie GET- Anforderungen, außer dass der Hauptteil der Antwort leer ist. Diese Art von Anforderung kann verwendet werden, wenn Sie nur Metadaten zu einer Datei benötigen, aber nicht alle Daten der Datei transportieren müssen.

Shadab Ali
quelle
-1

Sie können leicht einen kleinen Test durchführen, um die Leistung selbst zu messen. Ich denke, der Leistungsunterschied wäre vernachlässigbar, denn wenn Sie nur 'Y' oder 'N' im Body zurückgeben, ist es ein einzelnes zusätzliches Byte, das an einen bereits offenen Stream angehängt wird.

Ich würde auch mit GET gehen, da es korrekter ist. Sie sollten keinen Inhalt in HTTP-Headern zurückgeben, sondern nur Metadaten.

AshleysBrain
quelle
GET - es ist nicht nur ein mysteriöses "einzelnes zusätzliches Byte". Nur der ganze Körper! Bei großen Dokumenten können es einige Megabyte sein.
Porfirion