Spring Boot Performans: Profiling'den JVM Ayarına Metodoloji
Spring Boot performans çalışmasının metodolojisi: ölçüm ve profiling araçları (JFR, async-profiler), tipik darboğaz sınıfları, bağlantı havuzu ve önbellek ayarı, GC ve heap yapılandırması.
Spring Boot uygulamam neden yavaş?
Bu sorunun mühendisçe tek cevabı vardır: 'ölçmeden bilemeyiz.' Performans çalışması tahminle değil, profille başlar — ve deneyim, Spring uygulamalarındaki yavaşlığın büyük bölümünün az sayıda tekrar eden darboğaz sınıfından geldiğini gösterir: veritabanı erişim desenleri, bağlantı havuzu doygunluğu, serileştirme maliyeti ve yanlış boyutlanmış bellek. Bu yazı, o sınıfları sırayla teşhis edip kapatan bir metodoloji sunar.
Ölçüm araç seti: neyi ne zaman kullanmalı?
Araç | Ne verir | Ne zaman |
|---|---|---|
Micrometer + APM | İstek gecikme dağılımı, katman kırılımı | Sürekli; ilk bakış her zaman burada |
JDK Flight Recorder (JFR) | Düşük maliyetli üretim profili: CPU, alokasyon, kilit | Üretimde şüpheli pencereyi kaydetmek için |
async-profiler | Alev grafiği (flame graph) ile CPU/alokasyon sıcak noktaları | Derin CPU analizi; test/staging'de |
Yavaş sorgu logu | DB tarafının gerçek maliyeti | Sürekli açık; eşik tanımlı |
Heap dump analizi | Bellek tutulumları, sızıntı şüpheleri | OOM veya büyüyen heap vakalarında |
Altın kural: p50 değil, p95/p99 izlenir — ortalama, kullanıcının yaşadığı kötü deneyimi gizler.
Darboğaz sınıfı 1: veritabanı erişim desenleri
Spring uygulamalarında ilk şüpheli her zaman veri katmanıdır. N+1 sorgular (liste başına satır sorgusu), gereksiz eager ilişki yüklemeleri, işlem (transaction) kapsamının servis metodunun tamamına yayılması ve indekssiz filtreler — dört klasik. Teşhis basittir: bir isteğin ürettiği sorgu sayısını loglayın; sayı sayfa öğesiyle orantılı büyüyorsa N+1 vardır. Çözümler de bilinir: fetch join/entity graph ile bilinçli yükleme, yalnızca gereken alanlar için projeksiyon sorguları, kısa işlem kapsamı ve sorgu planına göre indeksleme. Bu sınıf kapatılmadan JVM ayarına geçmek, çatısı akan evin duvarını boyamaktır.
Darboğaz sınıfı 2: havuzlar ve doygunluk
Gecikme grafiği 'belirli yükte aniden dikleşiyorsa' klasik şüpheli doygunluktur: bağlantı havuzu (HikariCP), thread havuzu veya dış servis istemci havuzu dolmuştur ve istekler kuyrukta beklemektedir. Teşhis için havuz metrikleri (aktif/bekleyen/bekleme süresi) panoya alınır. Ayar ilkesi sezgiye aykırıdır: havuzu büyütmek çoğu zaman çözüm değildir — veritabanının paralel işleme kapasitesinin üstündeki havuz, yalnızca bekleme yerini değiştirir. Doğru sıra: önce sorgu sürelerini kısaltmak, sonra havuzu ölçümle boyutlandırmak, dış çağrılarda zaman aşımı + devre kesici ile beklemenin yayılmasını durdurmak.
Darboğaz sınıfı 3: serileştirme ve yanıt boyutu
Yüksek trafikli API'lerde JSON serileştirme ve şişkin yanıtlar görünmez vergidir: istemcinin kullanmadığı alanlar, derin nesne grafikleri ve tekrarlı meta veriler hem CPU hem bant genişliği yakar. Çözüm seti: DTO/projeksiyon ile yanıtın ihtiyaca indirilmesi, sayfalama zorunluluğu, sıkıştırmanın (gzip) doğru yapılandırılması ve sık istenen sabit yanıtlarda HTTP önbellek başlıkları. Profilde Jackson yığınları üst sıralara çıkıyorsa bakılacak yer burasıdır.
Darboğaz sınıfı 4: bellek ve GC
GC ayarı listenin sonundadır — çünkü çoğu 'GC sorunu' aslında alokasyon sorunudur: istek başına gereksiz nesne üretimi (dev ara listeler, tekrarlı string birleştirme, kontrolsüz log nesneleri) toplayıcıyı yorar. Önce alokasyon profili (JFR/async-profiler) ile üreticiler bulunur; sonra heap, konteyner limitiyle uyumlu boyutlanır; duraklama hedefi kritikse düşük duraklamalı toplayıcılar (ZGC gibi) değerlendirilir. Ayar değişiklikleri tek tek ve yük testiyle doğrulanarak yapılır — aynı anda beş bayrak değiştiren ekip, hangisinin işe yaradığını asla öğrenemez.
Başlangıç süresi ve ayak izi: gerektiğinde
Ölçeklenen (scale-out) ve serverless senaryolarda başlangıç süresi de performanstır: gereksiz auto-configuration'ların ayıklanması, lazy initialization'ın bilinçli kullanımı ve CDS/AOT gibi mekanizmalar açılış süresini kısaltır. Native imaj (GraalVM) en uçtaki seçenektir; kazandırdığı açılış hızına karşılık derleme kısıtları ve profil farklılıklarıyla birlikte değerlendirilmelidir.
İş etkisi: performans, kapasite ve faturadır
Aynı donanımda iki katı istek karşılamak, bulut faturasının yarıya inmesi demektir; p99 gecikmenin düşmesi, dönüşüm ve kullanıcı memnuniyetine doğrudan yansır. Metodolojik performans çalışmasının çıktısı tek seferlik hızlanma değil; ölçüm panoları, yük testi süreci ve 'performans bütçesi' pratiğiyle kalıcı bir mühendislik yeteneğidir. Bu yetenek, kurumsal müşteri SLA görüşmelerinde de elinizi güçlendirir.
Sık sorulan sorular
Üretimde profil almak güvenli mi?
JFR bunun için tasarlandı: düşük ek yükle üretimde kayıt alınabilir. Yine de kayıt pencereleri planlı açılmalı ve çıktılar hassas veri açısından kontrol edilmelidir.
Önbellek eklemek her zaman hızlandırır mı?
Hayır — yanlış anahtar/geçersiz kılma tasarımı bayat veri ve hata üretir; isabet oranı izlenmeyen önbellek yalnızca bellek yer. Önbellek, ölçülen sıcak noktaya eklenir.
Sanal thread'ler performans sorunlarını çözer mi?
Bekleme-yoğun iş yüklerinde eşzamanlılığı büyük ölçüde rahatlatır; ama CPU-yoğun darboğazları, N+1'i veya doygun veritabanını çözmez. Sınıf teşhisi yine şarttır.
Yük testini neyle ve nasıl yapmalıyım?
Üretim benzeri veri ve gerçekçi senaryolarla (JMeter/Gatling/k6 fark etmez); önemli olan p95/p99 hedeflerinin tanımlı olması ve testin CI'da tekrarlanabilir olmasıdır.
Performans kontrol listesi
p95/p99 panoları ve katman kırılımı aktif
İstek başına sorgu sayısı izleniyor; N+1 taraması yapıldı
Havuz metrikleri panoda; zaman aşımı + devre kesici tanımlı
Yanıtlar DTO/projeksiyonla daraltıldı; sayfalama zorunlu
Alokasyon profili alındı; heap konteyner limitiyle uyumlu
Ayar değişiklikleri tek tek, yük testiyle doğrulanıyor
Performans bütçesi ve sürüm öncesi test süreci yazılı
SSH Yazılım, Spring Boot uygulamalarında ölçüme dayalı performans teşhisi ve optimizasyonu gerçekleştirir. Uygulamanızın darboğaz haritasını birlikte çıkaralım.