EMZETT.
Giriş yap

Çok kiracılı mimari

Kısaca: Tek bir uygulamanın birbirinden bağımsız birkaç müşteriye (“kiracıya”) aynı anda hizmet verdiği bir yazılım mimarisi — her birinin kendi verileri vardır ve çoğu zaman kendi alt alan adlarıyla ayrılır.

Biraz daha ayrıntılı: Tipik kalıp: customer1.my-platform.com, customer2.my-platform.com vb. hepsi aynı kod tabanında, ancak kiracı başına ayrı verilerle çalışır. Bu genellikle bir joker karakterli DNS kaydı ve parayı birkaç alıcıya dağıtabilen bir ödeme çözümü (örneğin Stripe Connect) gerektirir.

Bizim bağlamımız: Emzett için uzun vadeli bir hedef — mağaza platformunun daha sonra başkalarına “kiralanması” amaçlanıyor, her müşteri kendi alt alan adında. Yol haritasına göre son ve en büyük genişleme adımı.

Ayrıntılı

Üç izolasyon derecesi

Çok kiracılı sistemlerde merkezî tasarım kararı, farklı kiracıların verilerinin NASIL ayrı tutulacağıdır — “gevşekten” “sıkıya” kabaca üç yaygın yaklaşım vardır:

  1. tenant_id sütunlu paylaşılan tablolar — tüm kiracılar aynı tablolarda yaşar, her satır bir kiracı tanımlayıcısı taşır ve her sorgu ek olarak buna göre süzer. İşletmesi en kolay olanı (bir veri tabanı, bir şema, bir bağlantı havuzu), ancak unutulmuş bir WHERE tenant_id = ... süzgeci müşteriler arasında veri karışmasına yol açabilir — pratikte çoğu zaman veri tabanı düzeyinde satır düzeyinde güvenlik politikalarıyla önlenen ciddi bir güvenlik riski (Postgres bunu yerel olarak destekler: bir politika, uygulama kodunda unutulmuş bir WHERE yan tümcesinin bile yabancı satır döndürmemesini sağlar, çünkü veri tabanı kendisi süzer).
  2. Kiracı başına bir şema — aynı veri tabanı, ancak her kiracı kendi PostgreSQL şemasını (ad alanı, örneğin public.orders yerine tenant_customer1.orders) alır. 1. yaklaşımdan daha iyi izolasyon (kötü yazılmış bir sorgu, açıkça adreslemeden yanlışlıkla başka bir şemaya erişemez), ancak migrasyonların her şema için ayrı çalışması gerekir — yüzlerce kiracıyla fark edilir bir işletme yükü.
  3. Kiracı başına bir veri tabanı — azami izolasyon (kiracı A’daki bir veri tabanı hatası ya da performans sıçraması kiracı B’yi hiç etkilemez), ancak özellikle çok sayıda küçük kiracıyla işletmesi en zahmetli olanı: her veri tabanının kendi yedekleri, kendi izlemesi, kendi migrasyonları vardır ve açık bağlantı sayısı kiracı sayısıyla doğrusal artar.

Birçok büyük SaaS platformu (örneğin Slack, ilk mimarisinde) 1. yaklaşımla başlar ve müşteriler büyüdükçe ve uyumluluk gereksinimleri arttıkça (bazı kurumsal müşteriler sözleşmeyle fiziksel veri ayrımı ister) 2. veya 3. yaklaşıma doğru ilerler; çoğu zaman yalnızca en büyük müşteriler için, küçükler 1. yaklaşımı paylaşmaya devam eder (“hibrit” model).

Alt alan adı yönlendirmesi

Alt alan adı tespitinin kendisi genellikle ara yazılım/proxy katmanında gerçekleşir: isteğin Host başlığı ayrıştırılır, kiracı ondan türetilir ve bu bağlam tüm sonraki veri tabanı sorgularına iletilir (örneğin bir istek bağlamı veya ara yazılım tarafından ayarlanan bir değişken aracılığıyla; bu da örneğin Node.js’te AsyncLocalStorage ile tüm istek işlemeye “geçirilir”, onu her işleve açıkça vermek zorunda kalmadan).

// Ara yazılım/proxy katmanında basitleştirilmiş kalıp
const host = request.headers.get("host"); // örn. "customer1.my-platform.com"
const tenant = host?.split(".")[0];

Joker karakterli alt alan adları için DNS bölgesinde uygun bir kayda (*.my-platform.com → aynı sunucu IP’si) ve TLS sertifikasının da bir joker sertifika olmasına (veya Vercel’in özel alan adları için sunduğu gibi alt alan adı başına otomatik sertifika sağlamaya) ihtiyaç vardır; aksi hâlde ziyaretçiler bir sertifika uyarısı alır.

Ödeme dağıtımı

Son müşterilerden kendisi para alan ve bunu ilgili kiracılara iletmesi gereken bir platform için (pazar yeri modeli) normal bir Stripe entegrasyonu yetmez — Stripe Connect bunun içindir: her kiracı kendi (bağlı) Stripe hesabını alır ve ödemeler doğrudan ya da platform üzerinden komisyon paylaşımıyla (“application fee”) yönlendirilebilir; platformun kendisinin tüm kiracı gelirleri için yasal alıcı olarak davranması gerekmez.

Ayrıca bak: DNS kayıtları