Sıkıcı kodla 1 milyar web isteğini karşılama deneyimi
(notes.billmill.org)- ABD Medicare sağlık sigortası planı karşılaştırma sistemini yeniden kurarken, yalnızca kanıtlanmış teknolojilerle (Postgres, golang, React vb.) oluşturulmuş basit bir yapıyla 1 milyardan fazla web isteğini istikrarlı biçimde karşılama deneyimini paylaşıyor
- Mimarinin hedefi sadelik ve kararlılık olacak şekilde tasarlanarak ortalama 10 ms’nin altında yanıt süresi ve çok düşük arıza oranı elde edildi
- Yenilik (innovation token) yalnızca çekirdek yapısal ayrımlarda minimum düzeyde uygulandı (3 büyük modül, gRPC iletişimi); bunun dışındaki her yerde sıkıcı ama güvenilir yöntemler tercih edildi
- DB şema yönetimi, ETL hattı, testler, loglama, dokümantasyon, CLI araçları dahil tüm operasyonel unsurlar tekrarlanabilir ve basit biçimde kurularak tüm ekibin kolayca anlayıp bakım yapabildiği bir sistem tamamlandı
- Sürekli kalite yönetimi ve güçlü ekip çalışmasının, büyük ölçekli kamu projelerinde de işe yaradığını canlı bir örnekle gösteriyor
Serving a billion web requests with boring code
High level
- 2 buçuk yıl boyunca ABD hükümetinin Medicare plan karşılaştırma ve satın alma web sitesinin baş geliştiriciliğini yaptı
- Günde ortalama 5 milyon API isteği işlendi; ortalama yanıt süresi 10 ms’nin altında, isteklerin %95’i 100 ms’nin altında kaldı
- Arıza oranı çok düşüktü; gerçekten bir mühendisin gece çağrıldığı durumlar bir elin parmaklarını geçmeyecek kadar azdı
- Postgres, golang, React gibi herkesin anlayabileceği, kanıtlanmış teknolojilerle kurularak sürekli olarak kararlı bir sistem oluşturuldu
Boring über alles
- En yüksek öncelikli ilke, yalnızca "sıkıcı ve kanıtlanmış teknolojileri" tercih etmekti (Choose Boring Technology)
- Yenilik denemeleri yalnızca gerçekten gerekli yerlerde, innovation token dikkatle harcanarak yapıldı
- Karmaşık ve gösterişli çözümler yerine kararlı ve açık teknolojiler ile süreçler tercih edildi
The boring bits
- Postgres: Veri saklamanın merkezi; hem güvenilirlik hem ölçeklenebilirlik sağladı. Karmaşık aramalar da (ör. faceted search) Postgres ile çözüldü
- golang: Derleme ve dağıtım hızlı, üretilen binary çıktılar net. Hata yönetimi sezgisel ve yeni ekip üyeleri de kolayca uyum sağlayabiliyor
- React: SPA framework’leri arasında en çok kanıtlanmış olanıydı ve ekip üyeleri zaten buna hakimdi. Erişilebilirlik ve farklı cihaz desteği de önemli etkenlerdi
- Uzun vadede bundle boyutu ve hız düşüşü sorunları ortaya çıktı, ancak o dönem için zamanında sonuç üretmek adına en iyi tercihti
The innovation tokens
- Modular backend: Tüm backend, ne mikroservis ne de monolit olacak şekilde 3 büyük modülden oluşuyordu (
druginfo,planinfo,beneinfo)- Her modül ayrı bir Postgres DB kullanıyor ve veri paylaşımı yalnızca gRPC üzerinden yapılıyordu
druginfo: Eczane, sigorta, paketleme gibi kombinasyonların geometrik olarak arttığı ilaç fiyat bilgilerini çok ayrıntılı biçimde indeksliyor; karmaşık ön işleme ve performans optimizasyonu gerektiriyorduplaninfo: Her gün yeni CMS verisi alıyor ve tüm DB sıfırdan yeniden oluşturuluyordu (değişmezlik korunuyor)beneinfo: Gerçek abone bilgilerini tutan tek bölüm; hassas PII (kişisel bilgiler) minimum düzeyde saklandı. Veri sızıntısı riskini azaltmak için tasarım ve operasyona özel dikkat gösterildi
- gRPC: Modüller arası iletişim arayüzlerini kodla açıkça tanımlama avantajı sundu. Otomasyon araçlarıyla entegrasyonu da çok iyiydi
- Ancak derleme, araç zinciri ve hata ayıklama daha karmaşıktı; JSON API’ye kıyasla sezgiselliği daha düşüktü
grpc-gatewayile web istemcisi desteği sağlandı ve yüksek trafik sorunsuz biçimde işlendi
Strict backwards compatibility
- API ve veritabanında geriye dönük uyumluluk katı biçimde korundu
- Açık API’deki alanlar asla silinmedi; güvenlik sorunu olmadığı sürece ömür boyu korundu
- DB sütunlarında ekleme serbestti, ancak silme işlemi çok aşamalı doğrulamadan geçti (referansları kaldırma → birkaç hafta bekleme → gerçek silme)
- Bu disiplin, yüksek değişim hızının yanı sıra kararlı dağıtım ve operasyonun temel dayanağı oldu
Faceted search
- ElasticSearch yerine yalnızca Postgres ile faceted search uygulandı
- İyi indekslenmiş bir plan tablosunda koşulları birleştiren 250 satırlık tek bir fonksiyon tüm arama mantığını yönetti
- İş gereksinimlerine odaklanıldı ve gereksiz karmaşıklık olmadan basit bir çözüm üretildi
Database
-
creation
- DB şeması numaralandırılmış
.sqldosyalarıyla yönetildi; sırayla yüklenerek güvenilirlik sağlandı planinfo/beneinfoDB’leri her gün yeniden oluşturulduğu için migration gerekmedi. Sürüm uyumsuzluğu gibi yapılandırma hatalarında uygulama hiç başlamayacak şekilde tasarlandı
- DB şeması numaralandırılmış
-
ETL
- Veri kaynağı bazlı shell script’lerle S3’e yükleme yapıldı → cron ile EC2 instance’ı en güncel ETL kodunu/verisini çekip yeni bir RDS DB oluşturdu
- Postgres’in COPY komutu yoğun biçimde kullanılarak INSERT yerine büyük veri yüklemeleri verimli şekilde işlendi
- Her gün 2 ila 4 saat içinde yüz milyonlarca satırlık veri yeni DB’ye aktarılabildi
-
models
- xo kütüphanesiyle DB modelleri otomatik üretildi; custom template’lerle ekibe uygun kod oluşturuldu
-
testing
- En büyük hata,
sqlmockile aşırı test yazmak oldu; verinin sık değiştiği bir ortamda bunun bakımı çok zahmetliydi - Gerçekten değişmez bir DB için gerçek DB üzerinde test yapmak daha verimli olurdu
- En büyük hata,
-
Local database for development
- Her tablo için kısmi veri otomatik üreten script’lerle, geliştiriciler küçük bir yerel DB üzerinde gerçek veriye dayalı test ve geliştirme yapabildi
- DB büyümeden önce böyle araçlar hazırlamak tüm ekibin geliştirme verimliliğini ciddi biçimde artırıyor
Miscellaneous tooling
- Çeşitli operasyon ve gözlemlenebilirlik otomasyonları için CLI araçları shell script’lerle geliştirildi; tüm yardımcı işlevler tek yerde toplandı
- Splunk loglarını Slack komutuyla anında grafiğe dökmek gibi sahaya dönük araçlar aktif biçimde geliştirildi ve kullanıldı
Logging
- İstek sisteme girdiği anda bir request id üretildi ve bu kimlik tüm log bağlamına eklenerek her yerden izlenebilir hale geldi
- zerolog ile güvenli ve düzenli bir loglama yapısı kuruldu
- Sistemin giriş/çıkış noktaları ve istisnai durumlar gibi kritik anlarda mutlaka log bırakıldı
Documentation
- GitHub markdown dokümanları sphinx-book-theme ile dönüştürülerek wikibook olarak işletildi
- Tüm ekip üyeleri dokümantasyona aktif katkı sundu; tüm sistem belgelerinin tek yerden bulunması sağlandı
- Güçlü dokümantasyon kültürü, ekibin büyümesi, bakım ve yeni çalışanların onboarding verimliliğini ciddi biçimde artırdı
Runtime integrations
- İstemcinin performansı düşüren talepleri (analitik script eklenmesi vb.) mümkün olduğunca ikna edilerek sınırlandırıldı
- Sorgular da browser runtime yerine build-time’da işlenecek şekilde taşınarak hizmet performansı korundu
- Gerçekte tüm müşteri talepleri engellenemediği için bazıları performans düşüşüne yol açtı
And more
- Teknik konuların ötesinde, olumlu ve işbirlikçi ekip atmosferi ile güçlü motivasyonun büyük ölçekli sistem başarısının asıl itici gücü olduğu vurgulandı
- Küçük ama önemli pratik tercihlerin ve sürekli kalite yönetiminin gücünü hissettiren bir örnekti
18 yorum
Bu sıkıcı şeyi tam 2,5 yıl boyunca mı?!
Faceted Search’in ne olduğunu merak edip baktım, daha fazla okunmaya değer şeyler de var.
https://www.cybertec-postgresql.com/en/faceting-large-result-sets/
https://roaringbitmap.org/about/
https://github.com/cybertec-postgresql/pgfaceting
sıkıcıhakkında yorumlar eğlenceliymiş haha. Başka bir ifadeyle değiştirsek ne iyi olur? Basmakalıp, yaygın?boringkelimesini "sıkıcı" diye çevirmek, aslında asıl anlamını pek yansıtmıyor.boringness, Go'nun tasarım felsefelerinden biri.Sıkıcıymış gibi…
Kore, başı sonu Java memleketi olduğu için ona yabancı geliyor haha
Bence
golangve React, yeni çağın sıradan (boring) kurumsal kodlama dillerinin tamamı.boring->sıkıcıdiye çevirmek de %100 doğru olmadığı için, Koreli okurlara nüansın tam olarak aktarılmadığı görünüyor.Postgres, golang ve React'in sıkıcı dünyasında yaşamak istiyorum
Evet, başlığı görünce ben de bunun nasıl bir şaka olduğunu düşünmüştüm.
Yurt dışında bunun sıkıcı bir stack olduğu düşünülüyor gibi görünüyor.
Aslında Go, sadece web sunucusu yapmak için en kolay seçimlerden biri...
Sanırım ancak Rust ya da FP tarafındaki dillerle geliştirme yapınca sıkıcı olmadığı söyleniyor.
Fazla bariz şeyler... Fazla bariz oldukları için gözden kaçırdığımız önemli noktalar...
Bu yığın, o kadar da sıkıcı görünmeyen bir stack gibi duruyor. Gerçekten sıkıcı olacaksa, herhalde Java 1.8 ve altı sürümler ya da VB falan çıkmalı diye biraz saygısızca bir düşünceye kapılıyorum.
Orijinal metinde
boringile ilgili bir bağlantı var; içeriğe bakınca buradaboringkelimesi "fazlasıyla alışıldık" anlamında kullanılıyor gibi görünüyor.experienced,verified,skillfulgibi daha uygun kelimeler varken özellikleboringkullanılması, dikkat çekme niyeti varmış gibi görünüyor.Yazmasının sıkıcı olduğundan değil de, çok fazla kullanıldığı için sıkıcı bir demirbaş stack olarak ifade etmiş olmaları mümkün değil mi?
Linux çekirdeği 2.6.29 civarında...
gRPC kullanmış olması bile... haha
Ben de ilk olarak,
golangın sıkıcı mı olduğu? diye düşündümAma
classic aspseviyesindeyse sıkıcı denebilir sanırım