Trong những điều kiện (nếu có), có tốt không khi truy vấn hai máy chủ và chỉ tiêu thụ phản hồi nhanh nhất?


12

Tôi đã hỏi những gì bây giờ là một câu hỏi bị xóa bởi Cộng đồng về SO về lý do tại sao một người nào đó sẽ sử dụng javascript Promise.racevà một người dùng đại diện cao đã nhận xét điều này:

Nếu bạn có hai dịch vụ tính toán một số giá trị, bạn có thể truy vấn cả hai song song và sử dụng giá trị nào được trả về trước, thay vì truy vấn một, chờ một lỗi, sau đó truy vấn thứ hai.

Tôi đã nói về sự dư thừa và trường hợp sử dụng này nói chung nhưng tôi không thể tìm thấy bất cứ điều gì và, từ POV của tôi, không bao giờ nên thêm khối lượng công việc vào máy chủ / dịch vụ nếu bạn không sử dụng phản hồi.


Ví dụ về đồ chơi: thay vì luôn luôn sử dụng quicksort, bạn sao chép dữ liệu, gửi nó đến quicksort, và sáp nhập, và heapsort, ... vv Bạn không phải kiểm tra đầu vào để xem đó có phải là trường hợp bệnh lý không đối với bất kỳ ai trong số đó, vì đó sẽ không phải là trường hợp bệnh lý cho tất cả bọn họ
Caleth

Bài báo của Dean và Barroso The Tail at Scale gọi một biến thể của phương pháp này là "Yêu cầu được bảo vệ". Nó cũng thảo luận về những ưu và nhược điểm của một số phương pháp liên quan để kiểm soát sự biến đổi đuôi dài về tỷ lệ lỗi và độ trễ.
Daniel Pryden

"Yêu cầu máy chủ" thứ hai có thể là giả mạo. Nó chỉ có thể muốn trong 5 giây và sau đó trả lại phản hồi giữ chỗ. Điều đó giúp bạn có một thời gian chờ theo yêu cầu thực sự.
dùng253751

Đặt một Lyft và sau đó đặt một Uber. Đi cái nào đến trước.
2023861

@ user2023861 trong sự tương tự này, trong khi một tài xế lái xe vô tư hướng tới vị trí của bạn, anh ấy / cô ấy có thể đã thực hiện một yêu cầu khác thay thế
Adelin

Câu trả lời:


11

Tôi sẽ tranh luận rằng đây là một câu hỏi kinh tế nhiều hơn. Tuy nhiên, đó là một lời kêu gọi phán xét mà các kỹ sư phải có thể làm được. Do đó, tôi đang trả lời.

Tôi chia câu trả lời của tôi thành bốn phần:

  • Quản lý rủi ro
  • Chiến lược
  • Chi phí
  • Trực giác

Quản lý rủi ro

Vì vậy, đôi khi khách hàng của bạn không nhận được phản hồi từ máy chủ. Tôi sẽ cho rằng đây không phải là do lỗi lập trình (nếu không thì giải pháp là sửa nó, vì vậy hãy làm điều đó). Thay vào đó, đó phải là vì một tình huống tình cờ nằm ​​ngoài tầm kiểm soát của bạn ...

Nhưng không vượt quá kiến ​​thức của bạn. Ban phai biet:

  • Làm thế nào thường xảy ra.
  • Nó có tác động gì.

Ví dụ, nếu thất bại và thử lại chỉ xảy ra khoảng 2% thời gian, có lẽ không đáng để giải quyết nó. Nếu nó xảy ra khoảng 80% thời gian, thì ... phụ thuộc ...

Khách hàng phải đợi bao nhiêu thời gian? Và làm thế nào để chuyển thành chi phí ... bạn thấy đấy, bạn có một độ trễ nhỏ trong một ứng dụng thông thường, nó có thể không phải là một vấn đề lớn. Nếu nó quan trọng và bạn có một ứng dụng thời gian thực hoặc một trò chơi video trực tuyến, điều này sẽ khiến người dùng bỏ đi và có lẽ bạn nên đầu tư vào nhiều máy chủ hơn hoặc tốt hơn. Nếu không, bạn có thể đặt thông báo "đang tải" hoặc "đang chờ máy chủ". Trừ khi, độ trễ thực sự lớn (theo thứ tự hàng chục giây), thì nó có thể là quá nhiều ngay cả đối với ứng dụng thông thường.


Chiến lược

Như tôi đã nói ở trên, có nhiều hơn một cách để giải quyết vấn đề này. Tôi sẽ giả sử bạn đã thực hiện vòng lặp try-fail-retry. Vì vậy, hãy cho chúng tôi xem ...

  • Đặt một tin nhắn đang tải. Đó là giá rẻ, giúp giữ chân người dùng.
  • Truy vấn song song. Có thể nhanh hơn, vẫn có thể thất bại. Sẽ yêu cầu một máy chủ dự phòng (có thể tốn kém), sẽ lãng phí thời gian của máy chủ và lưu lượng mạng.
  • Truy vấn song song để thiết lập máy chủ nhanh hơn và sử dụng từ đó trở đi. Có thể nhanh hơn, vẫn có thể thất bại. Sẽ yêu cầu máy chủ dự phòng (có thể tốn kém), sẽ không lãng phí nhiều thời gian của máy chủ và lưu lượng mạng.

Bây giờ, thông báo tôi nói những điều này vẫn có thể thất bại. Nếu chúng tôi cho rằng một truy vấn đến máy chủ có 80% khả năng thất bại, thì truy vấn song song tới hai máy chủ có khả năng thất bại 64%. Vì vậy, bạn vẫn có thể phải thử lại.

Một lợi thế của việc chọn máy chủ nhanh hơn và tiếp tục sử dụng nó, đó là máy chủ nhanh hơn cũng ít có khả năng bị lỗi do sự cố mạng.

Điều này nhắc nhở tôi, nếu bạn có thể tìm ra lý do tại sao yêu cầu thất bại, hãy làm như vậy. Nó có thể giúp bạn quản lý tình huống tốt hơn, ngay cả khi bạn không thể ngăn chặn những thất bại. Ví dụ, bạn có cần thêm tốc độ truyền ở phía máy chủ không?

Một số chi tiết:

  • Triển khai nhiều máy chủ trên toàn thế giới và chọn máy chủ theo vị trí địa lý.
  • Cân bằng tải ở phía máy chủ (một máy chuyên dụng sẽ thực hiện tất cả các yêu cầu và gửi chúng đến máy chủ của bạn, bạn có thể có sự song song của mình ở đó hoặc chiến lược cân bằng tốt hơn).

Và ai nói bạn chỉ phải làm một trong số này? Bạn có thể đặt một thông báo tải, truy vấn nhiều máy chủ được trải đều để chọn nhanh hơn và chỉ sử dụng thông báo đó từ đó, khi thử lại trên một vòng lặp và mỗi máy chủ đó là một cụm máy có cân bằng tải . Tại sao không? Chà, chi phí ...


Chi phí

Có bốn chi phí:

  • Chi phí phát triển (thường rất rẻ)
  • Chi phí triển khai (thường cao)
  • Thời gian chạy chi phí (phụ thuộc vào loại ứng dụng và mô hình kinh doanh)
  • Chi phí thất bại (có thể thấp, nhưng không phải về mặt phân tích)

Bạn phải cân bằng chúng.

Chẳng hạn, hãy để chúng tôi nói rằng bạn kiếm được khoảng một đô la cho mỗi người dùng hài lòng. Bạn có 3000 người dùng mỗi ngày. Rằng các yêu cầu thất bại khoảng 50% thời gian. Và 2% người dùng đó rời đi mà không trả tiền khi yêu cầu thất bại. Điều này có nghĩa là bạn đang mất (3000 * 50% * 2%) 30 đô la mỗi ngày. Bây giờ, hãy để chúng tôi nói rằng việc phát triển tính năng mới sẽ tiêu tốn của bạn 100 đô la và việc triển khai các máy chủ sẽ tiêu tốn của bạn 800 đô la - và bỏ qua chi phí thời gian chạy - điều này có nghĩa là bạn sẽ có khoản hoàn vốn đầu tư vào ((100 + 800) / 30 ) 30 ngày. Bây giờ, bạn có thể kiểm tra ngân sách của bạn và quyết định.

Đừng coi những giá trị này là đại diện cho thực tế, tôi đã chọn chúng cho sự đồng thuận toán học.

Phụ lục:

  • Hãy nhớ rằng tôi cũng đang bỏ qua các chi tiết. Ví dụ, bạn có thể có ít chi phí triển khai nhưng phải trả tiền cho thời gian CPU và bạn cần xem xét điều đó.
  • Một số khách hàng có thể đánh giá cao nếu bạn không lãng phí gói dữ liệu của họ trong các yêu cầu dư thừa.
  • Cải thiện sản phẩm của bạn có thể giúp mang lại quảng cáo tự nhiên.
  • Đừng quên chi phí cơ hội. Bạn có nên phát triển một cái gì đó khác?

Vấn đề là, nếu bạn xem xét vấn đề về mặt cân bằng chi phí, bạn có thể ước tính chi phí cho các chiến lược bạn xem xét và sử dụng phân tích này để quyết định.


Trực giác

Trực giác nếu nuôi dưỡng bằng kinh nghiệm. Tôi không đề nghị làm loại phân tích này mỗi lần. Một số người làm, và đó là ok. Tôi đề nghị bạn nên có một số hiểu biết về điều này, và phát triển một trực giác cho nó.

Hơn nữa, trong kỹ thuật, ngoài kiến ​​thức chúng ta có được từ khoa học thực tế, chúng ta còn học hỏi trong thực tiễn và biên soạn các hướng dẫn về những gì hoạt động và những gì không. Do đó, thường là khôn ngoan để xem trạng thái của nghệ thuật là gì ... mặc dù, đôi khi bạn cần phải nhìn thấy bên ngoài khu vực của mình.

Trong trường hợp này, tôi sẽ xem các trò chơi video trực tuyến. Họ có màn hình tải, họ có nhiều máy chủ, họ sẽ chọn một máy chủ dựa trên độ trễ và thậm chí họ có thể cho phép người dùng chuyển đổi máy chủ. Chúng tôi biết rằng hoạt động.

Tôi sẽ đề nghị làm điều đó thay vì lãng phí lưu lượng mạng và thời gian máy chủ cho mỗi yêu cầu, cũng cần lưu ý rằng ngay cả với máy chủ dự phòng, lỗi có thể xảy ra.


2
Tôi không nghĩ rằng tôi cần phải nói điều đó nhưng đây là một câu trả lời tuyệt vời :) Tôi biết tôi sẽ chấp nhận nó ở 10 dòng đầu tiên, nhưng tôi đã cho bạn cơ hội để vẫn thất bại và đọc đến cuối. Bạn đã không
Adelin

9

Điều này có thể chấp nhận được, nếu thời gian của máy khách có giá trị hơn thời gian trên máy chủ.

Nếu khách hàng cần phải nhanh chóng và chính xác. Bạn có thể biện minh cho việc truy vấn một số máy chủ. Và thật tuyệt khi hủy yêu cầu nếu nhận được câu trả lời hợp lệ.

Và tất nhiên, luôn luôn là khôn ngoan khi tham khảo ý kiến ​​chủ sở hữu / người quản lý của các máy chủ.


Tại sao bạn cần hủy yêu cầu? Chắc chắn đó là chủ quan.
JᴀʏMᴇᴇ

@ JᴀʏMᴇᴇ, Đó là xây dựng trong hoang tưởng. Tôi đã từng làm việc với một hệ thống không xóa hàng đợi của nó và nó đã bị sập khi hàng đợi đầy (Có, đó là phần mềm chuyên nghiệp).
Toon Krijthe

4

Kỹ thuật này có thể làm giảm độ trễ. Thời gian đáp ứng của máy chủ không mang tính quyết định. Ở quy mô, có khả năng sẽ có ít nhất một máy chủ hiển thị thời gian phản hồi kém. Do đó, bất cứ điều gì sử dụng máy chủ đó cũng sẽ có thời gian phản hồi kém. Bằng cách gửi tới một số máy chủ, người ta sẽ giảm thiểu rủi ro khi nói chuyện với một máy chủ hoạt động kém.

Các chi phí bao gồm buôn bán mạng bổ sung, xử lý máy chủ lãng phí và độ phức tạp của ứng dụng (nghĩ rằng điều này có thể được ẩn trong thư viện). Những chi phí này có thể được giảm bằng cách hủy các yêu cầu không sử dụng hoặc chờ một thời gian ngắn trước khi gửi yêu cầu thứ hai.

Đây là một tờ giấy , một tờ giấy khác . Tôi nhớ đọc một bài báo Google thực hiện của họ, quá.


2

Tôi hầu hết đồng ý với các câu trả lời khác, nhưng tôi nghĩ rằng điều này nên cực kỳ hiếm trong thực tế. Tôi muốn chia sẻ một ví dụ phổ biến và hợp lý hơn nhiều khi bạn sẽ sử dụng Promise.race(), một cái gì đó tôi tình cờ sử dụng nó trong vài tuần trước (tốt, tương đương với python).

Giả sử bạn có một danh sách dài các nhiệm vụ, một số nhiệm vụ có thể được chạy song song và một số nhiệm vụ phải chạy trước các nhiệm vụ khác. Bạn có thể bắt đầu tất cả các nhiệm vụ mà không phụ thuộc, sau đó chờ trong danh sách đó với Promise.race(). Ngay khi nhiệm vụ đầu tiên hoàn thành, bạn có thể bắt đầu bất kỳ nhiệm vụ nào phụ thuộc vào nhiệm vụ đầu tiên đó và Promise.race()một lần nữa trong danh sách mới kết hợp với các nhiệm vụ chưa hoàn thành từ danh sách ban đầu. Tiếp tục lặp lại cho đến khi tất cả các nhiệm vụ được thực hiện.

Lưu ý API của Javascript không được thiết kế lý tưởng cho việc này. Đó là khá ít mức tối thiểu hoạt động, và bạn phải thêm khá nhiều mã keo. Tuy nhiên, quan điểm của tôi là các chức năng như race()hiếm khi được sử dụng để dự phòng. Chúng chủ yếu ở đó khi bạn thực sự muốn kết quả từ tất cả các lời hứa, nhưng không muốn đợi tất cả chúng hoàn thành trước khi thực hiện các hành động tiếp theo.


Vấn đề là, ít nhất là với Promise.race của Javascript, bạn thực sự bắt đầu nhiệm vụ mỗi khi bạn thực hiện phương thức đua. Nó sẽ không phải là nhiệm vụ còn dang dở, nó sẽ là một nhóm nhiệm vụ mới, không liên quan đến những gì đã được chạy trước đó (trừ khi bạn thực hiện logic đó ở cấp độ nhiệm vụ). Danh sách ban đầu bị lãng quên và chỉ còn lại giá trị trả về của nhiệm vụ đầu tiên
Adelin

1
Các lời hứa trong Javascript được bắt đầu một cách háo hức, khi new Promiseđược gọi và không được khởi động lại khi Promise.race()được gọi. Một số thực hiện lời hứa là lười biếng, nhưng háo hức là phổ biến hơn nhiều. Bạn có thể kiểm tra bằng cách tạo một lời hứa trong bảng điều khiển đăng nhập vào bảng điều khiển. Bạn sẽ thấy nó đăng nhập ngay lập tức. Rồi truyền lời hứa đó cho Promise.race(). Bạn sẽ thấy nó không đăng nhập lại.
Karl Bielefeldt

À đúng rồi. Nhưng afaik giá trị trả lại của phần còn lại của các lời hứa ngoại trừ lời hứa đầu tiên bị lãng quên, với lời hứa.race
Adelin

Đó là lý do tại sao tôi nói API không được thiết kế lý tưởng. Bạn phải lưu trữ bộ nhiệm vụ ban đầu trong một biến ở đâu đó.
Karl Bielefeldt

1

Ngoài những cân nhắc kỹ thuật, bạn có thể muốn sử dụng phương pháp này khi nó là một phần của mô hình kinh doanh thực tế của bạn.

Biến thể về cách tiếp cận này là tương đối phổ biến trong đặt giá thầu thời gian thực trên quảng cáo. Trong mô hình này, nhà xuất bản (nhà cung cấp không gian quảng cáo) sẽ yêu cầu nhà quảng cáo (nhà cung cấp quảng cáo) đặt giá thầu trên một lần hiển thị bởi một người dùng cụ thể. Vì vậy, với mỗi lần hiển thị như vậy, bạn sẽ truy vấn từng nhà quảng cáo đã đăng ký, gửi truy vấn có chi tiết hiển thị đến điểm cuối được cung cấp bởi mỗi nhà quảng cáo (hoặc cách khác, tập lệnh do nhà quảng cáo cung cấp chạy như điểm cuối trên máy chủ của bạn), đua tất cả các yêu cầu này lên đến thời gian chờ (ví dụ 100ms) và sau đó nhận giá thầu cao nhất, bỏ qua các yêu cầu khác.

Một biến thể cụ thể của điều này giúp giảm thời gian chờ đợi của khách hàng là nhà xuất bản cho phép giá trị mục tiêu tối thiểu cho giá thầu, sao cho giá thầu của nhà quảng cáo đầu tiên vượt qua giá trị đó sẽ được chấp nhận ngay lập tức (hoặc, nếu không có giá thầu nào vượt quá giá trị, tối đa sẽ được thực hiện). Vì vậy, trong biến thể này, truy vấn đến đầu tiên có thể thắng và loại khác bị loại bỏ, ngay cả khi chúng tốt hoặc thậm chí tốt hơn.

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.