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:
| Lapisan | Direktori | Tanggung Jawab |
|---|---|---|
| API | API/Controllers/ | Penangan titik akhir HTTP/gRPC tipis, perutean permintaan, anotasi auth |
| Aplikasi | Application/DTOs/ | Definisi payload permintaan/respons, amplop API |
| Domain | Domain/Entities/ | Entitas bisnis inti yang disimpan di PostgreSQL, termasuk sensor fisik, sensor virtual, dan inventaris antarmuka sensor terstruktur |
| Infrastruktur | Infrastructure/ | Layanan, repositori, DbContext, integrasi eksternal |
| Umum (Common) | Common/Helpers/ | Utilitas bersama yang digunakan di semua lapisan |
| Ekstensi | Extensions/ | Komposisi startup (DI, middleware, migrasi, validasi) |
Arah Dependensi
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 bawahInfrastructure/Repositories/.
Arsitektur Runtime
Aplikasi berkembang melalui tiga fase berbeda selama startup:
Fase 1: Builder (Registrasi Layanan)
- Konfigurasi Logging: Inisialisasi logging Serilog dari appsettings
- Validasi Konfigurasi: Pastikan semua kunci konfigurasi yang diperlukan ada
- Pemeriksaan Keamanan: Keluarkan peringatan panjang rahasia JWT jika
< 32 karakter - Pengaturan Log: Log konfigurasi migrasi otomatis
- Ikat Typed Options: Petakan bagian konfigurasi ke kelas ber-tipe kuat
- Daftarkan Controller: Konfigurasi controller API dengan JSON case-insensitive
- Daftarkan Dokumentasi API: Tambahkan EndpointsApiExplorer dan Swagger
- Daftarkan gRPC: Tambahkan layanan gRPC
- Pembatasan Laju (Rate Limiting): Atur
auth-login(5/menit) danauth-register(3/menit) - Database: Konfigurasi PostgreSQL DbContext dengan Npgsql
- Caching: Hubungkan ke Redis (koneksi aktif/eager)
- Layanan Singleton: Daftarkan
JwtService,InfluxDbService,OpenSearchService,RedisService,ResilientHttpService - Repositori Scoped: Daftarkan semua repositori entitas (misalnya,
UserRepository,SensorRepository) - Layanan Scoped: Daftarkan semua layanan logika bisnis (misalnya,
AuthService,SensorsService) - Klien HTTP: Daftarkan pabrik HttpClient generik
- Autentikasi: Konfigurasi autentikasi JWT Bearer dengan pemeriksaan blacklist token
- Otorisasi: Konfigurasi kebijakan otorisasi berbasis peran/izin
- CORS: Daftarkan kebijakan CORS
Fase 2: Pemeriksaan Kesehatan & Migrasi
- Periksa PostgreSQL: Jalankan pemeriksaan konektivitas dengan mekanisme retry
- Periksa Redis: Jalankan pemeriksaan PING dengan mekanisme retry
- Periksa InfluxDB: Jalankan pemeriksaan titik akhir
/healthdengan mekanisme retry - Periksa OpenSearch: Jalankan pemeriksaan titik akhir root dengan mekanisme retry
- Fail-Fast: Hentikan startup segera jika ada pemeriksaan yang gagal
- Terapkan Migrasi: Eksekusi migrasi database EF Core (jika
AutoMigrate = true)
Fase 3: Pipa Middleware
- Logging Permintaan: Logging permintaan HTTP Serilog
- Penanganan Pengecualian: Penangan pengecualian global (
ApiExceptionMapper) - UI Swagger: Sajikan dokumentasi API
- CORS: Terapkan Berbagi Sumber Daya Lintas Asal (Cross-Origin Resource Sharing)
- HTTPS Redirection: Paksa koneksi aman
- Pembatasan Laju: Terapkan batas titik akhir
- Autentikasi: Validasi token JWT
- Otorisasi: Tegakkan kebijakan akses
- Petakan Controller: Rutekan permintaan HTTP ke titik akhir
- Petakan gRPC: Rutekan
SensorHealthcheckService
Arsitektur Metode Ekstensi
Setiap tanggung jawab startup diisolasi dalam metode ekstensi khusus:
| Kelas Ekstensi | Metode | Tujuan |
|---|---|---|
ServiceCollectionExtensions | AddBackendServicesAsync() | Semua registrasi DI (layanan, repositori, DB, auth, rate limiting) |
ConfigurationValidationExtensions | ValidateRequiredConfiguration() | Validasi kunci konfigurasi startup |
StartupDependencyHealthChecksExtensions | RunStartupDependencyHealthChecksAsync() | Pemeriksaan PostgreSQL, Redis, InfluxDB, OpenSearch |
DatabaseMigrationExtensions | ApplyDatabaseMigrationsAsync() | Migrasi otomatis dengan logika retry |
WebApplicationExtensions | UseBackendPipeline() | Komposisi pipa middleware |
GlobalExceptionHandlingExtensions | UseGlobalExceptionHandling() | Registrasi penangan pengecualian global |
CorsExtensions | AddCorsPolicy() | 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
-
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. -
Pola repositori untuk semua entitas — Setiap entitas memiliki abstraksi repositori yang sesuai (basis
IRepository<T>+ antarmuka khusus fitur). Layanan bergantung pada antarmuka repositori, bukanApplicationDbContextsecara langsung. -
Layanan infrastruktur singleton —
JwtService,InfluxDbService,OpenSearchService,RedisService, danResilientHttpServicedidaftarkan sebagai singleton karena mereka mengelola status koneksi mereka sendiri dan aman secara thread (thread-safe). -
Koneksi Redis aktif (eager) — Redis
ConnectionMultiplexerdihubungkan selama registrasi layanan (AddBackendServicesAsync), tidak secara malas (lazily). Ini berarti kegagalan Redis memblokir pengaturan DI. -
Filosofi startup fail-fast — Layanan sengaja mati saat startup untuk setiap kegagalan konfigurasi atau dependensi, daripada berjalan dalam kondisi yang terdegradasi.
-
Typed options daripada pembacaan ad-hoc — Semua bagian konfigurasi diikat ke kelas opsi ber-tipe kuat (didefinisikan dalam
BackendConfiguration.cs), menghindari panggilanconfiguration["key"]yang tersebar. -
Opsi runtime komposit —
SensorRuntimeOptionsmenggabungkan pengaturan dari beberapa bagian konfigurasi ke dalam satu kelas opsi untuk kenyamanan dalam operasi terkait sensor. -
Amplop API standar — Semua titik akhir mengembalikan
ApiResponse<T>melaluiApiEnvelope.Success()danApiEnvelope.Error(), menyediakan kontrak respons{ success, data, errors, traceId }yang konsisten. -
Penanganan pengecualian global —
GlobalExceptionHandlingExtensionsmenangkap pengecualian yang tidak tertangani dan memetakannya melaluiApiExceptionMapperke kode status HTTP yang sesuai, menghilangkan pola try-catch manual. -
Panggilan eksternal yang resilien —
ResilientHttpServicemembungkus panggilan HTTP keluar dengan retry (3 percobaan dengan backoff) dan pola circuit breaker (terbuka setelah 3 kegagalan, pendinginan 30 detik). -
Pembatasan laju pada titik akhir auth — Login (5 permintaan/menit) dan register (3 permintaan/menit) dilindungi oleh pembatas laju jendela tetap ASP.NET Core.
-
Model sensor berbasis agen-host — Sebuah
Sensorfisik 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, sementaraVirtualSensorhanya mencatat status penyebaran tingkat beban kerja dan antarmuka penangkapan yang ditetapkan. -
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. -
Pengukuran telemetri terpisah — InfluxDB menyimpan kehadiran host dalam
sensor_statusdan metrik host/penghitung antarmuka dalamsensor_metrics, sehingga status online diturunkan dari data heartbeat daripada disimpulkan dari deret CPU.
Hutang Arsitektur yang Diketahui
| Area | Masalah | Status | Dampak |
|---|---|---|---|
| Cakupan tes | Cakupan terus meningkat, tetapi banyak layanan/controller masih kekurangan tes integrasi dan kontrak yang mendalam | Terbuka | Risiko regresi tetap ada untuk alur yang kurang teruji |
| Fallback analitik | Fallback 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 akhir | Parsial | Konsumen harus tetap menangani nuansa payload fallback khusus titik akhir |
| Precompute/warming analitik | Layanan pemanasan (warming) cache latar belakang ada untuk kueri dasbor utama, tetapi cakupan dan penyetelan jadwal masih dasar | Parsial | Lonjakan cold-start yang tersisa mungkin terjadi pada bentuk kueri yang tidak dipanaskan |
Item hutang yang telah diselesaikan (sebelumnya terbuka):
- Logging audit di
RoleService,UserService, danPermissionService. - Caching respons analitik untuk titik akhir frekuensi tinggi.
- Layanan pemanasan cache analitik ter-host untuk jalur dasbor utama.