http HEAD so với GET hiệu suất


111

Tôi đang thiết lập một dịch vụ web REST chỉ cần trả lời CÓ hoặc KHÔNG, càng nhanh càng tốt.

Thiết kế một dịch vụ HEAD có vẻ là cách tốt nhất để làm điều đó nhưng tôi muốn biết liệu tôi có thực sự mất thời gian so với việc thực hiện yêu cầu GET hay không.

Tôi cho rằng tôi đạt được luồng nội dung không được mở / đóng trên máy chủ của mình (khoảng 1 mili giây?). Vì số lượng byte trả về rất thấp, tôi có mất thời gian trong quá trình truyền tải, ở số gói IP không?

Cảm ơn trước sự phản ứng của bạn!

Biên tập:

Để giải thích thêm về bối cảnh:

  • Tôi có một tập hợp các dịch vụ REST đang thực thi một số quy trình, nếu chúng ở trạng thái hoạt động.
  • Tôi có một dịch vụ REST khác cho biết trạng thái của tất cả các dịch vụ đầu tiên này.

Vì dịch vụ cuối cùng đó sẽ được gọi rất thường xuyên bởi một tập hợp rất lớn khách hàng (dự kiến ​​cứ sau 5ms sẽ có một cuộc gọi), tôi đã tự hỏi liệu sử dụng phương pháp HEAD có thể là một tối ưu hóa có giá trị không? Khoảng 250 ký tự được trả lại trong phần nội dung phản hồi. Phương pháp HEAD ít nhất đạt được sự vận chuyển của 250 ký tự này, nhưng tác động đó là gì?

Tôi đã cố gắng đánh giá sự khác biệt giữa hai phương pháp (HEAD so với GET), chạy 1000 lần các cuộc gọi, nhưng không thấy lợi ích gì cả (<1ms) ...


2
Nó cũng phụ thuộc vào cách bạn sử dụng phía máy chủ. Thường có thể mất cùng một thời gian máy chủ để xử lý yêu cầu GET hoặc yêu cầu HEAD, vì máy chủ có thể cần biết nội dung cuối cùng để tính toán Content-Lengthgiá trị tiêu đề, đây là thông tin quan trọng trong phản hồi của yêu cầu HEAD. Trừ khi có một số phương pháp tiếp cận phía máy chủ khác được tối ưu hóa hơn, lợi ích duy nhất là băng thông được tiết kiệm và máy khách không phải phân tích cú pháp nội dung phản hồi. Vì vậy, về cơ bản, lợi ích tối ưu hóa phụ thuộc vào cả việc triển khai máy chủ và máy khách.
itjavi

Câu trả lời:


173

Một URI RESTful phải đại diện cho một "tài nguyên" tại máy chủ. Tài nguyên thường được lưu trữ dưới dạng bản ghi trong cơ sở dữ liệu hoặc tệp trên hệ thống tệp. Trừ khi tài nguyên lớn hoặc truy xuất chậm tại máy chủ, bạn có thể không thấy mức tăng có thể đo lường được bằng cách sử dụng HEADthay thế GET. Có thể là việc truy xuất dữ liệu meta không nhanh hơn việc truy xuất toàn bộ tài nguyên.

Bạn có thể triển khai cả hai tùy chọn và đánh giá chúng để xem cái nào nhanh hơn, nhưng thay vì tối ưu hóa vi mô, tôi sẽ tập trung vào việc thiết kế giao diện REST lý tưởng. Một API REST sạch thường có giá trị hơn về lâu dài so với một API nhỏ có thể nhanh hơn hoặc không nhanh hơn. Tôi không khuyến khích việc sử dụng HEAD, chỉ đề nghị bạn chỉ sử dụng nó nếu đó là thiết kế "phù hợp".

Nếu thông tin bạn thực sự cần là dữ liệu meta về một tài nguyên có thể được biểu diễn độc đáo trong tiêu đề HTTP hoặc để kiểm tra xem tài nguyên đó có tồn tại hay không, HEADcó thể hoạt động tốt hay không .

Ví dụ: giả sử bạn muốn kiểm tra xem tài nguyên 123 có tồn tại hay không. A 200nghĩa là "có" và a 404nghĩa là "không":

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

HTTP/1.1 404 Not Found
[...]

Tuy nhiên, nếu "có" hoặc "không" bạn muốn từ dịch vụ REST của mình là một phần của chính tài nguyên chứ không phải là dữ liệu meta, bạn nên sử dụng GET.


2
những điều tốt nhất luôn đơn giản, giống như câu trả lời này. Thì đấy!
Afzal SH

Câu trả lời tuyệt vời! Tôi có một câu hỏi: Còn về việc sử dụng nó như một touchlệnh để cập nhật số lượt xem bài đăng trên máy chủ thì sao? Dữ liệu bài đăng đã được truy xuất thông qua một /postscuộc gọi thông thường , vì vậy tôi chỉ muốn cập nhật số lượt xem sau khi người dùng tương tác với bài đăng theo một cách nào đó.
aalaap

1
@aalaap Nếu bạn định cập nhật bộ đếm lượt xem cho HEADcác yêu cầu, thì bạn cũng nên làm như vậy cho GETcác yêu cầu. Quyết định sử dụng GEThay HEADcuối cùng là tùy thuộc vào máy khách HTTP. Máy chủ của bạn sẽ hoạt động theo cùng một cách cho cả hai loại yêu cầu, ngoại trừ không có cơ quan phản hồi khi phản hồi HEAD. Về việc liệu đây có phải là một cách tốt để triển khai một cái gì đó như bộ đếm lượt xem hay không, tôi không chắc chắn.
Andre D

-1 Bất kỳ thông tin nào có thể được đặt tên đều có thể là tài nguyên. Do đó Bộ định vị Tài nguyên Đồng nhất. Ý tưởng rằng việc sử dụng một phần của giao thức HTTP, như được thiết kế, là "không sạch" hoặc "không sạch" là kỳ lạ.
Fraser

1
@Siddhartha, điều đó rất thường đúng, nhưng không phải lúc nào cũng vậy. Content-Lengthcó thể được bỏ qua khi sử dụng Transfer-Encoding: chunked. Thậm chí Content-Length, có thể máy chủ có thể lấy kích thước tài nguyên và siêu dữ liệu khác được sử dụng trong tiêu đề mà không cần tìm nạp tài nguyên thực tế. Có thể siêu dữ liệu đó thậm chí còn được lưu trong bộ nhớ để truy cập rất nhanh. Đó là tất cả các triển khai rất cụ thể.
Andre D

38

Tôi đã tìm thấy câu trả lời này khi tìm câu hỏi tương tự mà người yêu cầu đã hỏi. Tôi cũng tìm thấy cái này tại http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html :

Phương thức HEAD giống với GET ngoại trừ việc máy chủ KHÔNG PHẢI trả lại nội dung thư trong phản hồi. Thông tin siêu dữ liệu chứa trong các tiêu đề HTTP phản hồi yêu cầu HEAD NÊN giống với thông tin được gửi để phản hồi yêu cầu GET. Phương pháp này có thể được sử dụng để thu thập thông tin về thực thể được ám chỉ bởi yêu cầu mà không cần chuyển chính nội dung thực thể. Phương pháp này thường được sử dụng để kiểm tra các liên kết siêu văn bản về tính hợp lệ, khả năng truy cập và sửa đổi gần đây.

Đối với tôi, dường như câu trả lời chính xác cho câu hỏi của người yêu cầu là nó phụ thuộc vào những gì được biểu thị bởi giao thức REST. Ví dụ, trong trường hợp cụ thể của tôi, giao thức REST của tôi được sử dụng để truy xuất hình ảnh khá lớn (như hơn 10K). Nếu tôi có một số lượng lớn các tài nguyên như vậy được kiểm tra liên tục và cho rằng tôi sử dụng các tiêu đề yêu cầu, thì việc sử dụng yêu cầu HEAD sẽ rất hợp lý, theo khuyến nghị của w3.org.


14

Tôi thực sự không khuyến khích kiểu tiếp cận này.

Một dịch vụ RESTful phải tôn trọng ngữ nghĩa của động từ HTTP. Động từ GET có nghĩa là truy xuất nội dung của tài nguyên, trong khi động từ HEAD sẽ không trả về bất kỳ nội dung nào và có thể được sử dụng, chẳng hạn, để xem liệu tài nguyên có thay đổi hay không, để biết kích thước hoặc loại của nó, để kiểm tra xem nó có tồn tại, và như vậy.

Và hãy nhớ rằng: tối ưu hóa sớm là gốc rễ của mọi điều xấu.


8

Hiệu suất của bạn sẽ hầu như không thay đổi bằng cách sử dụng yêu cầu HEAD thay vì yêu cầu GET.

Hơn nữa, khi bạn muốn nó là REST-ful và bạn muốn NHẬN dữ liệu, bạn nên sử dụng yêu cầu GET thay vì yêu cầu HEAD.


8

GET tìm nạp đầu + nội dung, HEAD chỉ tìm nạp đầu. Nó không phải là một vấn đề quan điểm mà cái nào nhanh hơn. Tôi không phủ nhận các câu trả lời được ủng hộ ở trên. Nếu bạn đang tìm kiếm thông tin META thay vì tìm HEAD, điều này có nghĩa là cho mục đích này.


3

Tôi không hiểu mối quan tâm của bạn về 'luồng cơ thể đang mở / đóng'. Nội dung phản hồi sẽ ở trên cùng một luồng với tiêu đề phản hồi http và sẽ KHÔNG tạo kết nối thứ hai (nhân tiện, kết nối này nhiều hơn trong phạm vi 3-6ms).

Điều này có vẻ giống như một nỗ lực tối ưu hóa rất trước khi trưởng thành về một thứ gì đó sẽ không tạo ra sự khác biệt đáng kể hoặc thậm chí có thể đo lường được. Sự khác biệt thực sự là sự phù hợp với REST nói chung, khuyến nghị sử dụng GET để lấy dữ liệu ..

Câu trả lời của tôi là KHÔNG, hãy sử dụng GET nếu thấy hợp lý, không có hiệu suất tăng khi sử dụng HEAD.


Giả sử nội dung là 100MB. Chắc chắn đầu sẽ ít hơn nội dung về kích thước. Bây giờ khi chúng tôi yêu cầu tài nguyên đó theo phương thức GET hoặc HEAD, theo ý kiến ​​của bạn, không có sự khác biệt về hiệu suất giữa chúng ?!
Mohammad Afrashteh

3
OP đã nêu 250 ký tự trong phần nội dung của câu trả lời. Không phải 100MB. Đó hoàn toàn là một câu hỏi khác.
smassey

1

Yêu cầu HEAD cũng giống như yêu cầu GET , ngoại trừ phần nội dung của phản hồi trống. Loại yêu cầu này có thể được sử dụng khi tất cả những gì bạn muốn là siêu dữ liệu về tệp nhưng không cần phải vận chuyển tất cả dữ liệu của tệp.


-1

Bạn có thể dễ dàng thực hiện một bài kiểm tra nhỏ để tự mình đo lường hiệu suất. Tôi nghĩ rằng sự khác biệt về hiệu suất sẽ không thể bỏ qua, bởi vì nếu bạn chỉ trả về 'Y' hoặc 'N' trong nội dung, thì đó là một byte bổ sung duy nhất được thêm vào một luồng đã mở.

Tôi cũng muốn sử dụng GET vì nó đúng hơn. Bạn không phải trả lại nội dung trong tiêu đề HTTP, chỉ siêu dữ liệu.


NHẬN - nó không chỉ bí ẩn "một byte thừa". Chỉ toàn bộ cơ thể! Trong trường hợp tài liệu lớn, nó có thể là một số megabyte.
porfirion
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.