Hangi durumlarda (varsa) iki sunucuyu sorgulamak ve yalnızca en hızlı yanıtı kullanmak iyi bir uygulamadır?


12

Birisinin neden javascript kullanması konusunda SO tarafından silinen bir Topluluk sorusu sorusunun ne olduğunu sordum Promise.raceve yüksek rep kullanıcısı bu yorumu yaptı:

Bazı değerleri hesaplayan iki hizmetiniz varsa, bunları paralel olarak sorgulayabilir ve birini sorgulamak, başarısızlık beklemek ve sonra ikincisini sorgulamak yerine ilk olarak döndürülen değeri kullanabilirsiniz.

Artıklık ve genel olarak bu kullanım durumu hakkında googledim, ancak hiçbir şey bulamadım ve POV'umdan, yanıtı kullanmayacaksanız sadece bir sunucuya / hizmete iş yükü eklemek iyi bir fikir değildir.


Oyuncak örneği: her zaman quicksort kullanmak yerine, verileri kopyalar, bir quicksort'a, bir birleşmeye ve bir heatsort'a gönderirsiniz ... vb. Patolojik bir durum olup olmadığını görmek için girişi incelemeniz gerekmez. için herhangi olanların, çünkü bir Patolojik vaka olmayacak hepsi bunların
Caleth

Dean ve Barroso gazetesi The Tail at Scale , "Heded talepleri" yaklaşımında bir değişiklik çağrıştırıyor. Ayrıca, hata oranları ve gecikme süresinde uzun kuyruk değişkenliğini kontrol etmek için ilgili birkaç yaklaşımın artılarını ve eksilerini tartışıyor.
Daniel Pryden

İkinci "sunucu isteği" sahte olabilir. Sadece 5 saniye isteyebilir ve daha sonra bir yer tutucu yanıtı döndürebilir. Bu size gerçek istek üzerine bir zaman aşımı sağlar.
user253751

Bir Lyft sipariş edin ve sonra bir Uber sipariş edin. Hangisi önce gelirse al.
user2023861

@ user2023861, bu analojide, bir sürücü konumunuza doğru anlamsızca giderken, onun yerine başka bir istekte bulunabilirdi
Adelin

Yanıtlar:


11

Bunun daha çok ekonomi meselesi olduğunu iddia ediyorum. Ancak bu, mühendislerin yapabilmesi gereken bir karar çağrısıdır. Bu yüzden cevap veriyorum.

Cevabımı dört bölüme ayırıyorum:

  • Risk yönetimi
  • Stratejiler
  • Maliyetler
  • Sezgi

Risk yönetimi

Bu nedenle, bazen istemciniz sunucudan yanıt alamıyor. Bunun programlı bir hatadan kaynaklanmadığını varsayacağım (aksi takdirde çözüm düzeltmek, bu yüzden bunu yapın). Bunun yerine, kontrolünüzün ötesindeki tesadüfi bir durum yüzünden olmalı ...

Ama bilginizin ötesinde değil. Bilmelisin:

  • Ne sıklıkta oluyor.
  • Ne gibi bir etkisi var.

Örneğin, başarısızlık ve yeniden deneme yalnızca% 2 oranında gerçekleşirse, muhtemelen bunu ele almaya değmez. Zamanın yaklaşık% 80'inde olursa, şey ... bağlıdır ...

Müşteri ne kadar zaman beklemek zorunda? Ve bu maliyetlere nasıl dönüşüyor ... görüyorsunuz, normal bir uygulamada küçük bir gecikmeniz var, muhtemelen büyük bir sorun değil. Önemliyse ve gerçek zamanlı bir uygulamanız veya çevrimiçi bir video oyununuz varsa, bu kullanıcıları uzaklaştıracaktır ve muhtemelen daha fazla veya daha iyi sunuculara yatırım yapmaktan daha iyidir. Aksi takdirde, muhtemelen bir "yükleme" veya "sunucu bekleniyor" mesajı koyabilirsiniz. Gecikme gerçekten büyük olmadıkça (onlarca saniye), normal uygulama için bile çok fazla olabilir.


Stratejiler

Yukarıda söylediğim gibi, bu soruna gitmek için birden fazla yol var. Zaten try-fail-retry loop uygulamasına sahip olduğunuzu varsayacağım. Bakalım ...

  • Bir yükleme mesajı koyun. Ucuzdur, kullanıcının tutulmasına yardımcı olur.
  • Sorgu paralel olarak. Daha hızlı olabilir, yine de başarısız olabilir. Yedekli bir sunucuya ihtiyaç duyacaktır (pahalı olabilir), sunucu zamanını ve ağ trafiğini boşa harcar.
  • Daha hızlı sunucuyu sabitlemek ve oradan kullanmak için paralel olarak sorgulayın. Daha hızlı olabilir, yine de başarısız olabilir. Gereksiz sunucu gerektirecek (pahalı olabilir), sunucu zamanını ve ağ trafiğini boşa harcamaz.

Şimdi, bunların hala başarısız olabileceğini söylüyorum. Bir sunucuya yönelik bir sorgunun% 80 başarısızlık olduğunu varsayarsak, iki sunucuya paralel bir sorgu% 64'lük bir hata şansına sahiptir. Böylece, tekrar denemeniz gerekebilir.

Daha hızlı sunucuyu seçmenin ve kullanmaya devam etmenin avantajı, daha hızlı sunucunun ağ sorunları nedeniyle başarısız olma olasılığının düşük olmasıdır.

Hangi hatırlatıyor, eğer isteği neden başarısız olduğunu anlayabiliyorsanız, bunu yapın. Arızaları önleyemeseniz bile durumu daha iyi yönetmenize yardımcı olabilir. Örneğin, sunucu tarafında daha fazla aktarım hızına mı ihtiyacınız var?

Biraz daha:

  • Dünya genelinde birden çok sunucu dağıtın ve coğrafi konum belirleme ile sunucu seçin.
  • Sunucu tarafında yük dengeleme yapın (özel bir makine tüm istekleri alır ve sunucularınıza yeniden bağlar, orada paralelliğiniz olabilir veya daha iyi bir denge stratejisi olabilir).

Ve bunlardan sadece birini yapmanız gerektiğini kim söyledi? Bir yükleme mesajı koyabilir, daha hızlı seçmek için wrold'a yayılmış birden fazla sunucuyu sorgulayabilir ve yalnızca oradan, bir döngüde hata yeniden denemede kullanabilirsiniz ve bu sunucuların her birinin yük dengelemeli bir makine kümesi olmasını sağlayabilirsiniz. . Neden olmasın? Maliyetler ...


Maliyetler

Dört maliyet vardır:

  • Geliştirme maliyeti (genellikle çok ucuz)
  • Dağıtım maliyeti (genellikle yüksek)
  • Maliyet çalışma zamanı (uygulamanın türüne ve iş modeline bağlıdır)
  • Başarısızlığın maliyeti (muhtemelen düşük, ancak gerekli değildir)

Onları dengelemek zorundasınız.

Örneğin, memnun kullanıcı başına yaklaşık bir dolar kazandığınızı varsayalım. Günde 3000 kullanıcınız olduğunu. İsteklerin% 50 oranında başarısız olduğu. Ve kullanıcıların% 2'si istek başarısız olduğunda ödeme yapmadan ayrılıyor. Bu, günde 30 dolar (3000 * 50 *% 2) kaybettiğiniz anlamına gelir. Şimdi, yeni özelliğin geliştirilmesinin size 100 dolara mal olacağını ve sunucuları konuşlandırmanın size 800 dolara mal olacağını ve çalışma zamanı maliyetlerini göz ardı edeceğinizi varsayalım ki bu, ((100 + 800) / 30 ) 30 gün. Artık bütçenizi kontrol edebilir ve karar verebilirsiniz.

Bu değerleri gerçeğin temsilcisi olarak düşünmeyin, onları matematik rahatlığı için seçtim.

Ekler:

  • Detayları da görmezden geldiğimi unutmayın. Örneğin, dağıtım maliyetiniz az olabilir, ancak CPU zamanı için ödeme yapıyor olabilirsiniz ve bunu göz önünde bulundurmanız gerekir.
  • Bazı istemciler veri paketlerini gereksiz istekler içinde boşa harcamazsanız memnun olabilirler.
  • Ürününüzü geliştirmek doğal reklamlar getirmenize yardımcı olabilir.
  • Fırsat maliyetlerini unutmayın. Başka bir şey geliştirmeli misiniz?

Mesele şu ki, eğer problemi maliyetleri dengeleme açısından ele alırsanız, dikkate aldığınız stratejiler için maliyeti tahmin edebilir ve bu analizi karar vermek için kullanabilirsiniz.


Sezgi

Deneyime göre teşvik eğer sezgi. Her seferinde bu tür bir analiz yapmayı önermiyorum. Bazı insanlar yapar ve bu sorun değil. Bunu anlamanız ve bunun için bir sezgi geliştirmenizi öneriyorum.

Dahası, mühendislikte, gerçek bilimden elde ettiğimiz bilginin yanı sıra, uygulamada öğrenir ve neyin işe yarayıp neyin yaramadığına dair yönergeler derleriz. Bu nedenle, sanatın durumunun ne olduğunu görmek genellikle akıllıca olur ... ancak bazen bölgenizin dışında görmeniz gerekir.

Bu durumda, çevrimiçi video oyunlarına bakardım. Yük ekranları var, birden fazla sunucuları var, gecikmeye göre bir sunucu seçecekler ve hatta kullanıcının sunucuları değiştirmesine izin verebilirler. Bunun işe yaradığını biliyoruz.

Her istekte ağ trafiğini ve sunucu zamanını boşa harcamak yerine bunu yapmayı öneririm, yedek sunucuda bile hata olabileceğini unutmayın.


2
Söylemem gerektiğini sanmıyorum ama bu harika bir cevap :) İlk 10 satırda kabul edeceğimi biliyordum, ama sana hala başarısız olma ve sonuna kadar okuma fırsatı verdim. Atmadın
Adelin

9

İstemcinin zamanı sunucudaki zamandan daha değerliyse, bu kabul edilebilir.

İstemcinin hızlı ve doğru olması gerekiyorsa. Birkaç sunucuyu sorgulamayı haklı gösterebilirsiniz. Geçerli bir yanıt alınırsa isteği iptal etmek güzeldir.

Ve tabii ki sunucuların sahiplerine / yöneticilerine danışmak her zaman akıllıca olacaktır.


Neden mi ihtiyacınız isteği iptal etmek? Elbette bu özneldir.
JᴀʏMᴇᴇ

@ JᴀʏMᴇᴇ, Bu paranoyada inşa edilmiştir. Bir zamanlar kuyruğunu temizlemeyen bir sistemle çalıştım ve kuyruk dolduğunda çöktü (Evet, profesyonel bir yazılımdı).
Toon Krijthe

4

Bu teknik gecikmeyi azaltabilir. Sunucu yanıt süresi belirleyici değildir. Ölçekte, yanıt sürelerinin düşük olduğunu gösteren muhtemelen en az bir sunucu olacaktır. Bu sunucuyu kullanan her şeyin yanıt süreleri de zayıf olacaktır. Birkaç sunucuya gönderme yapmak, kötü performans gösteren bir sunucuyla konuşma riskini azaltır.

Maliyetler, ek ağ trafiğini, boşa giden sunucu işlemeyi ve uygulama karmaşıklığını (bunun bir kütüphanede gizlenebileceğini düşünüyor) içerir. Bu maliyetler, kullanılmayan istekleri iptal ederek veya ikinci bir istek göndermeden önce kısa bir süre bekleyerek azaltılabilir.

İşte bir kağıt , ve başka . Bir Google belgesini de uyguladıklarını hatırlıyorum.


2

Çoğunlukla diğer cevaplara katılıyorum, ancak bunun pratikte çok nadir olması gerektiğini düşünüyorum. Ne zaman kullanacağınız için çok daha yaygın ve makul bir örnek paylaşmak istedim, Promise.race()birkaç hafta önce kullandığım bir şey (python eşdeğeri).

Diyelim ki bazıları paralel çalıştırılabilecek ve bazıları diğerlerinden önce çalıştırılması gereken uzun bir görev listeniz var. Tüm görevleri bağımlılık olmadan başlatabilir, ardından bu listede ile bekleyebilirsiniz Promise.race(). İlk görev tamamlanır tamamlanmaz, o ilk göreve ve Promise.race()yeni listeye orijinal listeden tamamlanmamış görevlerle birleştirilmiş görevleri başlatabilirsiniz . Tüm görevler tamamlanana kadar tekrarlamaya devam edin.

Not Javascript API'sı bunun için ideal olarak tasarlanmamıştır. Neredeyse işe yarayan minimum minimumdur ve biraz tutkal kodu eklemeniz gerekir. Ancak benim görüşüm, race()fazlalık için nadiren kullanılan fonksiyonlardır . Öncelikle tüm vaatlerden sonuçları istediğinizde oradalar, ancak sonraki eylemleri gerçekleştirmeden önce hepsinin tamamlanmasını beklemek istemiyorum.


Sorun, en azından Javascript'in Promise.race ile, yarış yöntemini her çalıştırdığınızda aslında görevi başlatmanızdır. Tamamlanmamış görevde olmayacak, daha önce neyin çalıştırıldığına bakılmaksızın (bu mantığı görev düzeyinde uygulamadığınız sürece) yeni bir görev kümesi olacaktır. Orijinal liste aksi halde unutulur ve sadece ilk görevin dönüş değeri kalır
Adelin

1
Javascript'teki vaatler new Promiseçağrıldığında hevesle başlatılır ve çağrıldığında yeniden başlatılmaz Promise.race(). Bazı vaat uygulamaları tembeldir, ancak istekli çok daha yaygındır. Konsolda, konsola oturum açan bir söz oluşturarak test edebilirsiniz. Günlükleri hemen göreceksiniz. Sonra bu sözü iletin Promise.race(). Tekrar giriş yapmadığını göreceksiniz.
Karl Bielefeldt

Ah, bu doğru. Ama önce biri dışında sözlerin dinlenme dönüş değeri afaik promise.race ile, unutulur
Adelin

Bu yüzden API'nin ideal bir şekilde tasarlanmadığını söyledim. Bir yerde bir değişken içindeki orijinal görev kümesini saklamanız gerekir.
Karl Bielefeldt

1

Teknik hususlara ek olarak, gerçek iş modelinizin bir parçası olduğunda bu yaklaşımı kullanmak isteyebilirsiniz.

Bu yaklaşımdaki varyasyonlar, reklamlara Gerçek zamanlı teklif vermede nispeten yaygındır . Bu modelde bir yayıncı (reklam alanı sağlayıcısı) reklamverenlerden (reklam sağlayıcılarından) belirli bir kullanıcının gösterimi için teklif vermesini ister . Dolayısıyla, bu tür her gösterim için, abone olan her bir reklamvereni sorgulayarak her bir reklamveren tarafından sağlanan bir bitiş noktasına (veya alternatif olarak, reklamveren tarafından kendi sunucularınızda bitiş noktası olarak çalışan bir komut dosyası) bir gösterim göndererek yarışırsınız. tüm bu talepler bir zaman aşımına kadar (örneğin 100 ms) ve ardından en yüksek teklifi alarak diğerlerini yok sayar.

Bunun, müşterinin bekleme süresini azaltmaya yardımcı olan belirli bir varyasyonu, yayıncının teklif için minimum hedef değerine izin vermesini sağlamaktır, böylece bu değeri aşan ilk reklamveren teklifi hemen kabul edilir (veya tekliflerin hiçbiri aşılmazsa) değer, maksimum değer alınır). Bu varyasyonda, ilk gelen sorgu kazanabilir ve diğeri, iyi veya daha iyi olsalar bile atılabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.