paint-brush
Tarçın Paketini Açmak—Uber'de Yeni Bir Dayanıklılık Yaklaşımıile@bmarquie

Tarçın Paketini Açmak—Uber'de Yeni Bir Dayanıklılık Yaklaşımı

ile Bruno Marquié10m2024/01/22
Read on Terminal Reader

Çok uzun; Okumak

Uber'in yüzlerce yıllık kavramlardan yararlanarak mikro hizmet mimarisinde esnekliği nasıl yeniden tanımladığını keşfetmeye istekli misiniz? Eldeki sorunları daha iyi anlamak için temel unsurları birlikte inceleyelim.
featured image - Tarçın Paketini Açmak—Uber'de Yeni Bir Dayanıklılık Yaklaşımı
Bruno Marquié HackerNoon profile picture
0-item
1-item



Geçen yıl Uber Mühendislik ekibi, mikro hizmet mimarileri için tasarlanan yeni yük azaltma mekanizmaları hakkında bir makale yayınladı .


Bu makale çeşitli açılardan çok ilginç. Bu yüzden, anladığımı yakalamak ve sonunda cevapları alamazsam daha sonra daha derinlemesine incelemek istediğim şeyleri yazmak için okurken bazı notlar aldım. Bunun benim için yeni şeyler öğrenmenin en iyi yolu olduğunu defalarca keşfettim.


Beni en başından beri etkileyen şey, bu çözümü oluşturmak için kullanılan asırlık ilkelere yapılan referanstı. Bu sevdiğim bir şey; farklı alanlardan kavramları/fikirleri ödünç almak ve bunları farklı bir alandaki bir sorunu çözmek için uyarlamak.


Sistem dayanıklılığı ve kararlılığı ilginizi çekiyorsa, 'Release It!' adlı mükemmel kitabı da okumanızı tavsiye ederim. Michael T. Nygard tarafından.


Eski ama güzel bir kitap; dayanıklı ve istikrarlı yazılım sistemleri oluşturmak için stratejiler, modeller ve pratik rehberlik sunan, arızaların etkili bir şekilde nasıl ele alınacağını vurgulayan bir kitap.




Uber, hizmetin mevcut yüküne ve istek önceliğine bağlı olarak hangi isteklerin bir hizmet tarafından işlenmesi veya atılması gerektiğine karar vermek için PID denetleyicisinden (asırlık mekanizma) yararlanan Cinnamon adlı yeni bir yük azaltma çözümünü uygulamaya koydu.


Hizmet seviyesinde herhangi bir ayar gerektirmiyor (gerçi bu konuda bir sorum vardı), otomatik olarak uyarlanabilir ve önceki QALM çözümlerinden çok daha verimli. Uber'in mikro hizmet mimarisinin korkaklara göre olmadığını da unutmayın…



Tarçın'ın Uber'deki hizmet ağına nasıl uyduğunu gösteren şema. (daha önce bahsedilen Uber makalesinden).




Bu ünlü PID denetleyici nedir ve nasıl kullanılır?


PID kontrol cihazı, endüstriyel kontrol uygulamalarında sıcaklığı, akışı, basıncı, hızı ve diğer proses değişkenlerini düzenlemek için kullanılan bir araçtır. PID (orantılı integral türev) kontrolörleri, süreç değişkenlerini kontrol etmek için bir kontrol döngüsü geri bildirim mekanizması kullanır ve en doğru ve kararlı kontrolörlerdir.

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


Bu asırlık kavram hakkında daha fazla bilgi edinmek istiyorsanız Wikipedia'ya gidin.


Şimdi makaleye dönelim. PID Orantılı, İntegral ve Türev anlamına gelir. Bu durumda, üç bileşene (veya ölçüme) dayalı olarak bir hizmetin (giriş istekleri) durumunu izlemek için PID denetleyicisi olarak bilinen bir bileşeni kullanırlar.

Orantılı

Orantılı terimi, yapılan eylemin mevcut hatayla orantılı olduğunu belirtir. Basit bir ifadeyle bu, uygulanan düzeltmenin istenen durum ile gerçek durum arasındaki farkla doğru orantılı olduğu anlamına gelir. Hata büyükse, düzeltici eylem orantılı olarak büyüktür.


Bir uç nokta aşırı yüklendiğinde, arka plandaki goroutine öncelik sırasına gelen isteklerin giriş ve çıkışlarını izlemeye başlar.


Böylece yük ayırıcıdaki Oransal (P) bileşen, mevcut kuyruk boyutunun hedeften veya istenen kuyruk boyutundan ne kadar uzakta olduğuna bağlı olarak atma oranını ayarlar. Kuyruk istenilenden büyükse daha fazla dökülme meydana gelir; daha küçükse dökülme azalır.


Benim bundan anladığım bu.

İntegral

PID denetleyicinin görevi sıradaki isteklerin sayısını en aza indirmekken, otomatik ayarlayıcının görevi yanıt gecikmelerinden ödün vermeden (çok fazla) hizmetin verimini en üst düzeye çıkarmaktır.


Metin, kuyruk boyutu bağlamında "İntegral (I)"den açıkça bahsetmese de, PID denetleyicisinin rolünün sıraya alınmış isteklerin sayısını en aza indirmek olduğunu belirtir. Kuyruğa alınan isteklerin en aza indirilmesi, Integral bileşeninin zaman içinde biriken hataları ele alma hedefiyle uyumludur.


Bir uç noktanın aşırı yüklenip yüklenmediğini belirlemek için, istek kuyruğunun en son ne zaman boş olduğunu takip ederiz ve eğer son 10 saniye içinde boşaltılmamışsa, uç noktanın aşırı yüklendiğini kabul ederiz (Facebook'tan esinlenerek).


Yük ayırıcıda, istek kuyruğunun son boş olmasından bu yana geçen süre gibi geçmiş davranışıyla ilgili kararlarla ilişkilendirilebilir.


Doğrusunu söylemek gerekirse bu benim için tam olarak net değil. Biraz sinir bozucu olduğunu söylemeliyim. Asırlık bir mekanizmadan bahsettikleri halde hangi parçanın neye karşılık geldiğini, nasıl çalıştığını açıkça belirtseler faydalı olurdu. Harika makalelerinin değerini azaltmak istemiyorum. Bu benim lafımdan başka bir şey değil… Sonuçta ben Fransızım… ;)

Türev

Bunu tanımlamanın daha kolay olduğunu düşünüyorum.


Klasik bir PID (Oransal-İntegral-Türev) denetleyicide, "Türev (D)" eylemi, denetleyicinin, hatanın mevcut değişim hızına dayalı olarak sistemin gelecekteki davranışını tahmin etmesini istediğinizde özellikle kullanışlıdır. Salınımları azaltmaya ve sistemin stabilitesini artırmaya yardımcı olur.


Makalede bahsedilen yük ayırıcı ve PID denetleyicisi bağlamında, Türev bileşeni muhtemelen istek kuyruğunun ne kadar hızlı dolduğunu değerlendirmek için kullanılır. Bunu yaparak, istikrarlı bir sistemi sürdürmeyi ve ani veya öngörülemeyen değişiklikleri önlemeyi amaçlayan kararların alınmasına yardımcı olur.


Reddeden bileşenin iki sorumluluğu vardır: a) bir uç noktanın aşırı yüklenip yüklenmediğini anlamak ve b) bir uç nokta aşırı yüklenmişse, istek kuyruğunun mümkün olduğu kadar küçük olduğundan emin olmak için isteklerin bir yüzdesini dağıtmak. Bir uç nokta aşırı yüklendiğinde, arka plandaki goroutine öncelik sırasına gelen isteklerin giriş ve çıkışlarını izlemeye başlar. Bu sayılara dayanarak, isteklerin dağıtılacak oranını belirlemek için bir PID denetleyicisi kullanır. PID denetleyicisi doğru seviyeyi bulmada çok hızlıdır (çok az yinelemeye ihtiyaç duyulur) ve istek kuyruğu boşaltıldıktan sonra PID, oranı yalnızca yavaşça azaltmamızı sağlar.


Bahsedilen bağlamda PID denetleyicisi, bir uç nokta aşırı yüklendiğinde isteklerin dökülme oranını belirlemek için kullanılır ve isteklerin giriş ve çıkışını izler. PID denetleyicisinin değişim hızına yanıt veren türev bileşeni, istek kuyruğunun ne kadar hızlı doldurulduğunun veya boşaltıldığının değerlendirilmesine dolaylı olarak dahil olur. Bu, sistem kararlılığını korumak için dinamik kararlar alınmasına yardımcı olur.



Hem İntegral hem de Türev bileşenleri, istek kuyruğunun zaman içindeki davranışının izlenmesinde rol oynar

  • Parçasıdır


Aşırı yüklemenin belirlenmesi bağlamında, integral bileşen, istek kuyruğunun ne kadar süreyle boş olmayan bir durumda olduğunun izlenmesiyle ilişkilendirilebilir. Bu, hata sinyalinin integralinin zaman içinde birikmesi fikriyle uyumludur.

"İntegral - isteğin kuyrukta ne kadar süre kaldığına bağlı..."


  • Türev Bileşen


Türev bileşen ise değişim oranıyla ilgilidir. İstek kuyruğunun durumunun ne kadar hızlı değiştiğine yanıt verir.


“Türev – kuyruğun ne kadar hızlı dolduğuna bağlı olarak reddetme…”


Hem İntegral hem de Türev yönleri istek kuyruğunun gözlemlenmesini içerirken, davranışının farklı yönlerine odaklanırlar.

İntegral bileşeni boş olmayan durumun süresini vurgularken Türev bileşeni kuyruğun değişme hızını dikkate alır.


Oyunun sonunda bir talebe ilişkin hareket tarzını belirlemek için bu üç önlemi kullanırlar.


Aklıma takılan soru, eğer öyleyse, bu üç bileşeni nasıl birleştirdikleridir. Onları nasıl izlediklerini de merak ediyorum.


Yine de, sanırım bir fikrim var…


Bu 3 bileşene göre hangi talebi rafa kaldırmaya karar veriyorlar ve nasıl?

Kenardaki uç noktaya isteğin önceliği eklenir ve bu, Jaeger aracılığıyla kenardan tüm aşağı akış bağımlılıklarına yayılır. Bu bilgilerin yayılmasıyla istek zincirindeki tüm hizmetler, isteğin önemini ve kullanıcılarımız için ne kadar kritik olduğunu bilecektir.


Akla gelen ilk düşünce, hizmet ağı mimarisine sorunsuz bir şekilde entegre olacağıdır.


İstek önceliğini yaymak için dağıtılmış hizmet izleme ve başlıkları kullanma kavramını takdir ediyorum. Bu doğrultuda, belki bir Istio eklentisi olarak hizmetin dışına yerleştirmek yerine, neden her bir mikro hizmete bu bağımlılığın eklendiği paylaşılan bir kitaplığı tercih etmelisiniz? Sunduğu faydalar göz önüne alındığında: bağımsız sürüm/dağıtım döngüleri, çok dilli destek vb.


İşte bazı ek düşünceler:


  • Planlanmamış yüksek öncelikli bir toplu işlemin veya görevin başlatılması veya saat dilimi/bölge düzeyindeki değişiklikler gibi bağlamsal değişikliklere bağlı olarak zaman içinde istek önceliğinin azalması veya değişmesi olasılığı var mı?


  • Bu yaklaşım, devre kesiciler, zaman aşımları, kiralamalar, bölmeler vb. gibi diğer 'standart' dayanıklılık yönetimi yaklaşımları/modelleri ile nasıl bir uyum sergiliyor?


  • Bir hizmetin, giriş isteği önceliğine dayalı olarak istekleri dağıtmaya ne ölçüde karar verdiğini (kararın sahibi olduğunu) anlamakla ilgileniyorum. Yapılandırma eksikliğinden bahsediyorlar (daha fazla araştırmak istediğim bir konu), dolayısıyla bu hizmete özgü değil ve hizmet uygulamasından tamamen bağımsız, bir nevi şeffaf. Bu, bağımlı kitaplığa karşı hizmet ağı/bağımsız sürüm döngüleri noktasını geri getirir.


Paylaşılan kitaplıkların büyük bir hayranı olmadığım için önyargılıyım, çünkü bunların yayın/dağıtım sürecini karmaşıklaştırdığını düşünüyorum. Ancak dikkate alınması gereken hizmete özgü bir yapılandırma unsuru olup olmadığından emin değilim. Belki de hizmetin bir sorguyu işlemeye başlamak ve tamamlamak için ne kadar beklemesi gerektiğini yapılandırıyorlar?


Diyagram, bir isteğin gerçek işleme için iş mantığına gönderilmeden önce Cinnamon üzerinden nasıl geçtiğini gösterir. (daha önce bahsedilen Uber makalesinden).


Belki de test edilmeye değer bir husus, ejektörün karar verme sürecidir.


Anladığım kadarıyla, hizmete yerelleştirilmiş PID denetleyicisine dayalı olarak bir isteğin reddedilip reddedilmeyeceğini belirliyor. Daha küresel bir yaklaşım seçeneği var mı? Örneğin, ardışık düzendeki aşağı akış hizmetlerinden birinin aşırı yüklendiği biliniyorsa (kendi PID denetleyicisi nedeniyle), herhangi bir yukarı akış hizmeti, bu aşırı yüklenmiş hizmete ulaşmadan önce isteği reddetmeye karar verebilir mi (bu, hizmetin n adım aşağısında olabilir) yol)?


Bu karar, PID denetleyicisi veya aşağı akış hizmetinin otomatik ayarlayıcısı tarafından döndürülen değere dayalı olabilir.



Şimdi, onlar makaleyi tamamlarken ve sistemlerinin verimliliğini gösteren bazı rakamlar sunarken, bahsedilen çeşitli yönler üzerinde düşünüyorum; bu oldukça etkileyici.


Farklı gelen RPS'lerde üç kurulum için yüksek öncelikli, katman 1 istekleri için P50 gecikmeleri. (daha önce bahsedilen Uber makalesinden).


Bir noktada 'Her isteğin 1 saniyelik bir zaman aşımı süresi vardır' diyorlar.


Trafiğin %50'sinin 1. kademe ve %50'sinin 5. kademe olduğu sabit miktarda RPS (örneğin 1.000) gönderdiğimiz 5 dakikalık testler gerçekleştiririz. Her isteğin 1 saniyelik bir zaman aşımı vardır.


Dağıtılmış sistemlerde, bir isteği belirli bir sona erme süresi veya son tarihle ilişkilendirmek ve işlem yolu üzerindeki her hizmetin bu süre sınırını uygulamaktan sorumlu olması yaygındır. İstek tamamlanmadan sona erme süresine ulaşılırsa zincirdeki herhangi bir hizmetin isteği iptal etme veya reddetme seçeneği vardır.


Bu 1 saniyelik zaman aşımının isteğe eklendiğini ve her hizmetin, bu son tarihte nerede olduğumuza bağlı olarak isteği iptal etmeye karar verebileceğini varsayıyorum. Bu, hizmetler aracılığıyla toplandığı için küresel bir ölçüdür. Sanırım bu, daha önce belirttiğim, tam sistem sağlığı veya bağımlılıkları hakkında küresel bir bakış açısına sahip olma ve aşağıdaki hizmetlerden biri nedeniyle tamamlanma şansı yoksa isteği mümkün olan en kısa sürede iptal etme kararı alma konusunda yankı uyandırıyor. yol.


Aşağı akış hizmetlerinin 'sağlığı' (yerel PID denetleyicilerinden gelen verileri içeren), yanıtlara eklenen başlıklar olarak döndürülebilir mi ve daha gelişmiş bir devre kesici/erken önleyici atma mekanizması oluşturmak için kullanılabilir mi?




Son olarak, önceki yaklaşım hakkında daha fazlasını öğrenmeyi merak ediyorum çünkü bu yazıda verilen açıklamaya göre bu yaklaşım mantıklı görünüyor.


İyi girdi ve gecikme ölçümlerini incelediğinizde hangisinin (QALM veya Tarçın) en iyi performansı gösterdiği konusunda hiçbir şüphe yoktur. Makalede QALM yaklaşımına bir bağlantıdan bahsettiklerini unutmayın. Muhtemelen oradan başlamalı ;)


Her zaman olduğu gibi bu yaklaşımlar herkese göre değildir. Uber'in mimarisi ve yükü kendine özgüdür. Aslında bu serideki sonraki makaleleri okumak, özellikle de PID denetleyici ve otomatik ayarlayıcı hakkında daha fazla bilgi edinmek için sabırsızlanıyorum.


Cinnamon ile hizmetlerin reddedilmesi ve kapasitesinin tahmin edilmesi için eşikleri dinamik olarak ayarlamak üzere asırlık teknikleri kullanan etkili bir yük ayırıcı oluşturduk. QALM'de (ve dolayısıyla herhangi bir CoDel tabanlı yük ayırıcıda) fark ettiğimiz sorunları çözer; yani Cinnamon şunları yapabilir:


- Hızlı bir şekilde istikrarlı bir ret oranı bulun


- Hizmetin kapasitesini otomatik olarak ayarlayın


- Herhangi bir konfigürasyon parametresi ayarlanmadan kullanılabilir


- Çok düşük ek yüke maruz kalır


Bu yaklaşımın ilginç yanı, bir (öncelik) kuyruğu kullandıklarından, her yeni giriş isteği için ne yapılacağına karar vermek üzere işlenecek tüm istekleri dikkate almalarıdır. Belirtildiği gibi, mekanizmanın aynı PID önlemlerine dayalı olarak tüm bağımlı hizmetlerin durumunu da dikkate alıp alamayacağını merak ediyorum…


Bu makalede stratejilerinin etkisini nasıl ölçtükleri ve önceki yaklaşımla karşılaştırma gibi başka ilginç yönler de var. Ancak benden daha önce sunulanlardan daha ayrıntılı notlar gerektirmiyor. Bu yüzden orijinal makaleyi okumanızı şiddetle tavsiye ederim.



Bu makaleyi faydalı buldunuz mu? Beni Linkedin , Hackernoon ve Medium'da takip edin! Lütfen bu makaleyi paylaşmak için 👏!