Temeller
İki bağlantı noktasındaki iki Router ekseni (8080 veri düzlemi, 8090 yönetim düzlemi), aynı paylaşılan AppStateöğesinden oluşturulmuştur. Veri düzlemi herhangi bir rotada bir API anahtarı gerektirir; Düzlem yönetimi özel bir JWT izleyici konsolu gerektirir; iki mekanizma asla örtüşmez. Hız sınırlaması iki kez uygulanır: kimlik doğrulamadan önce IP'ye göre, ardından kimlik doğrulaması yapılan aktöre göre. Devre kesici global bir ara yazılım değildir: hizmet başına (ve PostgREST için ayrılmış hedef başına) doğrudan proxy kodunda çağrılan bir nesnedir. Ve son proxy, rotaya bağlı olarak aktarımı değiştirir - bazen HTTP yöntemine veya veritabanı aramasına göre: trafiğin çoğu için NATS isteği/yanıtı, depolama için doğrudan HTTP akışı, üç gerçek zamanlı değişken ve özel Postgres CRUD.
Tek bir ağ geçidi, iki farklı hedef kitle
Veri düzlemi trafiği, SDK'dan veya bir istemci uygulamasından gelir: herhangi bir genel API'ye yakın bir kötüye kullanım profiline sahip, API anahtarıyla kimliği doğrulanan bir dizi anonim istek veya istek. Trafik yönetimi düzlemi, bir projenin yönetim arayüzü olan Studio'dan gelir ve hassas işlemleri gerçekleştirir: proje oluşturma, anahtar rotasyonu, kiracının günlüklerinin okunması. İkisi ortak bir hedefi paylaşıyor (aynı dahili hizmetlere vekil olarak geliyor: aura-auth, aura-db, aura-storage, vb.) ancak aynı risk yüzeyini paylaşmıyor.
Her ikisini de aynı yönlendiriciden geçirmek, iki kötü seçenek arasında seçim yapmayı gerektirir: Studio CORS, genel SDK (Access-Control-Allow-Origin: *) için gerekli joker karakteri devralır veya SDK, dahili bir kontrol paneli için tasarlanmış kısıtlı bir kaynak listesini devralır. Aura-gateway kodu, bu gerilimi main.rs'den ayırır: her biri kendi CorsLayer jokerine sahip iki ayrı Router- veri düzlemi tarafında yetkilendirilmiş, reddedilmiş ve yönetim düzlemi tarafında bir hata olarak günlüğe kaydedilmiş.
İki axum Yönlendirici, bir paylaşılan AppState
Ayırma ayrı bir dağıtım değildir: iki plan aynı süreçte, aynı AppState üzerinde çalışır (Postgres havuzları, NATS istemcisi, Moka önbellekleri, devre kesiciler). Yalnızca Router yapısı farklılık gösterir; her biri başlangıçta bir kez çağrılan ve iki ayrı TcpListenertarafından sunulan iki özel işlev aracılığıyla.
İki rota grafiği aynı tabandan başlar, service_routes(): aynı proxy işleyicileri (db_proxy, storage_proxy, functions_proxy…), her birine özel ek rotalarla birlikte her iki plana da monte edilir. Aynı işleyicilerin yeniden kullanılması, proxy'nin iki kez uygulanmasını önler; Yalnızca ara katman yazılımında farklılık, bir güvenlik sınırı elde etmek için iş mantığının kopyalanmasını önler. Arka ucunuzun kendisi çok hizmetli bir Kargo çalışma alanı olarak yapılandırılmışsa, Kargo çalışma alanı mimarisi kılavuzumuza bakın — ağ geçidi, bu bölümdeki diğer kasalardan yalnızca biridir.
Kimlik doğrulama girişte farklılaşıyor
Veri düzleminde, bir avuç gerçek genel yol (/health, JWKS, kayıt uç noktaları) dışında tüm rotalarda API anahtarı zorunludur. apikey veya X-API-Key başlığı olarak veya yalnızca WebSocket ve SSE akış rotaları için ?apikey=parametresi olarak hareket eder. Kod, bir service_role anahtarı için bu son modu açıkça yasaklar: erişim günlüklerinde, OTEL izlerinde ve Yönlendiren başlığında bir URL anahtarı sızdırılır. Veri düzlemi tarafında JWT isteğe bağlı olarak kalır: JWT olmadan arayan kişi anonolarak kalır; onunla birlikte authenticatedolur.
Yönetim düzleminde API anahtarı mevcut değildir: yalnızca hedef kitlesinin tam olarak aurabase-contrololması gereken bir JWT konsolu kabul edilir. Rol, belirtecin kendisi tarafından taşınmaz; kullanıcının proje → kuruluş ilişkisi aracılığıyla devralınan, projenin sahibi kuruluştaki üyeliğinden gelen her istek üzerine yeniden hesaplanır.
| Jeton gerekli | API anahtarı (apikey / X-API-Key), her zaman | JWT konsolu (Yetkilendirme: Taşıyıcı), her zaman |
|---|---|---|
| Rol yükseltmesi | İsteğe bağlı JWT: anon → kimliği doğrulanmış | Kuruluştan devralınan RBAC (sahip/yönetici/geliştirici/görüntüleyici) |
| Sorgu dizesini girin | Yalnızca WS/SSE'de tolere edilir; service_role için asla kabul edilmez | Geçerli değil |
| Beklenen kitle | Hedeflenen proje (yolun UUID'si) | "aurabase kontrolü" düzeltildi |
| CORS | Joker karaktere * izin verildi | Joker karakter reddedildi, yalnızca Studio kökenleri |
Ara Yazılımın Gerçek Düzeni (Ve Neden Önemlidir)
axum ara yazılımı ardışık .layer() çağrılarıyla yığınlar - ve yürütme sırasını yöneten kural pratikte şaşırtıcıdır: yerleştirilen LAST .layer() OUTTERmost katmanı olur, dolayısıyla gelen bir istek tarafından ilk geçilen ve yanıt iznini en son gören katman olur. Dolayısıyla dosyanın doğrusal okunması, gerçek yürütme sırasının ters sırasını verir.
request_id ara yazılımı, X-Request-Id üstbilgisini yalnızca RESPONSE'da ayarlar, hiçbir zaman gelen istekte ayarlamaz. AccessLogLayer dosyada kendisinden sonra yerleştirildiğinden (bu nedenle daha harici olduğundan daha önce geçildiği için) request_id alanının yakalanması, zincirin ilerisinde oluşturulan tanımlayıcıyı değil, istemcinin gönderdiği şekilde başlığı okur. Arayan herhangi bir X-Request-Idsağlamadıysa, erişim günlüğü satırı boş bir alanla ayrılır, geri dönen yanıt ise yeni oluşturulmuş bir UUID taşır. Gizli bir kusur değil — bir .layer() dizesinin yazılma sırasının, ona atfettiğimiz mantıksal sıra hakkında hiçbir şeyi garanti etmediğini hatırlatmak isteriz.
Hız sınırlaması: Önce IP, sonra aktör
Hız sınırlaması, zincirde iki farklı zamanda, iki ayrı geçişte uygulanır. İlki, kimlik doğrulamadan ÖNCE çalışır ve IP adresine göre sınırlar - genel yollarda bile aktif olan genel bir taşkın önleme filtresi: bu olmadan, kimliği doğrulanmamış bir akış, bir JWT kontrolünü tetiklemeden günlük toplama gibi pahalı bir uç noktaya zarar verebilir. İkincisi, kimlik doğrulamanın SONRA çalıştırılır ve kimlik doğrulamanın az önce eklediği iddiaları kullanarak aktöre (API anahtarı veya kullanıcı) göre sınırlandırır: bu, faturalandırma ve planlar için dikkate alınan gerçek ürün kotasıdır.
Uygulama, yerel hesaplama için governor sandığına (jeton kovası), ağ geçidi örnekleri arasında dağıtım için kayan pencere Lua Redis komut dosyasına ve Redis kullanılamıyorsa yerel bir geri dönüşe (Moka önbelleği) dayanır. Depo varsayılanları: 100 istek/saniye, 1000'lik artış.
Devre kesici bir katman değildir, hedef başına bir nesnedir
Zincirin geri kalanından farklı olarak devre kesici HİÇBİR .layer()öğesinde görünmez. AppState hizmet başına bir CircuitBreaker örneği taşır (kimlik doğrulama, veri tabanı, gerçek zamanlı, depolama, işlevler, bildirimler, yapay zeka, hazırlayıcı, kontrol) ve isteği gerçekleştirmeden önce try_acquire_probe()'yi çağıran, ardından sonuca bağlı olarak record_success() veya record_failure()'yi çağıran, yönlendirici değil, proxy kodunun kendisidir.
PostgREST'in durumu farklıdır: adanmış topolojideki projeler (projeye özel Postgres ve PostgREST) paylaşılan bir hata alanına sahip değildir; her PostgREST işlemi kendi hedefidir. Bu nedenle ağ geçidi, çözümlenmiş hedefe göre indekslenen, anında doldurulan ve etkin olmayan girişleri ortadan kaldıran bir taramayla her 60 saniyede bir temizlenen bir devre kesiciler tablosu tutar: bu temizleme olmadan, her yeni özel proje asla kaybolmayan bir giriş ekleyecektir.
Araştırma belirteci, hiçbir zaman açıkça tüketilmediği takdirde Drop olarak döndürülür; bu, bir istekteki tüm girişimler, onu serbest bırakacak bir şubeye ulaşmadan zaman aşımına uğradığında kullanışlıdır. Ve otomatik tekrar yürütme yalnızca NATS tarafında teslim edilmediğine dair katı bir kanıt olması durumunda tetiklenir (NoResponders): basit bir ağ geçidi zaman aşımı, isteğin gerçek teslimiyle ilgili hiçbir şeyi kanıtlamaz ve tekrar oynatmak, onu iki kez çalıştırabilir.
Son bağlantı: NATS veya doğrudan HTTP, asla rastgele değil
Nihai proxy tek bir protokolü geriye doğru konuşmaz ve seçim rotaya göre sabitlenmez: HTTP yöntemine, hatta bir veritabanı aramasına bağlı olabilir. Trafiğin çoğu için (kimlik doğrulama, işlevler, bildirimler, kontrol ve veri tabanının çoğunluğu), ağ geçidi, HTTP isteğini bir NATS zarfı içinde serileştirir ve bunu hizmete ayrılmış bir konuya istek/yanıt olarak gönderir; bu, bu RPC türü trafik için klasik bir HTTP proxy'sinden önemli ölçüde daha hızlı olduğu kodda belgelenen, TCP anlaşması olmayan bir gidiş-dönüş yolculuğudur.
Depolama, gerçek zamanın üç çeşidi (yayın/kanallar/varlık için WebSocket, SSE ve REST) ve - koşullu olarak - Postgres CRUD istekleri bu yoldan çıkar ve canlı, havuza alınmış bir HTTP istemcisinden geçer. Depolama bu seçimi açıkça yaptı: Bir ikili gövdeyi bir NATS zarfı içinde kodlamak, onu serileştirmeyi, her iki uçta tamamen belleğe yüklemeyi ve NATS mesaj boyutu sınırının altında kalmayı gerektirir; bu, büyük nesneler için gerçek bir maliyettir. WebSocket ve SSE, istek/yanıt anlambilimine tolerans göstermez: bir protokol yükseltmesinin ve açık kalan bir akışın NATS eşdeğeri yoktur.
En ilginç durum, işleyicisi her istek üzerine kendisi karar veren /v1/db/*'dir: yönetim rotaları (şema, politikalar, ham SQL) her zaman NATS'de aura-db'ye gider, bir PUT her zaman NATS'ye gider (PostgREST tam değiştirmede 405 döndürür), bir MongoDB projesi her zaman NATS'ye gider - ve yalnızca özel bir PostgREST örneği çözümlenmiş bir Postgres projesindeki CRUD Direct HTTP'ye gider. Bu özel örnek çözümlenmezse ağ geçidi, paylaşılan bir PostgREST'e geri dönmek yerine 503 yanıtı verir: başarısız bir şekilde kapatıldığı varsayılır, azaltılmış bir sessiz geri dönüş değil. güvenlik üstbilgileri (katı CSP, CORS kimlik bilgileri yok), yanıt ağ geçidinden ayrılmadan önce zincirin en sonuna yerleştirilen tüm bu yollara eşit şekilde uygulanır.
Genel bir zaman aşımı değil, rota başına bir zaman aşımı bütçesi
Ağ geçidi, genel zaman aşımı yerine GRUBU BAŞINA TimeoutLayer rota uygular; bu, ara yazılım sırası ile aynı yığınlama mekaniğine bağlı bir seçimdir. Edge işlevleri rotası diğerlerinden çok daha uzun bir bütçeye ihtiyaç duyar (bir işlev yasal olarak birkaç dakika boyunca çalışabilir): depo varsayılanı rotaların çoğu için 30 saniyedir, /v1/functions/*için ise 380 saniyedir.
Her şeyin üstüne tek bir global TimeoutLayer istiflemek, her iki grubu da aynı sınırda keserdi: daha içeriye yerleştirilen daha uzun bir zaman aşımına bakılmaksızın, her zaman en dış konuma yerleştirilen en kısa zaman aşımı kazanır. Bu nedenle, işlevlere ayrı bir bütçe vermenin tek yolu, bunların ASLA ortak bir pakete girmemesidir: yolların her bir dalı, iki yönlendiricinin birleşmesinden önce yerleştirilen kendi TimeoutLayeröğesini taşır ve sonrasında herhangi bir genel zaman aşımı uygulanmaz.
Bu modeli başka bir yerde yeniden üretin: kontrol listesi
- Hizmete göre değil, PLAN'a (teşhir yüzeyi) göre ayırın: Güvenliği ihlal edilmiş bir genel SDK, asla yönetici kontrol panelinizin CORS kaynak listesine ulaşmamalıdır.
- İki ayrı dağıtım yerine tek bir paylaşılan durumu koruyun; iş mantığını çoğaltmak, bir yönlendiriciyi çoğaltmaktan daha maliyetlidir.
- GERÇEK ara yazılım sırasını, asla dosyanın doğrusal okumasından değil, son
.layer()'den izleyerek kontrol edin. - IP başına hız sınırlamasını (kimlik doğrulamadan önce) aktör başına kotadan (sonra) ayırın; aksi takdirde, kimliği doğrulanmamış bir akış, sınırsız maliyetli doğrulamaya neden olur.
- Kesiciyi proxy'de gerçek ağ çağrısına mümkün olduğunca yakın yerleştirin ve hata etki alanı paylaşılmadığında hedefe göre boyutlandırın.
- Bir isteği yalnızca teslim edilmediğinin kanıtlanması durumunda yeniden oynatın; asla basit bir zaman aşımında oynatmayın.
- Yönlendiricileri birleştirmeden önce her rota grubuna kendi zaman aşımı bütçesini verin; asla en uzun bütçenin üzerine yazacak global bir
TimeoutLayervermeyin.