Wydajność http HEAD vs GET

111

Konfiguruję usługę internetową REST, która musi odpowiadać TAK lub NIE, tak szybko, jak to możliwe.

Zaprojektowanie usługi HEAD wydaje się najlepszym sposobem na zrobienie tego, ale chciałbym wiedzieć, czy naprawdę zyskam trochę czasu w porównaniu z wykonaniem żądania GET.

Przypuszczam, że strumień treści nie jest otwierany / zamykany na moim serwerze (około 1 milisekundy?). Ponieważ ilość zwracanych bajtów jest bardzo mała, czy zyskuję czas w transporcie, w numerze pakietu IP?

Z góry dziękuję za twoją odpowiedź!

Edytować:

Aby dokładniej wyjaśnić kontekst:

  • Mam zestaw usług REST wykonujących niektóre procesy, jeśli są w stanie aktywnym.
  • Mam inną usługę REST wskazującą stan wszystkich tych pierwszych usług.

Ponieważ ta ostatnia usługa będzie wywoływana bardzo często przez bardzo dużą grupę klientów (jedno połączenie spodziewane co 5 ms), zastanawiałem się, czy użycie metody HEAD może być wartościową optymalizacją? W treści odpowiedzi zwracanych jest około 250 znaków. Metoda HEAD przynajmniej zyskuje transport tych 250 znaków, ale jaki to ma wpływ?

Próbowałem porównać różnicę między tymi dwiema metodami (HEAD vs GET), wykonując 1000 razy więcej połączeń, ale nie widzę żadnego zysku (<1 ms) ...

Asterius
źródło
2
Zależy to również od podejścia używanego po stronie serwera. Przetwarzanie żądania GET lub HEAD może zwykle zająć tyle samo czasu, ponieważ serwer może potrzebować znać ostateczną treść, aby obliczyć Content-Lengthwartość nagłówka, która jest ważną informacją w odpowiedzi na żądanie HEAD. O ile nie istnieje inne, bardziej zoptymalizowane podejście po stronie serwera, jedyną korzyścią jest to, że przepustowość jest zapisywana, a klient nie musi analizować treści odpowiedzi. Zasadniczo korzyści z optymalizacji zależą zarówno od implementacji serwera, jak i klienta.
itsjavi

Odpowiedzi:

173

URI RESTful powinien reprezentować „zasób” na serwerze. Zasoby są często przechowywane jako rekord w bazie danych lub jako plik w systemie plików. Jeśli zasób nie jest duży lub wolno go pobierać na serwerze, użycie HEADzamiast opcji może nie przynieść wymiernych korzyści GET. Może się zdarzyć, że pobranie metadanych nie jest szybsze niż pobranie całego zasobu.

Możesz zaimplementować obie opcje i przetestować je, aby zobaczyć, która jest szybsza, ale zamiast mikro-optymalizacji skupiłbym się na zaprojektowaniu idealnego interfejsu REST. Czysty interfejs API REST jest zwykle bardziej wartościowy na dłuższą metę niż nieznośny interfejs API, który może, ale nie musi, być szybszy. Nie zniechęcam do używania HEAD, po prostu sugeruję, aby używać go tylko wtedy, gdy jest to „właściwy” projekt.

Jeśli informacje, których potrzebujesz, to naprawdę metadane dotyczące zasobu, które można ładnie przedstawić w nagłówkach HTTP lub sprawdzić, czy zasób istnieje, czy nie, HEADmoże działać dobrze.

Na przykład załóżmy, że chcesz sprawdzić, czy istnieje zasób 123. A 200oznacza „tak”, a a 404oznacza „nie”:

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

HTTP/1.1 404 Not Found
[...]

Jeśli jednak „tak” lub „nie”, które chcesz uzyskać z usługi REST, jest częścią samego zasobu, a nie metadanych, powinieneś użyć GET.

I czerwony
źródło
3
najlepsze rzeczy są zawsze proste, tak jak ta odpowiedź. Voila!
Afzal SH
Wspaniała odpowiedź! Mam pytanie: co powiesz na użycie go jako touchpolecenia do aktualizacji liczby wyświetleń posta na serwerze? Dane postu zostały już pobrane za pośrednictwem zwykłego /postspołączenia, więc chcę tylko zaktualizować liczbę wyświetleń po tym, jak użytkownik w jakiś sposób z nim skorzysta.
aalaap
1
@aalaap Jeśli masz zamiar zaktualizować licznik wyświetleń HEADżądań, powinieneś to zrobić GETrównież dla żądań. Decyzja o użyciu GETlub HEADostatecznie zależy od klienta HTTP. Twój serwer powinien zachowywać się w ten sam sposób dla obu typów żądań, z wyjątkiem braku treści odpowiedzi podczas odpowiadania HEAD. Jeśli chodzi o to, czy jest to dobry sposób na zaimplementowanie czegoś takiego jak licznik wyświetleń, nie jestem pewien.
Andre D
-1 Wszelkie informacje, które można nazwać, mogą być zasobami. Stąd Uniform Resource Locator. Pomysł, że używanie części protokołu HTTP, zgodnie z projektem, jest „kludgey” lub „nieczysty”, jest dziwaczny.
Fraser
1
@Siddhartha, to bardzo często prawda, ale nie zawsze. Content-Lengthmożna pominąć podczas używania Transfer-Encoding: chunked. Nawet jeśli Content-Lengthjest to możliwe, serwer może uzyskać rozmiar zasobu i inne metadane użyte w nagłówkach bez pobierania rzeczywistego zasobu. Może te metadane są nawet buforowane w pamięci, aby uzyskać bardzo szybki dostęp. To wszystko jest bardzo specyficzne dla implementacji.
Andre D
38

Znalazłem tę odpowiedź, szukając tego samego pytania, które zadał żądający. Znalazłem to również na http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html :

Metoda HEAD jest identyczna z metodą GET, z wyjątkiem tego, że serwer NIE MOŻE zwracać treści wiadomości w odpowiedzi. Metainformacja zawarta w nagłówkach HTTP w odpowiedzi na żądanie HEAD POWINNA być identyczna z informacjami przesłanymi w odpowiedzi na żądanie GET. Tej metody można użyć do uzyskania metainformacji o jednostce, której dotyczy żądanie, bez przenoszenia samej treści jednostki. Ta metoda jest często używana do testowania linków hipertekstowych pod kątem ważności, dostępności i niedawnych modyfikacji.

Wydaje mi się, że prawidłowa odpowiedź na pytanie wnioskodawcy jest taka, że ​​zależy to od tego, co reprezentuje protokół REST. Na przykład w moim konkretnym przypadku mój protokół REST jest używany do pobierania dość dużych (jak w przypadku ponad 10 KB) obrazów. Jeśli mam stale sprawdzanych wiele takich zasobów i biorąc pod uwagę, że używam nagłówków żądań, sensowne byłoby użycie żądania HEAD, zgodnie z zaleceniami w3.org.

Charles Thomas
źródło
14

Zdecydowanie odradzam tego rodzaju podejście.

Usługa zgodna z REST powinna respektować semantykę czasowników HTTP. Czasownik GET ma na celu pobranie zawartości zasobu, podczas gdy czasownik HEAD nie zwróci żadnej treści i może być używany na przykład do sprawdzenia, czy zasób się zmienił, aby poznać jego rozmiar lub typ, aby sprawdzić, czy istnieje i tak dalej.

I pamiętaj: wczesna optymalizacja jest źródłem wszelkiego zła.

Eric Citaire
źródło
8

Twoja wydajność prawie się nie zmieni, jeśli użyjesz żądania HEAD zamiast żądania GET.

Ponadto, jeśli chcesz, aby był w pełni REST i chcesz uzyskać dane, powinieneś użyć żądania GET zamiast żądania HEAD.

jabbink
źródło
8

GET pobiera głowę + ciało, HEAD pobiera tylko głowę. Nie powinno być kwestią opinii, który z nich jest szybszy. Nie rozumiem powyższych odpowiedzi, za którymi się popieram. Jeśli szukasz informacji META, wybierz HEAD, który jest przeznaczony do tego celu.

Viktor Joras
źródło
3

Nie rozumiem twojej obawy związanej z „otwieraniem / zamykaniem strumienia ciała”. Treść odpowiedzi będzie znajdować się w tym samym strumieniu, co nagłówki odpowiedzi http i NIE będzie tworzyć drugiego połączenia (które, nawiasem mówiąc, jest bardziej w zakresie 3-6 ms).

Wydaje się, że jest to bardzo przedwczesna próba optymalizacji czegoś, co po prostu nie zrobi znaczącej ani nawet wymiernej różnicy. Prawdziwą różnicą jest ogólna zgodność z REST, który zaleca użycie GET do pobierania danych.

Moja odpowiedź brzmi NIE, użyj GET, jeśli ma to sens, nie ma wzrostu wydajności przy użyciu HEAD.

smassey
źródło
Załóżmy, że zawartość ma 100 MB. Z pewnością głowa będzie mniejsza niż zawartość. Teraz, gdy żądamy tego zasobu metodą GET lub HEAD, Twoim zdaniem nie ma między nimi różnicy w wydajności ?!
Mohammad Afrashteh
3
OP zawierał 250 znaków w treści odpowiedzi. Nie 100 MB. To zupełnie inne pytanie.
smassey
1

Żądania HEAD są takie same jak żądania GET , z wyjątkiem tego, że treść odpowiedzi jest pusta. Tego rodzaju żądanie może być używane, gdy wszystko, czego potrzebujesz, to metadane dotyczące pliku, ale nie musisz transportować wszystkich danych pliku.

Shadab Ali
źródło
-1

Możesz łatwo wykonać mały test, aby samodzielnie zmierzyć wydajność. Myślę, że różnica w wydajności byłaby pomijalna, ponieważ jeśli zwracasz tylko „Y” lub „N” w treści, jest to pojedynczy dodatkowy bajt dołączany do już otwartego strumienia.

Poszedłbym również z GET, ponieważ jest bardziej poprawny. Nie powinieneś zwracać treści w nagłówkach HTTP, tylko metadane.

AshleysBrain
źródło
GET - to nie tylko tajemniczy „pojedynczy dodatkowy bajt”. Tylko całe ciało! W przypadku dużego dokumentu może to być kilka megabajtów.
porfirion