PRODEgemen Avrupa BaaS platformuKontrol Panelini Aç →

Mühendislik · 10 dk. okuma

Çoklu hizmet Rust arka ucu için kargo çalışma alanları

Affane Daylami · Fondateur · 12 Ağustos 2026

Bloga geri dön

Rust'taki çoklu hizmet arka ucu hemen aynı soruyu gündeme getiriyor: hizmet başına bir depo mu, yoksa tek bir Kargo çalışma alanı mı? Aurabase ikinci seçeneğe karar verdi. On bir hizmet, bir CLI ve beş paylaşılan kitaplık, herkes için tek bir Cargo.lock ile tek bir Cargo.toml kökünde bulunur. İşte bu çalışma alanının nasıl oluşturulduğu, satır satır okunarak.

Bu İngilizce metin, Fransızca orijinalinden otomatik olarak oluşturulmuştur ve henüz incelenmemiştir.
Bu sayfa otomatik olarak çevrildi. İngilizce versiyonu yetkilidir.

Bu durum için icat edilmiş eğitici bir örnek değil. Aşağıdaki her kod parçacığı, Aurabase kökü Cargo.toml'den ve bugün depoda mevcut olan sandık bildirimlerinden geliyor; bu makale için bunları yeniden okurken bulduğumuz ve yayınlanmadan önce sessizce düzeltmek yerine olduğu gibi belgelediğimiz iki tutarsızlık da dahil.

Temeller
  • Aurabase root Cargo çalışma alanı 18 açık üye bildirir: 11 hizmet, aura-cliCLI, 5 paylaşılan kütüphane ve aurabase-rs SDK — resolver = "2" ve tek bir Cargo.lockaltında.
  • [workspace.dependencies] paylaşılan sürümleri merkezileştirir; her sandık kendi numarasını ayarlamak yerine { workspace = true } ile miras alır - bir sandığın sessizce geçersiz kılınması durumu hariç.
  • services/ altındaki bir klasör, otomatik olarak çalışma alanının bir üyesi değildir: members listesi, tam olarak Rust olmayan kodu hariç tutabilmek için bir glob değil, açık bir listedir.
  • [profile.release] tüm çalışma alanına yalnızca bir kez uygulanır; panic = "unwind" gibi bir seçim aynı anda on bir hizmetin tamamına uygulanır.
#
Neden bir çalışma alanı

Hizmet başına bir depo mu, yoksa yalnızca bir Cargo.lock mu?

Bir çalışma alanı Cargo birden fazla kasayı tek bir Cargo.lock ve tek bir hedef dizin altında gruplandırır; Rust'un paket yöneticisinin bu durum için sağladığı işlevselliktir. Her biri kendi deposunda bulunan on bir ayrı Rust ikili dosyası, ilk bakışta daha bağımsız görünüyor. Pratikte bu, on bir farklı Cargo.lock, zaman içinde farklılık gösterebilecek on bir sürüm çözünürlüğü anlamına gelir ve iki hizmetin aynıaxum veya sqlxsürümünü derleyeceğinin garantisi yoktur.

A Cargo workspace solves this at the package manager level, not the team discipline level. All members share a single Cargo.lock at the root: a common dependency is resolved once, to an identical version, for the entire graph. This is also what makes a cross-service refactor (changing a signature in aura-core, for example) visible to a single cargo build --workspace, rather than discovered service by service in production. This is one of the choices that distinguishes our 100% unified Rust core from a heterogeneous stack assembled service by service.

#
Anatomi

Cargo.toml kökü: çözümleyici ve üyeler

Her şey [workspace] bildirimi ve onun memberslistesiyle başlar. Aurabase'de bu liste, services/*gibi genel bir model tarafından oluşturulmak yerine, elle yazılmıştır ve role (hizmetler, araçlar, kütüphaneler) göre gruplandırılmıştır.

Cargo.tomltoml
[workspace]
resolver = "2"

members = [
    # Hizmetler
    "services/aura-gateway",
    "services/aura-auth",
    "services/aura-db",
    # … 8 diğer hizmet (aura-gerçek zamanlı, aura-depolama, aura-ai, …)
    # Araçlar
    "aura-cli",
    # Kitaplıklar
    "libs/aura-core",
    # …4 diğer kitaplık
    "aurabase-rs",
]

resolver = "2" kozmetik bir detay değildir. Cargo'nun çözümleyici v2, build-dependencies işlevselliğini ve hedefe özgü bağımlılıkları (örneğintarget.'cfg(windows)') grafiğin geri kalanından yalıtır; bunlar artık son ikili dosyaya sızmaz. Ayrıca, çalışma alanının onu paylaşan tüm üyeleri arasında aynı bağımlılığın sürümlerini birleştirir: tek bir axum, yalnızca bir kez, on bir bağımsız çözüm değil.

#
Eski

workspace.package: tek sürüm, tek sürüm, prensipte paylaşılır

[workspace.package] bir kez, her kasanın kopyalamak yerine version.workspace = true ile devralabileceği ortak alanları (sürüm, basım, yazarlar, lisans) bildirir.

Cargo.toml (kök)toml
[workspace.package]
version = "0.1.1"
edition = "2021"

# hizmetler/aura-gateway/Cargo.toml
[package]
name = "aura-gateway"
version.workspace = true

Aurabase'in on bir hizmetinin tümü bu modeli takip ediyor. İki kasa sapıyor ve bu, bu makaleyi hazırlarken bulunan iki tutarsızlıktan ilkidir: aura-cli basılı kopyada version = "0.2.0" bildirir ve lib libs/aura-migrations version = "0.1.0" bildirir — her ikisi de çalışma alanının 0.1.1'sinden farklıdır.

Bu ne anlama geliyor?

version.workspace = true isteğe bağlıdır; tarla tarla, sandık sandık. Hiçbir şey bir sandığın kendi numaralandırmasını korumasını engelleyemez - gönüllü olarak (örneğin ayrı olarak yayınlanan bir araç) veya unutkanlık nedeniyle. Bir çalışma alanı denetimi bu sahayı sandık başına kontrol etmeli, mirası üstlenmemelidir.

#
Tekilleştirme

çalışma alanı.bağımlılıklar: bir sandık onu atlamadığı sürece gerçeğin kaynağı

[workspace.dependencies] çeşitli kasalar tarafından paylaşılan bağımlılıkları merkezileştirir. Her hizmet, kendi sürüm sınırlamasını ayarlamak yerine { workspace = true } ile ona başvurur.

Cargo.toml (kök)toml
[workspace.dependencies]
axum = { version = "0.8", features = ["ws", "multipart", "macros"] }
sqlx = { version = "0.8", default-features = false, features = […] }
tower_governor = { version = "0.8", features = ["axum"] }
governor = "0.10"

# services/aura-gateway/Cargo.toml — çalışma alanı yöneticisini devralmaz
governor = "0.8"  # yerel sürüm, farklı

This is the second real discrepancy: the workspace centralizes governor in version 0.10, but aura-gateway redeclares its own line governor = "0.8" instead of inheriting — the gateway applies its rate limiting with the bare governor crate, when aura-auth, aura-ai, aura-db and aura-functions pass through tower_governor in middleware. A workspace does not prevent divergence: it only makes it visible, if we take the trouble to compare.

Ancak tüm bağımlılıklar merkezileştirilmeyi hak etmiyor. wasmtime, [workspace.dependencies]'nin hiçbir yerinde görünmüyor: yalnızca bir kasa, aura-functions, onu WASM çalışma zamanı için kullanıyor, dolayısıyla yerel olarak bildirilmiş durumda kalıyor. Uyguladığımız kural: çalışma alanı seviyesine bağımlılığı daha önce değil, iki veya daha fazla kasanın paylaştığı andan itibaren yükseltin.

#
Dahili grafik

libs/ to services/: neye bağlı

Beş paylaşılan kütüphane (aura-core, aura-crypto, aura-db-adapters, aura-migrations, aura-telemetry) [workspace.dependencies] — aura-core = { path = "libs/aura-core" } içinde yol bağımlılıkları olarak bildirilir ve ardından her hizmet gerçekte hangisine ihtiyaç duyduğunu seçer.

Ortaya çıkan grafik bir dosyadan diğerine okunabilir durumda kalır. aura-gateway yalnızca beş dahili kütüphaneden üçüne bağlıdır — aura-core, aura-crypto ve aura-telemetry. Yönlendirmek için yeterli, PostgREST sepeti için bir JWT imzalayın ve aura-db-adapters veya aura-migrationsdokunmadan izlerini dışa aktarın. aura-provisionerşunu ekler: aura-migrations: bir projenin oluşturulmasından kaynaklanan şema geçişlerini yeniden oynatır.

En dar durum, CI/CD geçişlerini gerçekleştiren özel ikili dosya olan aura-migrator'dir. Aurabase dahili kütüphaneleri arasında, üretimi [dependencies] yalnızcaaura-migrations'yi listeler — aura-core, test amacıyla yalnızca [dev-dependencies]içinde görünür. Bu nedenle üretime teslim edilen ikili dosya herhangi biraura-core kodunu içermez; yalnızca cargo testsırasında mevcuttur.

#
Beton kasa

Bir sandık, birkaç ikili dosya: aura-gerçek zamanlı bölme

Bir çalışma alanı, her yeni konuşlandırılabilir süreç istediğinizde yeni bir üye oluşturmayı gerektirmez. aura-realtime çalışma alanının tek bir üyesi olarak kalır, ancak Cargo.toml aynı paylaşılan [lib]etrafında üç farklı [[bin]] tablosu bildirir.

Cargo.tomltoml
[lib]
name = "aura_realtime"

[[bin]]
name = "aura-realtime"

[[bin]]
name = "aura-realtime-cdc-worker"
path = "src/bin/cdc_worker.rs"

[[bin]]
name = "aura-realtime-ws-front"
path = "src/bin/ws_front.rs"

Manifesto bu ikisi arasındaki sınırı belgeliyor. cdc-worker, Postgres değişikliklerini yoklama yoluyla yakalar ve bir WebSocket sunucusu açmadan pub/sub çekirdeğinde (Client::publish_with_headers) NATS yayınlar — JetStream, aynı hizmette, CDC yayılımına değil, yalnızca örnekler arası mevcudiyet KV'sine hizmet eder. ws-front yalnızca NATS tüketir ve CDC'ye hiç dokunmadan WebSocket/SSE bağlantılarını tutar - tüm ayrıntılar gerçek zamanlı motor belgelerindedir. Her iki ikili dosya da [lib]aracılığıyla aynı RLS filtreleme kodunu paylaşır ancak Kubernetes'te bağımsız olarak dağıtılır ve ölçeklendirilir. Bu, yeni bir çalışma alanı üyesi yerine bir sandıkta birkaç ikili dosya seçmek için doğru sinyaldir: aynı dahili mantık, farklı dağıtım topolojileri.

#
Kaçınılması gereken tuzak

Hizmetler/ altındaki bir dosyanın mutlaka Kargo üyesi olması gerekmez

aura-edge-runtime klasörü Aurabase deposunda mevcut. Ancak herhangi bir Cargo.toml içermez - yalnızca TypeScript (index.ts, envelope.ts) ve kök çalışma alanının members listesinde hiçbir yerde görünmez.

Astuce

Aurabase'in members listesinin services/*gibi genel bir kalıpla değiştirilmek yerine elle yazılmasının nedeni tam olarak budur. Bir glob, Rust olmayan bu klasörü çalışma alanına dahil etmeye çalışmış ve sonuç olarak bir çözümleme hatası yaşanmıştı. Açık bir liste, aynı dili konuşmayan klasörlerin aynı üst öğe services/altında bir arada bulunmasına olanak tanır.

Derste genelleme yapılıyor: services/ alt klasörlerini listeleyerek Rust arka ucunun hizmetlerini saymak yanlış bir sayı verir. Yalnızca Cargo.toml kökü, çalışma alanında gerçekte neyin derlendiği konusunda yetkilidir.

#
derleme

[profile.release]: tüm çalışma alanı için tek bir ayar

Çalışma alanının kökünde bildirilen bir [profile.release], yayın modunda derlenen tüm üyelere uygulanır; ayarlanacak on bir değil yalnızca tek bir yer vardır. Cargo, derleme profili referansındaki tüm mevcut anahtarları belgeliyor; Aurabase yalnızca beşini etkinleştirir.

Cargo.toml (kök)toml
[profile.release]
lto = "thin"          # LTO çapraz kasaları, performans/derleme süresi dengesi
codegen-units = 1     # en iyi genel satır içi
panic = "unwind"   # tokio/axum tarafından izole edilen bir panik → 500, küresel bir çöküş değil
strip = "symbols"
opt-level = 3

"abort" yerine panic = "unwind" seçimi doğrudan dosya yorumunda belgelenmiştir: axum işleyicisindeki panik tokio tarafından durdurulur, görev 500 değerini döndürür ve süreç diğer eşzamanlı istekleri sunmaya devam eder.abort'nin performans kazancı, sorgular arası izolasyon kaybına değmez.

#
pratikte

Alet zincirini ve önemli komutları dondurun

Birleşik bir çalışma alanı bağımlılık sürümlerini belirler ancak derleyicinin kendi sürümünü ayarlamaz. rust-toolchain.toml, kökte, depodaki cargo veya rustc öğesine doğrudan çağrı için araç zincirini (bugünchannel = "1.93") dondurur.

Bu dosya tam olarak sessiz bir kayma meydana geldiği için var: Bir CI eylemi, günün stable kanalını rust-toolchain.tomlokumadan yüklerken, serbest bırakılan Docker görüntüsü donmuş sürümle derlendi. Bir taahhüt, günümüzün kararlı Rust'uyla tüm testleri geçebilir ve daha sonra, birleşmeden önce değil, birleşme sonrasında keşfedilen görüntü yapısında başarısız olabilir. rustupbu dosyaya herhangi bir doğrudan komut için saygı duyar: CI iş akışlarını etkilemeden gerekli olan tek düzeltmeydi.

terminalbash
# Tüm çalışma alanını derleyin
cargo build --workspace

# Tek bir sandığı test edin (tüm çalışma alanını değil)
cargo test -p aura-auth

# Çalışma alanının tamamında katı tüy bırakmama, uyarılar = hatalar
cargo clippy --workspace --all-targets -- -D warnings

# Biçimlendirme
cargo fmt --all

Bir bildirimi çalıştırmadan önce okuyanlar için son bir ayrıntı: aura-cli sandığı, [[bin]] tablosu onu auradeğil aurabaseolarak adlandıran bir ikili dosya derler. Yayınlanan npm sarmalayıcısı @aurabase/cliiki komutu ortaya çıkarır — aura ve aurabase her ikisi de aynı betiğe işaret eder. [[bin]] Kargonun adı, sandığın adı ve npm ambalajının gösterdiği ad üç ayrı şeydir; hiçbiri diğer ikisinden tahmin edilemez.

#
Özet

Kontrol listesi: neyin nerede beyan edileceği

Kargo çalışma alanına her sandık eklediğinizde beş karar ortaya çıkar. Yukarıda ele alınan Aurabase örneğine göre her birinin beyan edildiği yer burasıdır.

Üye listesi[çalışma alanı] üyelerKök - açık liste, asla küresel değil
Paylaşılan sürüm/baskı[çalışma alanı.paket]Kök — version.workspace = true, kasaya göre, isteğe bağlı
2'den fazla kasanın paylaştığı bağımlılık[çalışma alanı.bağımlılıklar]Kök — ardından her sandıkta { çalışma alanı = doğru }
Tek bir tüketiciye bağımlılıksandığın [bağımlılıkları]Yerel olarak, çalışma alanından geçmeden
Profil oluştur[profil.yayın]Yalnızca kök — tüm üyeler için geçerlidir

Mevcut bir Kargo çalışma alanını (sizin veya devraldığınız bir projenin) denetlemek için yukarıda belgelenen türdeki tutarsızlıkları bulmak için dört kontrol yeterlidir:

  1. [workspace.package].version ile her sandığın version değerini karşılaştırın; farklı bir değer mutlaka bir hata değildir ancak belgelenmeye değerdir.
  2. [workspace.dependencies]'yi her kasa tarafından yerel olarak bildirilen bağımlılıklarla karşılaştırın; her iki tarafta da farklı sürümlerde bulunan adları bulun.
  3. Cargo.toml kökündeki members listesini depodaki gerçek alt klasörlerle karşılaştırın; members'de eksik olan bir klasör mutlaka bir gözden kaçma anlamına gelmez.
  4. Sandık adıyla veya olası bir npm sarmalayıcısının gösterdiği adla eşleştiğini varsaymak yerine, derlenmiş her ikili dosyanın ([[bin]] name) gerçek adını kontrol edin.

DAĞITILMAYA HAZIR MISINIZ?

Beş dakika içinde arka ucunuz.

Kredi kartı gerekmez · 500 MB ücretsiz · 50.000 MAU