Hüseyin DOLHüseyin DOL

CMS Platformu · Spring Boot 3.5 · Java 21

Elly

Hız, izolasyon ve ölçeklenebilirlik için tasarlanmış güçlü bir çok kiracılı İçerik Yönetim Sistemi.

PostgreSQL · DB-per-Tenant
Redis Cache
RabbitMQ
JWT + OAuth2
Kubernetes-ready
1

Elly Nedir?

Genel bakış ve dört temel

Elly, Spring Boot 3.5 üzerine inşa edilmiş headless bir CMS ve hızlı MVP platformudur. Sayfalar, bileşenler, dinamik formlar, asenkron e-posta ve kullanıcı kimlik doğrulaması — hepsi kiracı bazında izole.

İçerik

Page → Component → Banner / Widget → Post → Comment / Rating

Auth

User → Role → Permission · Login · Register · RefreshToken · OAuth2

Form

FormDefinition (JSONB) → ConditionEvaluator → FormSubmission

E-posta

MailAccount → Async Queue → Thymeleaf → Gmail SMTP

Tüm Alan Varlıkları

PageComponentBannerWidgetPostFormUserPermissionCommentRatingAssetsEmailMailAccountRefreshTokenSeoInfoRoleFormDefinitionFormSubmission
2

Auth Mimarisi

JWT akışı, OAuth2 ve Refresh Token

JWT Giriş Akışı

  1. POST /api/auth/login
    AdminLoginInterceptor · TenantLoginInterceptor
  2. JWT Üretimi
    Access + Refresh · loginSource & tenantId claim
  3. POST /api/auth/refresh
    RefreshToken doğrula · revoke kontrol · yeni Access

Kayıt & OAuth2

  1. POST /api/auth/register
    Kullanıcı oluştur · Rol ata · doğrulama maili
  2. OAuth2 Sağlayıcılar
    Google · Facebook · GitHub → SuccessHandler → JWT
  3. Redis Auth Önbelleği
    auth:user:{username} · TTL 30dk · 3 SQL → 1 GET
AlanAçıklama
tokenUUID · oturum başına benzersiz
expiryDateLocalDateTime
revokedBoolean · çıkış işareti
userManyToOne → User
3

Form Sistemi

JSONB şema, doğrulama stratejisi, koşullu alanlar

FormDefinition (JSONB)

  • idUUID · Birincil Anahtar
  • versionInteger · şema versiyonlama
  • schemaJSONB → FormSchema (alanlar + config)
  • activeBoolean · yayın durumu

FieldDefinition

  • typetext · select · number
  • validationmin · max · regex deseni
  • conditionConditionRule: alan · operatör · değer
  • operatörlerEQUALS · NOT_EQUALS · GT · LT

Strateji Deseni

TextFieldValidatormin/max uzunluk, regex
NumberFieldValidatoraralık, tam sayı kontrolü
SelectFieldValidatorizin verilen değerler

Gönderim Akışı

  1. 1.FormDefinition çek
  2. 2.Alanları iterate et → ConditionEvaluator
  3. 3.Görünmez → payload'dan anahtarı temizle
  4. 4.Görünür → FieldValidator stratejisini çalıştır
  5. 5.Temizlenmiş → FormSubmission kaydet (JSONB)
4

E-posta Sistemi

Asenkron mesajlaşma, retry & DLQ

Asenkron Mail Akışı

  1. 1. POST /api/v1/emails/sendJWT korumalı endpoint
  2. 2. EmailLog PENDINGDB'ye kaydedilir · 202 Accepted hemen döner
  3. 3. RabbitMQ email-queueSadece emailLogId yayınlanır
  4. 4. ConsumerLog çek → Thymeleaf render → TenantMailSenderFactory → Gmail SMTP
  5. 5. Başarı / HataSENT · retry-queue TTL 30sn · max 3× → FAILED + DLQ

MailAccount (Kiracı Başına)

  • smtpHostsmtp.gmail.com
  • smtpPort587 (TLS)
  • passwordAES-256 şifreli
  • verifyGöndermeden SMTP testi

EmailLog & Rescue Job

EmailLog alanları: recipient · subject · templateName · payloadJson · status · retryCount · errorMessage · sentAt

EmailRescueJob: @Scheduled her 5 dakika · 5dk'dan eski PENDING kayıtları parti 50 ile yeniden kuyruğa alır.

5

Katmanlı Mimari

Controller → Service → Repository → Entity

1
IController
Arayüz kontratları, endpoint imzaları
2
Controller
HTTP katmanı, istek ayrıştırma, yanıt sarmalama
3
IService → Service
İş mantığı, önbellek, kiracı bağlamı
4
Repository
Spring Data JPA, Entity Graph sorguları
5
Entity + DTO
MapStruct eşleme, entity API'ye doğrudan açılmaz
Java
21 LTS
🍃
Spring Boot
3.5.7
🐘
PostgreSQL
Multi-DB
Redis
Cache
🐇
RabbitMQ
Queues
☸️
Kubernetes
K8s
6

Multi-Tenancy

Kiracı başına veritabanı izolasyonu

JWT Token
tenantId claim
JwtTenantFilter
TenantContext.set()
TenantDataSourceRouter
AbstractRoutingDataSource
elly_basedb
elly_tenant1
elly_tenant2

Tam İzolasyon

Her kiracının kendi PostgreSQL veritabanı vardır. Veri sızıntısı mümkün değildir.

ThreadLocal Bağlamı

TenantContext, istek bazlı izolasyon için ThreadLocal kullanır; finally bloklarında garantili temizlik.

HikariCP Havuzları

Her kiracı veritabanının kendi optimize edilmiş HikariCP havuzu — kaynak çekişmesi olmaz.

Redis Önbellek İzolasyonu

Anahtar öneki: {tenantId}::{cacheName}::{key} — otomatik kiracı bazlı kapsam.

7

Güvenlik & Kimlik Doğrulama

JWT, OAuth2, RBAC ve granüler izinler

JWT Auth

  • Access + Refresh token çifti
  • tenantId & loginSource claim
  • Redis auth önbelleği — TTL 30dk
  • 3 SQL → 1 Redis GET

OAuth2

  • Google · Facebook · GitHub
  • OAuth2AuthenticationSuccessHandler
  • Sorunsuz JWT entegrasyonu
  • Durumsuz tasarım

RBAC

  • User → Role → Permission (M2M)
  • SUPER_ADMIN · ADMIN · EDITOR · VIEWER
  • 40+ ayrıntılı izin sabiti
  • @PreAuthorize · @EnableMethodSecurity
RolKapsamYetkiler
SUPER_ADMINTüm kiracılarTam sistem · kiracı yönetimi
ADMINKendi kiracısıTüm CMS işlemleri · kullanıcı yönetimi
EDITORKendi kiracısıİçerik oluştur/güncelle · yayınla
VIEWERKendi kiracısıSalt okunur içerik erişimi
8

Performans Profili

Önce/Sonra metrikleri ve optimizasyon öncelikleri

Yanıt Süresi p95

2340ms456ms

Verim

18 req/s187 req/s

DB Sorgu / İstek

47 sorgu1 sorgu
HIGH
@EntityGraph ile N+1 Sorgu Düzeltmesi
47 sorgu → istek başına 1 sorgu
HIGH
HikariCP Havuz Boyutu 10 → 50
Yük altında bağlantı tükenmesini önler
HIGH
FK sütunlarında DB İndeksi
Tablo taramalarını ortadan kaldırır — 5–10× hız
MID
Tüm liste endpoint'lerinde sayfalama
Büyük veri setlerinde OOM önleme
MID
Kiracı önekli Redis @Cacheable
Önbellek isabetinde 50–100×
LOW
Read replica + CDN (dosya yükleme)
Okuma işlemlerini yatayda ölçekle
9

Dağıtım & Altyapı

Kubernetes, izleme, mail sistemi, CI/CD

Kubernetes Kurulumu

  • App Deployment2a-app-deployment.yaml
  • Burst Config2b-app-burst.yaml
  • HPA Autoscaler5-hpa.yaml
  • Monitoring6-monitoring.yaml

Servisler & İzleme

  • PostgreSQLMulti-DB · Backup CronJob
  • RedisTTL=10min · Graceful fallback
  • RabbitMQemail-queue · retry · DLQ
  • PrometheusSpring Actuator metrics
  • GrafanaReal-time dashboards
  • SonarQubeCI kalite kapısı

Mail Sistemi

  • Kiracı SMTPAES-256 şifreli kimlik bilgileri
  • Asenkron gönderimRabbitMQ email-queue
  • Yeniden deneme3× ve 30sn bekleme
  • Ölü mektup kuyruğuTükenmede FAILED + DLQ
  • Doğrulama endpoint'iGöndermeden SMTP doğrulaması

CI/CD & Yük Testleri

  • GitHub ActionsDerleme → Test → Dağıtım
  • DockerDockerfile + docker-compose
  • k6 Load Teststemel · stres · yazma paketleri
  • SonarQubeCI boru hattında kalite kapısı
10

Mevcut Durum & Yol Haritası

Özet metrikler ve sonraki adımlar

3
Kiracı
40+
İzin
10×
Perf. Kazanım
K8s
Üretime hazır

Şimdi · Yüksek Öncelik

  • Veritabanı indeksi dağıtımı
  • Bağlantı havuzu → 50
  • N+1 düzeltmesi için Entity Graph
  • Tüm listelerde sayfalama

Yakında · Bu Sprint

  • Her yerde DTO pattern'i
  • Redis önbellek yaygınlaştırması
  • Asenkron dosya yükleme
  • Yük testi baseline'ı + yeniden test

İleride · Ölçeklendirme

  • Read replica kurulumu
  • Dosya yüklemeleri için CDN
  • Çok bölgeli K8s
  • Dinamik kiracı onboarding'i