Lewati ke konten utama

Arsitektur

Pendahuluan

Dokumen ini menjelaskan arsitektur berlapis dari Ravenxcope.Backend, arah dependensi antar lapisan, alur inisialisasi runtime, dan keputusan desain penting yang membentuk basis kode. Dokumen ini juga menyoroti arsitektur sensor penyebaran baru (fresh-deployment) di mana Sensor fisik didaftarkan (enroll) sekali melalui agen host dan setiap VirtualSensor disebarkan secara independen ke host tersebut.


Pendekatan Pelapisan

Backend diatur ke dalam lapisan-lapisan yang berbeda, masing-masing dengan tanggung jawab yang jelas:

LapisanDirektoriTanggung Jawab
APIAPI/Controllers/Penangan titik akhir HTTP/gRPC tipis, perutean permintaan, anotasi auth
AplikasiApplication/DTOs/Definisi payload permintaan/respons, amplop API
DomainDomain/Entities/Entitas bisnis inti yang disimpan di PostgreSQL, termasuk sensor fisik, sensor virtual, dan inventaris antarmuka sensor terstruktur
InfrastrukturInfrastructure/Layanan, repositori, DbContext, integrasi eksternal
Umum (Common)Common/Helpers/Utilitas bersama yang digunakan di semua lapisan
EkstensiExtensions/Komposisi startup (DI, middleware, migrasi, validasi)

Arah Dependensi

Program.csAPI LayerInfrastructure LayerDomain LayerExtensions (orchestration only)Application DTOsDomain Entities & Infrastructure ServicesDomain Entities, External SDKs(no outward dependencies)

Aturan dependensi saat ini:

  • API bergantung pada Aplikasi (DTO), dan Infrastruktur (antarmuka layanan). Controller harus mendelegasikan ke layanan dan menghindari akses persistensi langsung.
  • Infrastruktur bergantung pada Domain (entitas) dan SDK eksternal (EF Core, Redis, InfluxDB, OpenSearch)
  • Domain tidak memiliki dependensi luar — murni definisi entitas
  • Umum (Common) dapat digunakan oleh semua lapisan — pembantu bersama
  • Program.cs dan Ekstensi hanya mengatur startup

Catatan: Semua controller fitur sekarang mendelegasikan ke antarmuka layanan khusus (misalnya, IAuthService, ISensorsService, IAssetService). Semua entitas memiliki abstraksi repositori yang sesuai di bawah Infrastructure/Repositories/.


Arsitektur Runtime

Aplikasi berkembang melalui tiga fase berbeda selama startup:

Fase 1: Builder (Registrasi Layanan)

  1. Konfigurasi Logging: Inisialisasi logging Serilog dari appsettings
  2. Validasi Konfigurasi: Pastikan semua kunci konfigurasi yang diperlukan ada
  3. Pemeriksaan Keamanan: Keluarkan peringatan panjang rahasia JWT jika < 32 karakter
  4. Pengaturan Log: Log konfigurasi migrasi otomatis
  5. Ikat Typed Options: Petakan bagian konfigurasi ke kelas ber-tipe kuat
  6. Daftarkan Controller: Konfigurasi controller API dengan JSON case-insensitive
  7. Daftarkan Dokumentasi API: Tambahkan EndpointsApiExplorer dan Swagger
  8. Daftarkan gRPC: Tambahkan layanan gRPC
  9. Pembatasan Laju (Rate Limiting): Atur auth-login (5/menit) dan auth-register (3/menit)
  10. Database: Konfigurasi PostgreSQL DbContext dengan Npgsql
  11. Caching: Hubungkan ke Redis (koneksi aktif/eager)
  12. Layanan Singleton: Daftarkan JwtService, InfluxDbService, OpenSearchService, RedisService, ResilientHttpService
  13. Repositori Scoped: Daftarkan semua repositori entitas (misalnya, UserRepository, SensorRepository)
  14. Layanan Scoped: Daftarkan semua layanan logika bisnis (misalnya, AuthService, SensorsService)
  15. Klien HTTP: Daftarkan pabrik HttpClient generik
  16. Autentikasi: Konfigurasi autentikasi JWT Bearer dengan pemeriksaan blacklist token
  17. Otorisasi: Konfigurasi kebijakan otorisasi berbasis peran/izin
  18. CORS: Daftarkan kebijakan CORS

Fase 2: Pemeriksaan Kesehatan & Migrasi

  1. Periksa PostgreSQL: Jalankan pemeriksaan konektivitas dengan mekanisme retry
  2. Periksa Redis: Jalankan pemeriksaan PING dengan mekanisme retry
  3. Periksa InfluxDB: Jalankan pemeriksaan titik akhir /health dengan mekanisme retry
  4. Periksa OpenSearch: Jalankan pemeriksaan titik akhir root dengan mekanisme retry
  5. Fail-Fast: Hentikan startup segera jika ada pemeriksaan yang gagal
  6. Terapkan Migrasi: Eksekusi migrasi database EF Core (jika AutoMigrate = true)

Fase 3: Pipa Middleware

  1. Logging Permintaan: Logging permintaan HTTP Serilog
  2. Penanganan Pengecualian: Penangan pengecualian global (ApiExceptionMapper)
  3. UI Swagger: Sajikan dokumentasi API
  4. CORS: Terapkan Berbagi Sumber Daya Lintas Asal (Cross-Origin Resource Sharing)
  5. HTTPS Redirection: Paksa koneksi aman
  6. Pembatasan Laju: Terapkan batas titik akhir
  7. Autentikasi: Validasi token JWT
  8. Otorisasi: Tegakkan kebijakan akses
  9. Petakan Controller: Rutekan permintaan HTTP ke titik akhir
  10. Petakan gRPC: Rutekan SensorHealthcheckService

Arsitektur Metode Ekstensi

Setiap tanggung jawab startup diisolasi dalam metode ekstensi khusus:

Kelas EkstensiMetodeTujuan
ServiceCollectionExtensionsAddBackendServicesAsync()Semua registrasi DI (layanan, repositori, DB, auth, rate limiting)
ConfigurationValidationExtensionsValidateRequiredConfiguration()Validasi kunci konfigurasi startup
StartupDependencyHealthChecksExtensionsRunStartupDependencyHealthChecksAsync()Pemeriksaan PostgreSQL, Redis, InfluxDB, OpenSearch
DatabaseMigrationExtensionsApplyDatabaseMigrationsAsync()Migrasi otomatis dengan logika retry
WebApplicationExtensionsUseBackendPipeline()Komposisi pipa middleware
GlobalExceptionHandlingExtensionsUseGlobalExceptionHandling()Registrasi penangan pengecualian global
CorsExtensionsAddCorsPolicy()Registrasi kebijakan CORS

Ini memberikan Program.cs urutan bootstrap yang bersih dan deklaratif:

var builder = WebApplication.CreateBuilder(args);
// ... logging, validasi, peringatan ...
await builder.Services.AddBackendServicesAsync(builder.Configuration);
var app = builder.Build();
await app.RunStartupDependencyHealthChecksAsync();
await app.ApplyDatabaseMigrationsAsync();
app.UseBackendPipeline();
await app.RunAsync();

Keputusan Desain Penting

  1. Desain controller berbasis layanan — Semua controller mendelegasikan logika bisnis ke antarmuka layanan khusus (misalnya, IAuthService, ISensorsService, IAssetService). Controller tidak berisi logika bisnis, hanya masalah transport HTTP.

  2. Pola repositori untuk semua entitas — Setiap entitas memiliki abstraksi repositori yang sesuai (basis IRepository<T> + antarmuka khusus fitur). Layanan bergantung pada antarmuka repositori, bukan ApplicationDbContext secara langsung.

  3. Layanan infrastruktur singletonJwtService, InfluxDbService, OpenSearchService, RedisService, dan ResilientHttpService didaftarkan sebagai singleton karena mereka mengelola status koneksi mereka sendiri dan aman secara thread (thread-safe).

  4. Koneksi Redis aktif (eager) — Redis ConnectionMultiplexer dihubungkan selama registrasi layanan (AddBackendServicesAsync), tidak secara malas (lazily). Ini berarti kegagalan Redis memblokir pengaturan DI.

  5. Filosofi startup fail-fast — Layanan sengaja mati saat startup untuk setiap kegagalan konfigurasi atau dependensi, daripada berjalan dalam kondisi yang terdegradasi.

  6. Typed options daripada pembacaan ad-hoc — Semua bagian konfigurasi diikat ke kelas opsi ber-tipe kuat (didefinisikan dalam BackendConfiguration.cs), menghindari panggilan configuration["key"] yang tersebar.

  7. Opsi runtime kompositSensorRuntimeOptions menggabungkan pengaturan dari beberapa bagian konfigurasi ke dalam satu kelas opsi untuk kenyamanan dalam operasi terkait sensor.

  8. Amplop API standar — Semua titik akhir mengembalikan ApiResponse<T> melalui ApiEnvelope.Success() dan ApiEnvelope.Error(), menyediakan kontrak respons { success, data, errors, traceId } yang konsisten.

  9. Penanganan pengecualian globalGlobalExceptionHandlingExtensions menangkap pengecualian yang tidak tertangani dan memetakannya melalui ApiExceptionMapper ke kode status HTTP yang sesuai, menghilangkan pola try-catch manual.

  10. Panggilan eksternal yang resilienResilientHttpService membungkus panggilan HTTP keluar dengan retry (3 percobaan dengan backoff) dan pola circuit breaker (terbuka setelah 3 kegagalan, pendinginan 30 detik).

  11. Pembatasan laju pada titik akhir auth — Login (5 permintaan/menit) dan register (3 permintaan/menit) dilindungi oleh pembatas laju jendela tetap ASP.NET Core.

  12. Model sensor berbasis agen-host — Sebuah Sensor fisik didaftarkan sekali melalui token instalasi satu kali dan token agen yang tahan lama. Agen host tersebut melaporkan heartbeat, metrik host, dan antarmuka jaringan yang ditemukan, sementara VirtualSensor hanya mencatat status penyebaran tingkat beban kerja dan antarmuka penangkapan yang ditetapkan.

  13. Inventaris antarmuka terstruktur — Backend menyimpan antarmuka sensor sebagai baris kelas utama (SensorNetworkInterface) daripada blob JSON runtime. Ini memungkinkan validasi kelayakan di sisi backend dan penetapan antarmuka eksklusif ke sensor virtual.

  14. Pengukuran telemetri terpisah — InfluxDB menyimpan kehadiran host dalam sensor_status dan metrik host/penghitung antarmuka dalam sensor_metrics, sehingga status online diturunkan dari data heartbeat daripada disimpulkan dari deret CPU.


Hutang Arsitektur yang Diketahui

AreaMasalahStatusDampak
Cakupan tesCakupan terus meningkat, tetapi banyak layanan/controller masih kekurangan tes integrasi dan kontrak yang mendalamTerbukaRisiko regresi tetap ada untuk alur yang kurang teruji
Fallback analitikFallback yang anggun (graceful fallback) sekarang diterapkan di seluruh titik akhir analitik dengan pola fallback cache-lama; kontrak metadata respons mungkin masih bervariasi berdasarkan bentuk titik akhirParsialKonsumen harus tetap menangani nuansa payload fallback khusus titik akhir
Precompute/warming analitikLayanan pemanasan (warming) cache latar belakang ada untuk kueri dasbor utama, tetapi cakupan dan penyetelan jadwal masih dasarParsialLonjakan cold-start yang tersisa mungkin terjadi pada bentuk kueri yang tidak dipanaskan

Item hutang yang telah diselesaikan (sebelumnya terbuka):

  • Logging audit di RoleService, UserService, dan PermissionService.
  • Caching respons analitik untuk titik akhir frekuensi tinggi.
  • Layanan pemanasan cache analitik ter-host untuk jalur dasbor utama.