paint-brush
Giải mã Quế—Phương pháp tiếp cận khả năng phục hồi mới tại Ubertừ tác giả@bmarquie

Giải mã Quế—Phương pháp tiếp cận khả năng phục hồi mới tại Uber

từ tác giả Bruno Marquié10m2024/01/22
Read on Terminal Reader

dài quá đọc không nổi

Bạn muốn khám phá cách Uber xác định lại khả năng phục hồi trong kiến trúc dịch vụ vi mô của họ bằng cách dựa trên các khái niệm hàng thế kỷ? Chúng ta hãy cùng nhau khám phá các yếu tố nền tảng để hiểu rõ hơn về các vấn đề hiện tại.
featured image - Giải mã Quế—Phương pháp tiếp cận khả năng phục hồi mới tại Uber
Bruno Marquié HackerNoon profile picture
0-item
1-item



Năm ngoái, nhóm Kỹ thuật Uber đã xuất bản một bài viết về cơ chế giảm tải mới được thiết kế cho kiến trúc vi dịch vụ của họ.


Bài viết này rất thú vị từ nhiều góc độ khác nhau. Vì vậy, tôi đã ghi lại một số ghi chú khi đọc nó để nắm bắt sự hiểu biết của mình và viết ra những điều mà tôi muốn tìm hiểu sâu hơn sau này nếu cuối cùng tôi không nhận được câu trả lời. Tôi đã nhiều lần nhận thấy rằng đây là cách tốt nhất để tôi học những điều mới.


Điều thu hút tôi ngay từ đầu là việc tham khảo các nguyên tắc hàng thế kỷ được sử dụng để xây dựng giải pháp này. Đó là điều tôi yêu thích - mượn các khái niệm/ý tưởng từ các lĩnh vực khác nhau và điều chỉnh chúng để giải quyết vấn đề ở một lĩnh vực khác.


Nếu bạn quan tâm đến khả năng phục hồi và ổn định của hệ thống, tôi khuyên bạn cũng nên đọc cuốn sách xuất sắc 'Giải phóng nó!' của Michael T. Nygard.


Đó là một cuốn sách cũ nhưng hay - một cuốn sách đi sâu vào các chiến lược, mô hình và hướng dẫn thực tế để xây dựng các hệ thống phần mềm ổn định và linh hoạt, nhấn mạnh cách xử lý lỗi một cách hiệu quả.




Uber đã triển khai giải pháp giảm tải mới có tên Cinnamon, tận dụng bộ điều khiển PID (cơ chế có từ hàng thế kỷ trước) để quyết định những yêu cầu nào sẽ được dịch vụ xử lý hoặc loại bỏ dựa trên tải hiện tại của dịch vụ và mức độ ưu tiên của yêu cầu.


Nó không liên quan đến bất kỳ điều chỉnh nào ở cấp độ dịch vụ (mặc dù tôi có câu hỏi về điều đó), có khả năng tự động thích ứng và hiệu quả hơn nhiều so với giải pháp QALM trước đây của họ. Cũng hãy nhớ rằng kiến trúc vi dịch vụ của Uber không dành cho người yếu tim…



Sơ đồ về cách Cinnamon phù hợp với mạng lưới dịch vụ tại Uber. (từ bài báo Uber đã đề cập trước đó).




Bộ điều khiển PID nổi tiếng này là gì và nó được sử dụng như thế nào?


Bộ điều khiển PID là một công cụ được sử dụng trong các ứng dụng điều khiển công nghiệp để điều chỉnh nhiệt độ, lưu lượng, áp suất, tốc độ và các biến quy trình khác. Bộ điều khiển PID (đạo hàm tích phân tỷ lệ) sử dụng cơ chế phản hồi vòng điều khiển để điều khiển các biến của quá trình và là bộ điều khiển ổn định và chính xác nhất.

- https://www.omega.co.uk/prodinfo/pid-controllers.html


Nếu bạn muốn biết thêm thông tin về khái niệm hàng thế kỷ này, hãy truy cập Wikipedia.


Bây giờ, quay lại bài viết. PID là viết tắt của Tỷ lệ, tích phân và đạo hàm. Trong trường hợp của họ, họ sử dụng một thành phần được gọi là bộ điều khiển PID để theo dõi tình trạng của dịch vụ (yêu cầu đầu vào) dựa trên ba thành phần (hoặc thước đo).

Tỷ lệ thuận

Thuật ngữ “tỷ lệ” chỉ ra rằng hành động được thực hiện tỷ lệ thuận với lỗi hiện tại. Nói một cách đơn giản, điều này có nghĩa là hiệu chỉnh được áp dụng tỷ lệ thuận với sự khác biệt giữa trạng thái mong muốn và trạng thái thực tế. Nếu lỗi lớn thì hành động khắc phục cũng lớn tương ứng.


Khi điểm cuối bị quá tải, goroutine nền sẽ bắt đầu giám sát luồng yêu cầu vào và ra khỏi hàng đợi ưu tiên.


Vì vậy, thành phần Tỷ lệ (P) trong bộ đổ tải sẽ điều chỉnh tốc độ loại bỏ dựa trên khoảng cách từ kích thước hàng đợi hiện tại đến kích thước hàng đợi mục tiêu hoặc mong muốn. Nếu hàng đợi lớn hơn mong muốn thì xảy ra hiện tượng đổ hàng nhiều hơn; nếu nó nhỏ hơn thì độ rụng sẽ giảm.


Đó là sự hiểu biết của tôi về nó.

tích phân

Công việc của bộ điều khiển PID là giảm thiểu số lượng yêu cầu xếp hàng đợi, trong khi công việc của bộ điều chỉnh tự động là tối đa hóa thông lượng của dịch vụ mà không làm giảm độ trễ phản hồi (quá nhiều).


Mặc dù văn bản không đề cập rõ ràng “Tích phân (I)” trong bối cảnh kích thước hàng đợi, nhưng nó chỉ ra rằng vai trò của bộ điều khiển PID là giảm thiểu số lượng yêu cầu được xếp hàng đợi. Việc giảm thiểu các yêu cầu được xếp hàng đợi phù hợp với mục tiêu của thành phần Tích hợp là giải quyết các lỗi tích lũy theo thời gian.


Để xác định xem điểm cuối có bị quá tải hay không, chúng tôi theo dõi lần cuối cùng hàng đợi yêu cầu trống và nếu nó không được làm trống trong 10 giây cuối cùng, chúng tôi coi điểm cuối bị quá tải (lấy cảm hứng từ Facebook).


Trong trình giảm tải, nó có thể được liên kết với các quyết định liên quan đến hành vi lịch sử của hàng đợi yêu cầu, chẳng hạn như thời gian kể từ lần cuối cùng nó trống.


Thành thật mà nói, điều đó không hoàn toàn rõ ràng với tôi. Phải nói là có một chút bực bội. Mặc dù họ đề cập đến việc tận dụng một cơ chế có từ hàng thế kỷ trước, nhưng sẽ rất hữu ích nếu họ tuyên bố rõ ràng bộ phận nào tương ứng với cái gì hoặc cách nó vận hành. Tôi không muốn làm giảm giá trị bài viết tuyệt vời của họ. Đó chỉ là lời nói của tôi ở đây… Suy cho cùng, tôi là người Pháp…;)

Phát sinh

Tôi nghĩ cái này dễ xác định hơn.


Trong bộ điều khiển PID (Tỷ lệ-Tích phân-Đạo hàm) cổ điển, hành động “Đạo hàm (D)” đặc biệt hữu ích khi bạn muốn bộ điều khiển dự đoán hành vi trong tương lai của hệ thống dựa trên tốc độ thay đổi lỗi hiện tại. Nó giúp làm giảm dao động và cải thiện tính ổn định của hệ thống.


Trong bối cảnh của bộ giảm tải và bộ điều khiển PID được đề cập trong bài viết, thành phần phái sinh có thể được sử dụng để đánh giá tốc độ lấp đầy hàng đợi yêu cầu. Bằng cách đó, nó hỗ trợ đưa ra các quyết định nhằm duy trì một hệ thống ổn định và ngăn chặn những thay đổi đột ngột hoặc không thể đoán trước.


Thành phần từ chối có hai trách nhiệm: a) tìm hiểu xem điểm cuối có bị quá tải hay không và b), nếu điểm cuối bị quá tải, hãy loại bỏ một tỷ lệ phần trăm yêu cầu để đảm bảo hàng đợi yêu cầu càng nhỏ càng tốt. Khi điểm cuối bị quá tải, goroutine nền sẽ bắt đầu giám sát luồng yêu cầu vào và ra khỏi hàng đợi ưu tiên. Dựa trên những con số này, nó sử dụng bộ điều khiển PID để xác định tỷ lệ yêu cầu được loại bỏ. Bộ điều khiển PID rất nhanh (vì cần rất ít lần lặp) trong việc tìm mức chính xác và khi hàng đợi yêu cầu đã hết, PID đảm bảo rằng chúng tôi chỉ giảm tỷ lệ từ từ.


Trong ngữ cảnh đã đề cập, bộ điều khiển PID được sử dụng để xác định tỷ lệ yêu cầu bị loại bỏ khi điểm cuối bị quá tải, đồng thời nó giám sát luồng yêu cầu vào và ra. Thành phần phái sinh của bộ điều khiển PID, đáp ứng tốc độ thay đổi, có liên quan ngầm đến việc đánh giá tốc độ lấp đầy hoặc tiêu hao hàng đợi yêu cầu. Điều này giúp đưa ra các quyết định năng động để duy trì sự ổn định của hệ thống.



Cả thành phần Tích phân và Đạo hàm đều tham gia vào việc giám sát hành vi của hàng đợi yêu cầu theo thời gian

  • Phần không thể thiếu


Trong bối cảnh xác định tình trạng quá tải, thành phần tích phân có thể liên quan đến việc theo dõi thời gian hàng đợi yêu cầu ở trạng thái không trống. Điều này phù hợp với ý tưởng tích lũy tích phân của tín hiệu lỗi theo thời gian.

“Tích hợp - dựa trên thời gian yêu cầu đã ở trong hàng đợi…”


  • Thành phần phái sinh


Mặt khác, thành phần phái sinh có liên quan đến tốc độ thay đổi. Nó phản hồi trạng thái của hàng đợi yêu cầu thay đổi nhanh như thế nào.


“Phái sinh — từ chối dựa trên tốc độ lấp đầy hàng đợi…”


Mặc dù cả khía cạnh Tích phân và Đạo hàm đều liên quan đến việc quan sát hàng đợi yêu cầu, nhưng chúng tập trung vào các khía cạnh khác nhau trong hành vi của nó

Thành phần Tích phân nhấn mạnh khoảng thời gian của trạng thái không trống, trong khi thành phần Phái sinh xem xét tốc độ thay đổi của hàng đợi.


Khi kết thúc trò chơi, họ sử dụng ba biện pháp này để xác định quá trình hành động cho một yêu cầu.


Câu hỏi của tôi là làm thế nào họ kết hợp được ba thành phần này, nếu có. Tôi tò mò muốn hiểu cách họ giám sát chúng.


Tuy nhiên, tôi nghĩ tôi đã có ý tưởng…


Họ quyết định gác lại yêu cầu nào tùy thuộc vào 3 thành phần này và bằng cách nào?

Điểm cuối ở cạnh được chú thích với mức độ ưu tiên của yêu cầu và điều này được truyền từ cạnh đến tất cả các phần phụ thuộc phía dưới thông qua Jaeger . Bằng cách truyền bá thông tin này, tất cả các dịch vụ trong chuỗi yêu cầu sẽ biết tầm quan trọng của yêu cầu và mức độ quan trọng của nó đối với người dùng của chúng tôi.


Ý nghĩ đầu tiên xuất hiện trong đầu là nó sẽ tích hợp liền mạch vào kiến trúc lưới dịch vụ.


Tôi đánh giá cao khái niệm sử dụng tiêu đề và theo dõi dịch vụ phân tán để truyền bá mức độ ưu tiên của yêu cầu. Do đó, tại sao lại chọn thư viện dùng chung với phần phụ thuộc này được thêm vào mỗi vi dịch vụ, thay vì đặt nó bên ngoài dịch vụ, có lẽ dưới dạng plugin Istio? Xem xét các lợi ích mà nó mang lại: chu kỳ phát hành/triển khai độc lập, hỗ trợ đa ngôn ngữ, v.v.


Dưới đây là một số suy nghĩ bổ sung:


  • Có khả năng rằng, theo thời gian, mức độ ưu tiên của yêu cầu có thể giảm bớt hoặc thay đổi dựa trên những thay đổi theo ngữ cảnh, chẳng hạn như việc bắt đầu một quy trình hoặc nhiệm vụ hàng loạt có mức độ ưu tiên cao ngoài kế hoạch hoặc những thay đổi ở cấp độ múi giờ/khu vực?


  • Cách tiếp cận này diễn ra như thế nào với các phương pháp/mô hình quản lý khả năng phục hồi 'tiêu chuẩn' khác, chẳng hạn như bộ ngắt mạch, thời gian chờ, cho thuê, vách ngăn, v.v.?


  • Tôi muốn hiểu mức độ mà một dịch vụ quyết định (sở hữu quyết định) loại bỏ các yêu cầu dựa trên mức độ ưu tiên của yêu cầu đầu vào. Họ đề cập đến việc thiếu cấu hình (một khía cạnh tôi muốn khám phá thêm), vì vậy nó không dành riêng cho dịch vụ và hoàn toàn độc lập với việc triển khai dịch vụ, khá minh bạch. Điều này mang lại quan điểm về lưới dịch vụ/chu kỳ phát hành độc lập so với thư viện phụ thuộc.


Chà, tôi thiên vị, vì tôi không phải là người yêu thích các thư viện dùng chung, nếu chỉ vì tôi nghĩ chúng làm phức tạp quá trình phát hành/triển khai. Tuy nhiên, tôi không chắc liệu có khía cạnh cấu hình dành riêng cho dịch vụ nào cần xem xét hay không. Có lẽ họ định cấu hình dịch vụ sẽ đợi bao lâu để bắt đầu xử lý một truy vấn và hoàn thành nó?


Sơ đồ cho thấy cách một yêu cầu đi qua Cinnamon trước khi được gửi đến logic nghiệp vụ để xử lý thực tế. (từ bài báo Uber đã đề cập trước đó).


Có lẽ một khía cạnh đáng để thử nghiệm là quá trình ra quyết định của máy phun.


Theo những gì tôi hiểu, nó xác định xem có từ chối yêu cầu hay không dựa trên bộ điều khiển PID, được bản địa hóa cho dịch vụ. Có lựa chọn nào cho cách tiếp cận toàn cầu hơn không? Ví dụ: nếu biết rằng một trong các dịch vụ hạ nguồn trong đường dẫn bị quá tải (do bộ điều khiển PID của chính nó), thì bất kỳ dịch vụ ngược dòng nào cũng có thể quyết định từ chối yêu cầu trước khi đến dịch vụ quá tải này (có thể là n bước nữa con đường)?


Quyết định này có thể dựa trên giá trị được trả về bởi bộ điều khiển PID hoặc bộ điều chỉnh tự động của dịch vụ xuôi dòng.



Bây giờ, tôi đang suy nghĩ về nhiều khía cạnh khác nhau được đề cập khi họ kết thúc bài viết và cung cấp một số con số để thể hiện tính hiệu quả của hệ thống của họ, điều này khá ấn tượng.


Độ trễ P50 dành cho mức độ ưu tiên cao, cấp 1, yêu cầu ba thiết lập ở các RPS gửi đến khác nhau. (từ bài báo Uber đã đề cập trước đó).


Tại một số thời điểm, họ đề cập rằng 'Mỗi yêu cầu có thời gian chờ là 1 giây.'


Chúng tôi chạy thử nghiệm trong 5 phút, trong đó chúng tôi gửi một lượng RPS cố định (ví dụ: 1.000), trong đó 50% lưu lượng truy cập là cấp 1 và 50% là cấp 5. Mỗi yêu cầu có thời gian chờ là 1 giây.


Thông thường trong các hệ thống phân tán, việc liên kết một yêu cầu với thời gian hết hạn hoặc thời hạn cụ thể là điều phổ biến, với mỗi dịch vụ dọc theo đường dẫn xử lý chịu trách nhiệm thực thi giới hạn thời gian này. Nếu hết thời gian trước khi yêu cầu được hoàn thành, mọi dịch vụ trong chuỗi đều có tùy chọn hủy bỏ hoặc từ chối yêu cầu.


Tôi cho rằng thời gian chờ 1 giây này được đính kèm với yêu cầu và mỗi dịch vụ, tùy thuộc vào vị trí của chúng tôi trong thời hạn này, có thể quyết định hủy yêu cầu. Đây là thước đo mang tính toàn cầu vì nó được tổng hợp thông qua các dịch vụ. Tôi nghĩ nó phù hợp với quan điểm tôi đã đưa ra trước đó về việc có cái nhìn toàn cầu về tình trạng hoặc sự phụ thuộc của toàn bộ hệ thống để quyết định hủy yêu cầu càng sớm càng tốt nếu yêu cầu đó không có cơ hội hoàn thành do một trong các dịch vụ phía dưới con đường.


Liệu 'tình trạng' của các dịch vụ hạ nguồn (bao gồm dữ liệu từ bộ điều khiển PID cục bộ của chúng) có thể được trả về dưới dạng tiêu đề gắn liền với các phản hồi và được sử dụng để xây dựng cơ chế ngắt mạch/cắt bỏ ưu tiên sớm phát triển hơn không?




Cuối cùng, tôi tò mò muốn tìm hiểu thêm về cách tiếp cận trước đó vì dựa trên mô tả được đưa ra trong bài viết này, nó có vẻ hợp lý.


Khi bạn kiểm tra các thước đo về hiệu suất tốt và độ trễ, chắc chắn cái nào, QALM hay Cinnamon, hoạt động tốt nhất. Lưu ý rằng họ đề cập đến liên kết đến phương pháp QALM trong bài viết. Có lẽ nên bắt đầu từ đó ;)


Như mọi khi, những cách tiếp cận này không dành cho tất cả mọi người. Kiến trúc và tải trọng của Uber là của riêng nó. Tôi thực sự nóng lòng muốn đọc các bài tiếp theo trong loạt bài này, đặc biệt là để tìm hiểu thêm về bộ điều khiển PID và bộ điều chỉnh tự động.


Với Cinnamon, chúng tôi đã xây dựng một công cụ giảm tải hiệu quả sử dụng các kỹ thuật có từ thế kỷ trước để tự động đặt ngưỡng từ chối và ước tính công suất của dịch vụ. Nó giải quyết các vấn đề mà chúng tôi nhận thấy với QALM (và do đó, bất kỳ trình giảm tải dựa trên CoDel nào), cụ thể là Cinnamon có thể:


- Nhanh chóng tìm được tỷ lệ từ chối ổn định


- Tự động điều chỉnh công suất dịch vụ


- Sử dụng không cần cài đặt bất kỳ thông số cấu hình nào


- Chi phí phát sinh rất thấp


Điều thú vị về cách tiếp cận này là họ xem xét tất cả các yêu cầu cần xử lý để quyết định phải làm gì đối với mỗi yêu cầu đầu vào mới vì họ sử dụng hàng đợi (ưu tiên). Như đã đề cập, tôi tò mò liệu cơ chế này có thể tính đến tình trạng của tất cả các dịch vụ phụ thuộc dựa trên cùng các biện pháp PID hay không…


Có những khía cạnh thú vị khác trong bài viết này, chẳng hạn như cách họ đo lường hiệu quả của chiến lược và so sánh với phương pháp trước đó. Tuy nhiên, nó không yêu cầu tôi ghi chú chi tiết hơn những gì đã được trình bày. Vì vậy, tôi rất khuyến khích bạn đọc bài viết gốc .



Tìm thấy bài viết này hữu ích? Theo dõi tôi trên Linkedin , Hackernoon Medium ! Hãy 👏 bài viết này để chia sẻ nó nhé!


Cũng được xuất bản ở đây.