Matematiği Yapın: Mikro Hizmet Uygulamalarını Orkestratörlerle Ölçeklendirme
Yayınlanan: 2022-03-11Mikro hizmet uygulama mimarisinin yazılım tasarımını istila etmeye devam etmesi pek de şaşırtıcı değil. Geliştirme ve ekip yönetimini kolaylaştırırken yükü dağıtmak, yüksek düzeyde kullanılabilir dağıtımlar oluşturmak ve yükseltmeleri yönetmek çok daha uygundur.
Ancak, konteyner düzenleyiciler olmadan hikaye kesinlikle aynı değil.
Tüm temel özelliklerini, özellikle otomatik ölçeklendirmeyi kullanmak istemek kolaydır. Gün boyu dalgalanan, mevcut yükün üstesinden gelmek için nazikçe boyutlandırılan ve diğer görevler için zamanımızı boşa harcayan konteyner dağıtımlarını izlemek ne büyük bir nimet. Konteyner izleme araçlarımızın gösterdiklerinden gurur duyuyoruz; bu arada, sadece birkaç ayarı yapılandırdık - evet, sihri yaratmak için gereken (neredeyse) bu kadar!
Bu, bununla gurur duymanın bir anlamı olmadığı anlamına gelmiyor: Kullanıcılarımızın iyi bir deneyim yaşadığından ve büyük boyutlu altyapı ile boşa para harcamadığımızdan eminiz. Bu zaten oldukça önemli!
Ve elbette, oraya ulaşmak ne büyük bir yolculuktu! Çünkü sonunda yapılandırılması gereken çok fazla ayar olmasa bile, başlamadan önce genellikle düşündüğümüzden çok daha zorlayıcıdır. Minimum/maksimum replika sayısı, ölçek büyütme/küçültme eşikleri, eşitleme periyotları, soğuma gecikmeleri - tüm bu ayarlar birbirine çok bağlıdır. Birini değiştirmek büyük olasılıkla diğerini etkileyecektir, ancak yine de hem uygulamanıza/dağıtımınıza hem de altyapınıza uyacak dengeli bir kombinasyon ayarlamanız gerekir. Yine de, büyük ölçüde ihtiyaçlarınıza bağlı olduğundan , internette herhangi bir yemek kitabı veya sihirli bir formül bulamazsınız.
Çoğumuz bunları önce "rastgele" veya varsayılan değerlere ayarlarız ve daha sonra izleme sırasında bulduklarımıza göre ayarlarız. Bu beni düşündürdü: Ya kazanan kombinasyonu bulmamıza yardımcı olacak daha "matematiksel" bir prosedür oluşturabilseydik?
Container Orkestrasyon Parametrelerini Hesaplama
Bir uygulama için otomatik ölçeklendirme mikro hizmetleri hakkında düşündüğümüzde, aslında iki ana noktada iyileştirmeye bakıyoruz:
- Hızlı bir yük artışı durumunda dağıtımın hızla ölçeklenebilmesini sağlama (böylece kullanıcılar zaman aşımları veya HTTP 500'lerle karşılaşmazlar)
- Altyapı maliyetini düşürmek (örn., örneklerin yetersiz yüklenmesini önlemek)
Bu temelde, ölçek büyütme ve küçültme için kapsayıcı yazılım eşiklerinin optimize edilmesi anlamına gelir. (Kubernetes algoritmasında ikisi için tek bir parametre vardır).
Örnekle ilgili tüm parametrelerin üst düzey eşiğe bağlı olduğunu daha sonra göstereceğim. Bu, hesaplanması en zor olanıdır - bu nedenle bu makale.
Not: Küme çapında ayarlanan parametrelerle ilgili olarak, onlar için iyi bir prosedürüm yok, ancak bu makalenin sonunda, hesaplama yaparken bunları dikkate alan bir yazılım parçası (statik bir web sayfası) tanıtacağım. örneğin otomatik ölçeklendirme parametreleri. Bu şekilde, etkilerini dikkate almak için değerlerini değiştirebileceksiniz.
Ölçek Arttırma Eşiğinin Hesaplanması
Bu yöntemin çalışması için uygulamanızın aşağıdaki gereksinimleri karşıladığından emin olmalısınız:
- Yük, uygulamanızın her örneğine eşit olarak dağıtılmalıdır (yuvarlak deneme şeklinde)
- İstek zamanlamaları, kapsayıcı kümenizin yük denetimi aralığından daha kısa olmalıdır.
- Prosedürü çok sayıda kullanıcı üzerinde çalıştırmayı düşünmelisiniz (daha sonra tanımlanacaktır).
Bu koşulların ana nedeni, algoritmanın yükü kullanıcı başına değil, bir dağılım (daha sonra açıklanacak) olarak hesaplamasından kaynaklanmaktadır.
Tüm Gauss'u Almak
Öncelikle hızlı bir yük artışı veya başka bir deyişle en kötü durum senaryosu için bir tanım formüle etmemiz gerekiyor. Bana göre, bunu çevirmenin iyi bir yolu şudur: çok sayıda kullanıcının kısa bir süre içinde kaynak tüketen eylemler gerçekleştirmesi — ve bunun her zaman başka bir kullanıcı veya hizmet grubu başka görevleri yerine getirirken olma olasılığı vardır. Öyleyse bu tanımdan başlayalım ve biraz matematik çıkarmaya çalışalım. (Aspirininizi hazırlayın.)
Bazı değişkenlerin tanıtılması:
- $N_{u}$, "çok sayıda kullanıcı"
- $L_{u}(t)$, "kaynak tüketen işlemi" gerçekleştiren tek bir kullanıcı tarafından oluşturulan yük ($t=0$, kullanıcının işlemi başlattığı anı gösterir)
- $L_{tot}(t)$, toplam yük (tüm kullanıcılar tarafından oluşturulur)
- $T_{tot}$, "kısa süre"
Matematik dünyasında, aynı şeyi aynı anda gerçekleştiren çok sayıda kullanıcıdan bahsederken, kullanıcıların zaman içindeki dağılımı, formülü şu şekilde olan bir Gauss (veya normal) dağılımı izler:
\[G(t) = \frac{1}{\sigma \sqrt{2 \pi}} e^{\frac{-(t-\mu)^2}{2 \sigma^2}}\]Burada:
- µ beklenen değerdir
- σ standart sapmadır
Ve aşağıdaki gibi grafiklendirilir ($µ=0$ ile):
Muhtemelen aldığınız bazı dersleri andırıyor - yeni bir şey değil. Bununla birlikte, burada ilk sorunumuzla karşı karşıyayız: Matematiksel olarak doğru olmak için, açıkça hesaplanamayan $-\infty$ ile $+\infty$ arasındaki bir zaman aralığını dikkate almamız gerekir.
Ancak grafiğe baktığımızda, $[-3σ, 3σ]$ aralığının dışındaki değerlerin sıfıra çok yakın olduğunu ve çok fazla değişmediğini, yani etkilerinin gerçekten ihmal edilebilir olduğunu ve bir kenara konulabileceğini fark ediyoruz. Bu daha doğrudur, çünkü amacımız uygulamamızın ölçeğini büyütmeyi test etmektir, bu nedenle çok sayıda kullanıcının varyasyonlarını arıyoruz.
Artı, $[-3σ, 3σ]$ aralığı kullanıcılarımızın yüzde 99,7'sini içerdiğinden, üzerinde çalışmak için toplama yeterince yakındır ve telafi etmek için sadece $N_{u}$ ile 1,003'ü çarpmamız gerekir. fark. Bu aralığı seçmek bize $µ=3σ$ değerini verir (çünkü $t=0$'dan çalışacağız).
$T_{tot}$ ile ilgili olarak, bunu $6σ$'a ($[-3σ, 3σ]$) eşit olarak seçmek iyi bir tahmin olmayacaktır, çünkü kullanıcıların yüzde 95,4'ü $[- aralığındadır. 4σ$ süren 2σ, 2σ]$. Dolayısıyla, $T_{tot}$'ı $6σ$'a eşit olarak seçmek, kullanıcıların yalnızca yüzde 4,3'ü için zamanın yarısını ekleyecektir ve bu gerçekten temsili değildir. Böylece $T_{tot}=4σ$ almayı seçiyoruz ve şunu çıkarabiliyoruz:
\(σ=\frac{T_{tot}}{4}\) ve \(µ=\frac{3}{4} * T_{tot}\)
Bu değerler bir şapkadan mı çıktı? Evet. Ama amaçları budur ve bu matematiksel prosedürü etkilemeyecektir. Bu sabitler bizim içindir ve hipotezimizle ilgili kavramları tanımlar. Bu sadece, onları ayarlamış olduğumuza göre, en kötü durum senaryomuzun şu şekilde çevrilebileceği anlamına gelir:
$N{u}$'ın yüzde 99,7'si tarafından oluşturulan, $L{u}(t)$ tüketen bir işlem gerçekleştiren ve yüzde 95,4'ünün bunu $T{tot}$ süresi içinde yaptığı yük.
(Bu, web uygulamasını kullanırken hatırlamaya değer bir şeydir.)
Kullanıcı dağıtım fonksiyonuna (Gaussian) önceki sonuçları enjekte ederek, denklemi aşağıdaki gibi sadeleştirebiliriz:
\[G(t) = \frac{4 N_{u}}{T_{tot} \sqrt{2 \pi}} e^\frac{-(4t-3T_{tot})^2}{T_{tot }^2}\]Şu andan itibaren, $σ$ ve $µ$ tanımlı olarak, $t \in [0, \frac{3}{2}T_{tot}]$ ($6σ$ süren) aralığı üzerinde çalışacağız.

Toplam Kullanıcı Yükü Nedir?
Otomatik ölçeklendirme mikro hizmetlerindeki ikinci adım, $L_{tot}(t)$'ı hesaplamaktır.
$G(t)$ bir dağıtım olduğundan, belirli bir zaman noktasındaki kullanıcı sayısını almak için integralini hesaplamamız (veya kümülatif dağılım işlevini kullanmamız) gerekir. Ancak tüm kullanıcılar işlemlerine aynı anda başlamadığından, $L_{u}(t)$'ı tanıtmaya ve denklemi kullanılabilir bir formüle indirgemeye çalışmak gerçek bir karmaşa olacaktır.
Bunu kolaylaştırmak için, küçük şekillerin sonlu bir toplamını kullanarak bir integrale yaklaşmanın matematiksel bir yolu olan Riemann toplamını kullanacağız (burada dikdörtgenler kullanacağız). Ne kadar fazla şekil (alt bölüm) olursa, sonuç o kadar doğru olur. Alt bölümleri kullanmanın bir başka yararı da, bir alt bölüm içindeki tüm kullanıcıları aynı anda operasyonlarına başlamış sayabilmemizdir.
Riemann toplamına dönersek, integrallerle bağlantılı şu özelliğe sahiptir:
\[\int_{a}^{b} f( x )dx = \lim_{n \rightarrow \infty } \sum_{k=1}^{n} ( x_{k} - x_{k-1} ) f( x_{k} )\]$x_k$ ile aşağıdaki gibi tanımlanır:
\[x_{ k } = bir + k\frac{ b - bir }{ n }, 0 \leq k \leq n\]Bu, şu durumlarda doğrudur:
- $n$ alt bölümlerin sayısıdır.
- $a$ alt sınırdır, burada 0.
- $b$ üst sınırdır, burada $\frac{3}{2}*T_{tot}$.
- $f$, alanını yaklaşık olarak tahmin etme işlevidir - burada $G$.
Not: Bir alt bölümde bulunan kullanıcı sayısı bir tam sayı değildir. Önkoşullardan ikisinin nedeni budur: Çok sayıda kullanıcıya sahip olmak (bu nedenle ondalık kısım çok fazla etkilenmez) ve yükün her örnekte eşit olarak dağıtılması ihtiyacı.
Ayrıca, Riemann toplam tanımının sağ tarafında alt bölümün dikdörtgen şeklini görebileceğimize dikkat edin.
Artık Riemann toplam formülüne sahip olduğumuza göre, $t$ anındaki yük değerinin, her alt bölümün kullanıcı sayısının, karşılık gelen zamanda kullanıcı yükleme işleviyle çarpımının toplamı olduğunu söyleyebiliriz. Bu şu şekilde yazılabilir:
\[L_{ tot }( t ) = \lim_{n \rightarrow \infty} \sum_{ k=1 }^{ n } ( x_{k} - x_{k-1} )G( x_{k} ) L_{ u }( t - x_{k} )\]Değişkenleri değiştirdikten ve formülü basitleştirdikten sonra, şu hale gelir:
\[L_{ tot }( t ) = \frac{6 N_{u}}{\sqrt{2 \pi}} \lim_{n \rightarrow \infty} \sum_{ k=1 }^{ n } (\ frac{1}{n}) e^{-{(\frac{6k}{n} - 3)^{2}}} L_{ u }( t - k \frac{3 T_{tot}}{2n } )\]Ve işte ! Yük fonksiyonunu yarattık!
Ölçek Arttırma Eşiğini Bulma
Bitirmek için, örnek başına yükün tüm yük fonksiyonu boyunca asla maksimum sınırını aşmadığı en yüksek değeri bulmak için eşiği değiştiren bir dikotomi algoritması çalıştırmamız yeterlidir. (Uygulama tarafından yapılan budur.)
Diğer Düzenleme Parametrelerini Çıkarma
Ölçek büyütme eşiğinizi ($S_{up}$) bulduğunuzda, diğer parametreleri hesaplamak oldukça kolaydır.
$S_{up}$'dan maksimum örnek sayınızı bileceksiniz. (Ayrıca, yükleme işlevinizdeki maksimum yükü arayabilir ve örnek başına maksimum yüke bölünerek yuvarlanabilirsiniz.)
Minimum örnek sayısı ($N_{min}$) altyapınıza göre tanımlanmalıdır. (AZ başına en az bir replika olmasını tavsiye ederim.) Ama aynı zamanda yük fonksiyonunu da hesaba katması gerekiyor: Bir Gauss fonksiyonu oldukça hızlı bir şekilde arttığından, başlangıçta yük dağılımı daha yoğundur (replika başına), yani bu etkiyi yumuşatmak için minimum kopya sayısını artırmak isteyebilir. (Bu büyük olasılıkla $S_{up}$'ınızı artıracaktır.)
Son olarak, minimum replika sayısını tanımladıktan sonra, aşağıdakileri dikkate alarak ölçeği küçültme eşiğini ($S_{down}$) hesaplayabilirsiniz: Tek bir replikanın ölçeğini küçültmenin diğer örnekler üzerinde, diğer örneklerin ölçeğini küçültmekten daha fazla etkisi yoktur. $N_{min}+1$ - $N_{min}$ arasında, ölçeği küçülttükten hemen sonra ölçek büyütme eşiğinin tetiklenmeyeceğinden emin olmalıyız. İzin verilirse, bunun bir yo-yo etkisi olacaktır. Başka bir deyişle:
\[( N_{ dak } + 1) S_{ aşağı } < N_{ dak }S_{ yukarı }\]Veya:
\[S_{ aşağı } < \frac{N_{ dak }}{N_{dk}+1}S_{ yukarı }\]Ayrıca, kümenizin ölçeği küçültmeden önce beklemek üzere yapılandırılması ne kadar uzun sürerse, $S_{down}$ öğesini daha yüksek sınıra ayarlamak o kadar güvenli olur. Bir kez daha, size uygun bir denge bulmanız gerekecek.
Mesosphere Marathon orkestrasyon sistemini kendi otomatik ölçekleyicisiyle birlikte kullanırken, ölçeğin küçültülmesinden bir kerede kaldırılabilecek maksimum örnek sayısının AS_AUTOSCALE_MULTIPLIER
($A_{mult}$) ile bağlantılı olduğunu unutmayın, bu şu anlama gelir:
Kullanıcı Yükleme İşlevi Nedir?
Evet, bu biraz sorun ve matematiksel olarak çözülmesi en kolay olanı değil - eğer mümkünse.
Bu soruna geçici bir çözüm bulmak için fikir, uygulamanızın tek bir örneğini çalıştırmak ve aynı görevi gerçekleştiren kullanıcı sayısını sunucu yükü atanan maksimum değere ulaşana kadar (ancak bitmeyen) art arda artırmaktır. Ardından kullanıcı sayısına bölün ve talebin ortalama süresini hesaplayın. Kullanıcı yükleme işlevinize entegre etmek istediğiniz her eylemde bu prosedürü tekrarlayın, biraz zaman ekleyin ve işte buradasınız.
Bu prosedürün, her kullanıcı isteğinin işlenmesi üzerinde sabit bir yüke sahip olduğunu düşünmek anlamına geldiğinin farkındayım (ki bu açıkça yanlıştır), ancak her biri aynı işlem adımında olmadığı için kullanıcı kitlesi bu etkiyi yaratacaktır. . Sanırım bu kabul edilebilir bir yaklaşım, ancak bir kez daha çok sayıda kullanıcıyla uğraştığınızı ima ediyor.
CPU alev grafikleri gibi diğer yöntemlerle de deneyebilirsiniz. Ancak kullanıcı eylemlerini kaynak tüketimine bağlayacak doğru bir formül oluşturmanın çok zor olacağını düşünüyorum.
app-autoscaling-calculator
Ve şimdi, baştan sona bahsedilen küçük web uygulaması için: Girdi olarak yükleme işlevinizi, kapsayıcı düzenleyici yapılandırmanızı ve diğer bazı genel parametreleri alır ve ölçek büyütme eşiğini ve örnekle ilgili diğer rakamları döndürür.
Proje GitHub'da barındırılıyor, ancak aynı zamanda canlı bir sürümü de mevcut.
Test verilerine karşı çalıştırılan web uygulaması tarafından verilen sonuç (Kubernetes'te):
Mikro Hizmetleri Ölçeklendirme: Artık Karanlıkta Uğraşmak Yok
Mikro hizmet uygulama mimarileri söz konusu olduğunda, konteyner dağıtımı tüm altyapının merkezi noktası haline gelir. Ve düzenleyici ve kapsayıcılar ne kadar iyi yapılandırılırsa, çalışma zamanı o kadar sorunsuz olur.
DevOps hizmetleri alanındaki bizler, uygulamalarımız için her zaman orkestrasyon parametrelerini ayarlamanın daha iyi yollarını arıyoruz. Otomatik ölçeklendirme mikro hizmetlerine daha matematiksel bir yaklaşım getirelim!