- Uber, saniyede yüz milyonlarca RPC işleyen binlerce mikroservis ortamında, birleşik bir aşırı yük koruma çerçevesi kurmak için küresel hız sınırlayıcıyı (Global Rate Limiter, GRL) inşa etti
- GRL, istemci-toplayıcı-denetleyiciden oluşan 3 katmanlı geri besleme döngüsü mimarisiyle, istekleri yerelde değerlendirirken birkaç saniye içinde küresel koordinasyon da sağlayabiliyor
- İlk token bucket yaklaşımından olasılıksal drop modeline geçerek adalet ve ölçeklenebilirlik sorunlarını çözdü, hot path üzerindeki gecikmeyi en aza indirdi
- Redis tabanlı sınırlayıcıya kıyasla P99.5 gecikmesi en fazla %90 iyileşti; 15 kat trafik artışı ve DDoS saldırıları da hizmette bozulma olmadan karşılandı
- Rate Limit Configurator (RLC), geçmiş trafik desenlerini analiz ederek limitleri otomatik güncelliyor; böylece sistem statik yapılandırmadan kendi kendini ayarlayan bir yapıya evrildi
Mevcut hız sınırlamanın sorunları
- Uber'in ilk mikroservis ortamında her ekip, iş mantığı, özel middleware, Redis tabanlı sayaçlar gibi yöntemlerle throttling'i kendi başına uyguluyordu
- Bunun sonucunda tutarsız yapılandırmalar, Redis kaynaklı ek gecikme, limit değişikliklerinde sunucu yeniden dağıtımı gerekliliği ve belgelenmemiş sınırlayıcılar nedeniyle incident müdahalesinin zorlaşması gibi sorunlar ortaya çıktı
- Küçük ölçekli servislerin önemli bir kısmı hiç hız sınırlama olmadan çalışıyordu ve her sınırlayıcı metrikleri ile hataları farklı biçimde raporladığı için birleşik gözlemlenebilirlik sağlanamıyordu
- Redis'i merkezi sayaç olarak kullanma yaklaşımı, yüz binlerce host, saniyede yüz milyonlarca istek ve çok bölgeli ortamda kabul edilemez gecikme ile bölgeler arası tutarlılık sorunları doğurdu
- Sharding ve replikasyon uygulansa bile yüzlerce Redis kümesi gerekir ve yeni arıza modları eklenirdi
- Sayaçların periyodik senkronizasyonu yaklaşımı da ağ ek yükünü azaltsa da verinin tazeliğini düşürdüğü ve ani trafik sıçramalarına yavaş tepki verdiği için elendi
- Sonuç olarak yalnızca yerel proxy'nin toplanmış yüke göre karar verdiği tamamen dağıtık bir mimarinin, düşük gecikme ile küresel ölçeklenebilirliği aynı anda sağlayabileceği sonucuna varıldı
Birleşik altyapı seviyesi sınırlayıcı vizyonu
- Çözüm, hız sınırlamayı Uber'in service mesh'ine (servisler arası RPC trafiği için altyapı katmanı) gömmek oldu
- Sınırlayıcı bu katmana gömülerek, çağıranın dili veya framework'ünden bağımsız olarak tüm istekler hedefe ulaşmadan önce denetlenip değerlendirilebilir hale geldi
- Hedef: ekiplerin kod değişikliği yapmadan çağıran bazında ve prosedür bazında kota tanımlayabildiği birleşik bir hız sınırlama servisi sunmak
- Saniyede yüz milyonlarca istek, on binlerce servis çifti ve coğrafi olarak dağıtılmış çok bölgeli host filoları üzerinde asgari ek gecikmeyle ölçeklenmesi gerekiyordu
GRL mimarisi: 3 katmanlı geri besleme döngüsü
- GRL'nin çekirdeğinde 3 katmanlı geri besleme döngüsü yapısı var
- Rate-limit istemcisi (service mesh data plane): toplayıcıdan aldığı yönergelere göre yerelde istek bazlı karar verir, host başına saniyelik istek sayısını zone seviyesindeki toplayıcıya raporlar
- Toplayıcı (zone bazında): aynı zone içindeki tüm istemcilerden metrik toplar, zone seviyesi kullanımı hesaplayıp denetleyiciye gönderir
- Denetleyici (bölge bazında, küresel): zone verilerini toplayarak küresel kullanım oranını belirler, güncellenmiş drop oranı yönergelerini tekrar toplayıcılara ve istemcilere dağıtır
- Bu hiyerarşik toplama yapısı, hot path üzerinde düşük gecikmeyi (karar yerelde verilir) korurken birkaç saniye içinde küresel koordinasyon da sağlar
- Control plane arızasında istemciler fail-open biçiminde çalışır; trafiği geçirmeye devam ederek kendi kendine tetiklenen kesintileri önler
Hız sınırlama mantığının evrimi
-
İlk token bucket yaklaşımı
- Başlangıçta ağ data plane'indeki her proxy üzerinde token bucket algoritması uygulanıyordu
- Her proxy yerel istek sayısını izliyor, zamanla token yeniliyor ve eldeki token sayısına göre isteğe izin veriyor ya da reddediyordu
- Token yenileme oranı, proxy'nin yerel yükü ile küresel limit arasındaki orana göre hesaplanıyordu:
ratio × limitRPS
- Burst trafiği karşılamak için kullanılmayan token'lar döngüsel buffer içinde tutuluyor, varsayılan olarak 10 saniye boyunca saklanıyordu (en fazla 20 saniyeye kadar yapılandırılabiliyordu)
- Ancak üretimde adalet ve ölçeklenebilirlik sorunları ortaya çıktı: çağıran sayısı limiti aştığında kapasite adil dağıtılamıyor, tekil host'lardaki burst trafik küresel limitin altında kalınsa bile erken drop'a yol açabiliyordu
-
Drop-by-Ratio'nun devreye alınması
- Toplanan küresel yük, tanımlanan limiti aştığında istemciler isteklerin belli bir oranını olasılıksal olarak drop etmeye başladı
- Örneğin çağıranın toplam RPS değeri limitin 1.5 katıysa tüm instance'larda yaklaşık %33 drop uygulanır; formül:
drop_ratio = (actual_rps - limit_rps) / actual_rps
- Bu, control plane'in birkaç saniyede bir güncellediği küresel drop sinyali ile, fazla trafiğin tüm çağıran instance'ları arasında eşit biçimde throttling edilmesini sağladı
- Özellikle yüzlerce ila binlerce çağıran instance'ına sahip büyük gateway tipi servislerde etkili oldu
-
Birleşik olasılıksal modele geçiş
- GRL olgunlaştıkça token bucket tamamen kaldırıldı ve sistem tek bir control plane tabanlı olasılıksal drop modeli altında birleştirildi
- Çünkü iki algoritmanın aynı anda çalıştırılması yapılandırma karmaşıklığını ve ağ ek yükünü artırıyordu
- Tek modele geçilerek yapılandırma sadeleşti, control plane bant genişliği azaldı ve tüm hız sınırlama kararları küresel olarak tutarlı bir mekanizma altında birleşti
- Karşılığında, saniyede bir güncellenen küresel toplu veriye bağımlılık nedeniyle 2-3 saniyelik uygulama gecikmesi oluştu
- Pratikte bu, çoğu iş yükü için ihmal edilebilir düzeydeydi; yalnızca çok kısa ve aşırı burst durumlarında etkiliydi
-
Nihai tasarım: control plane yönergeli olasılıksal drop
- Bugün GRL'de uygulama tamamen ağ data plane'indeki istemci katmanında gerçekleşiyor
- İstek geldiğinde işleme akışı şu şekilde:
- İstek, tanımlı bucket'a eşleştirilir (çağıran, prosedür veya her ikisine göre)
- İlgili bucket için etkin bir drop oranı yönergesi varsa bu orana göre olasılıksal drop uygulanır
- Drop yönergesi yoksa istek normal şekilde iletilir
- Hot path son derece hafiftir: yerel token hesabı ya da istek başına control plane iletişimi gerekmez; karar basit olasılıksal örnekleme ile proses içinde verilir
- Toplayıcılar ve denetleyiciler, iletim düzleminin dışında karmaşık hesaplamaları (istek sayısı toplama, eşik karşılaştırma, yeni drop oranı hesaplama) her saniye yürütür
- Bu tasarım, saniyede yüz milyonlarca isteğe ölçeklenirken birkaç saniye içinde küresel uygulama doğruluğunu korur
Limit yapılandırması
- Servis sahipleri, yapılandırma dosyalarında hız sınırlama bucket'larını tanımlar
- Scope: küresel, bölge bazında, zone bazında
- Eşleştirme kuralları: çağıran adı, prosedür veya her ikisi
- Davranış: deny (uygula) veya allow (test amaçlı shadow mode)
- Hedef servise kod değişikliği olmadan şeffaf biçimde uygulanır
Operasyonel sonuçlar
-
Gecikmenin azaltılması ve ek yükün kaldırılması
- GRL öncesinde birçok servis, her istek için ağ round-trip'i gerektiren Redis tabanlı sınırlayıcılar kullanıyordu
- Service mesh data plane içinde yerel değerlendirmeye geçilerek ek hop ortadan kaldırıldı ve gecikme ciddi biçimde azaltıldı
- P50 gecikmesi yaklaşık 1 ms azaldı, P90 onlarca ms düştü, P99.5 ise yüzlerce ms'den onlarca ms'ye indi ve en fazla %90 iyileşme sağlandı
-
Operasyonların sadeleşmesi ve kaynak verimliliği
- Hız sınırlamanın service mesh data plane içinde merkezileştirilmesiyle altyapı sadeleşti
- Kota uygulamak için ayrı veri deposu veya önbellek katmanı gerekmiyor
- Daha önce yalnızca hız sınırlama için ayrılmış çok sayıda Redis instance'ının kapatılmasıyla anlamlı hesaplama verimliliği elde edildi
-
Kararlılığın artması ve incident müdahalesi
- Dağıtımdan sonra GRL, spike'lar, failover'lar ve retry storm durumlarında tekrar tekrar aşırı yükü önledi
- Service mesh içinde fazla trafik olasılıksal olarak shed edilerek ani giriş yükü artışlarında bile tutarlı yanıt süreleri korundu
- Kritik bir servis, 22K'dan 367K RPS'ye çıkan 15 kat trafik artışını bozulma olmadan kaldırdı
- DDoS saldırıları, iç sistemlere ulaşmadan önce absorbe edildi
- Incident müdahalesi sırasında production engineering ekipleri, GRL ile belirli yüksek trafikli çağıranlara veya prosedürlere hedefli hız sınırlama uygulayabildi; control plane güncellemeleri her saniye yayıldığı için birkaç saniye içinde aşırı yüke müdahale edilebildi
- Servis yeniden dağıtımı olmadan belirli trafik desenleri hızlı ve güvenli biçimde throttling edilebildi
- Toplam ölçekte sistem, saniyede yaklaşık 80 milyon istek üzerinde 1.100'den fazla serviste dinamik kota uyguluyor
Hız sınırlamanın otomasyonu: Rate Limit Configurator (RLC)
-
Manuel yapılandırmanın sınırları
- GRL uygulamayı birleştirmiş olsa da limit tanımlama hâlâ manuel çalışma gerektiriyordu
- Servis sahipleri, YAML dosyalarında çağıran ve prosedür bazında kota tanımlıyor, trafik desenleri değiştikçe bunları ayarlıyordu
- Yüzlerce mikroservisin sürekli evrildiği ortamda statik yapılandırmalar hızla güncelliğini yitiriyordu
- Çok sıkı olursa normal trafik zirvelerinde bile throttling oluşuyordu
- Çok gevşek olursa gerçek kapasiteye kıyasla aşırı yüksek limitler nedeniyle koruma etkisi zayıf kalıyordu
- Değişiklikler dashboard analizi ve manuel ince ayara dayanıyordu
-
RLC nasıl çalışıyor
- RLC (Rate Limit Configurator), GRL yapılandırmalarını otomatik olarak güncel tutuyor
- Sabit bir zamanlamada ya da yapılandırma değiştiğinde şu döngü hemen çalışıyor:
- Uber'in gözlemlenebilirlik platformundan son birkaç haftaya ait metriklerin toplanması
- Geçmiş zirveler ve buffer payı kullanılarak çağıran ve prosedür bazında güvenli limitlerin hesaplanması
- Güncellenmiş yapılandırmanın paylaşılan yapılandırma deposuna yazılması
- Var olan control plane üzerinden GRL'ye yeni limitlerin itilmesi
- Bu kapalı döngü süreç sayesinde limitler gerçek trafikle birlikte evriliyor ve manuel müdahale en aza iniyor
-
Ölçeklenebilir tasarım
- RLC baştan itibaren birden fazla hız sınırlama hesaplama stratejisini destekleyecek şekilde tasarlandı
- Varsayılan politika geçmiş RPS verisine dayanıyor; ancak yeni politika türleri modüler biçimde eklenebiliyor
- Harita ve konum verisi servisleri gibi bazı alanlar, geçmiş eğilimler yerine gelecekteki yükü tahmin eden öngörü modelleri kullanarak trafik tahmini ve önceden planlanmış kapasiteyi yansıtıyor
- Önceden belirlenmiş sözleşmesel veya operasyonel uzlaşılara dayanan sabit kota atama yaklaşımı da destekleniyor
- Modüler arayüz sayesinde her servis alanı, yakın gerçek zamanlı trafik deseni, öngörü veya statik kota arasından uygun hesaplama mantığını seçebiliyor
-
Shadow mode ve doğrulama
- Güvenlik için limitler shadow mode'da oluşturulup izlenebiliyor, ancak uygulanmayabiliyor
- Servis sahipleri, production ortamında hız sınırlamanın davranışını gözlemledikten sonra etkinleştirme yapabiliyor
- Özel dashboard'lar ve uyarılar, gözlemlenen trafik ile sanal drop'ları görselleştirerek dağıtımdan önce güven sağlıyor
-
Otomasyonun etkisi
- Binlerce hız sınırlama kuralı, manuel düzenleme olmadan otomatik olarak güncelleniyor
- Tüm servisler genelinde aynı formül ve veri kaynağıyla tutarlı politikalar üretiliyor
- Farklı politika türleri sayesinde ekipler iş yüklerine en uygun hesaplama mantığını seçip genişletebiliyor
- Shadow mode ile uygulama öncesinde doğruluk güvence altına alınıyor
Gelecek yönü
- RLC devreye alındıktan sonra da buffer ayarlarının genişletilmesi, yapılandırma değişikliklerinin etki alanını azaltmak için bölge bazlı hız sınırlama ve canlı trafiğe tepkiselliği artırmak için güncelleme sıklığının artırılması üzerinde çalışılıyor
- Uber'in throttler katmanı, uygulamaya daha yakın noktada ek aşırı yük koruması sağlıyor
- Bugün GRL, Uber'in çok katmanlı kararlılık yığınının temel bileşenlerinden biri olarak, aşırı yük altında bile platformun kararlılığını ve adaletini koruyor
Henüz yorum yok.