Bu dosyada, Java/Spring mülakatlarında karşılaşılmış sorular ve cevapları yer almaktadır. Soruların üzerine tıklayarak cevapları görebilirsiniz.
1. JDK, JRE ve JVM nedir? Farkları nelerdir?
- JDK (Java Development Kit): Java uygulamaları geliştirmek için gereken araçları ve kütüphaneleri içerir. JRE ve ek araçları kapsar.
- JRE (Java Runtime Environment): Java uygulamalarını çalıştırmak için gereken ortamdır. JVM ve standart sınıf kütüphanelerini içerir.
- JVM (Java Virtual Machine): Java kodunu makine koduna dönüştürüp çalıştıran sanal makinedir. JVM, platform bağımsızlığı sağlar.
Farklar:
- JDK, geliştirme araçlarını ve çalıştırma ortamını içerir.
- JRE, yalnızca çalıştırma ortamıdır.
- JVM, JRE'nin bir parçasıdır ve kodun platformdan bağımsız çalışmasını sağlar.
2. Java'da String ve StringBuilder arasındaki fark nedir?
- String: Immutable'dır, yani değiştirilemez. Her değişiklik yeni bir String nesnesi oluşturur.
- StringBuilder: Mutable'dır, yani mevcut nesne üzerinde değişiklik yapılabilir. Performans açısından daha verimlidir.
3. equals() ve == operatörünün farkları nelerdir?
- ==: Referansları karşılaştırır, yani iki nesnenin aynı bellek adresini işaret edip etmediğine bakar.
- equals(): Genellikle nesnelerin içeriklerini karşılaştırmak için kullanılır (ör. String'lerde içerik karşılaştırması yapar).
4. String sınıfı neden değişmez (immutable) olarak tasarlanmıştır?
- Güvenlik: String'in içeriği değiştirilemediği için güvenlidir.
- Performans: Immutable nesneler hashCode'u bir kez hesaplar ve tekrar kullanır.
- Thread-Safety: String nesneleri değişmez olduğu için çoklu iş parçacıkları arasında güvenle paylaşılabilir.
5. Abstract sınıf nedir?
- Abstract sınıf, soyut metotlar (gövdesiz) ve gövdeli metotlar içerebilen bir sınıf türüdür.
- Alt sınıflar tarafından miras alınarak tamamlanmak üzere tasarlanır.
6. Abstract sınıfların constructor'ı olur mu?
- Evet, abstract sınıfların constructor'ı olabilir. Ancak abstract sınıflar doğrudan örneklendirilemez, constructor yalnızca alt sınıflar tarafından çağrılır.
Java'da final anahtar kelimesi nedir? Ne için kullanırız?
- final bir değişkenin değerinin değiştirilemez olduğunu belirtir.
- final bir metodun override edilmesini engeller.
- final bir sınıfın miras alınmasını önler.
7. Stack ve Heap memory arasındaki fark nedir?
- Stack Memory: Küçük boyutlu, hızlı ve metod çağrıları için kullanılır. Yerel değişkenler burada saklanır.
- Heap Memory: Daha büyük boyutlu, dinamik olarak nesnelerin saklandığı alan.
8. Idempotence nedir?
- Idempotence, bir işlemin birden fazla kez uygulanmasının aynı sonucu vermesi durumudur.
- Örneğin: HTTP GET ve DELETE istekleri genellikle idempotenttir.
9. Java JIT compiler nedir?
- Just-In-Time (JIT) Compiler, bytecode'u çalışma zamanında makine koduna çevirerek performansı artırır.
- Bu işlem, tekrar eden kodları optimize etmek için kullanılır.
10. Double check locking nedir?
- Double-check locking, thread-safe singleton oluşturma tekniğidir. Aynı nesnenin birden fazla kez oluşturulmasını engeller.
11. Functional Interface nedir? Interface ile arasındaki fark nedir?
- Functional Interface, yalnızca bir abstract metoda sahip bir arayüzdür.
- Functional Interface'ler, lambda ifadeleriyle kullanılabilir.
- Diğer arayüzler birden fazla abstract metoda sahip olabilir.
12. Interface'lerde içi dolu metot yazabilir miyiz?
- Evet, Java 8'den itibaren
defaultvestaticanahtar kelimeleri kullanılarak içi dolu metot yazılabilir.
13. try-with-resources nedir? Hiç kullandın mı?
- try-with-resources, kaynakların (ör. dosya, veritabanı bağlantıları) otomatik olarak kapatılmasını sağlayan bir yapıdır.
- Kapatılabilir sınıfların
AutoCloseablearayüzünü implement etmesi gerekir.
14. Checked ve Unchecked Exception'ların farkı nedir?
- Checked Exception: Derleme zamanında (compile time) kontrol edilen istisnalardır. Kodda try-catch bloğunda yakalanmaları veya metot imzasında
throwsile belirtilmeleri gerekir. Örnek:IOException,SQLException. - Unchecked Exception: Çalışma zamanında (runtime) oluşan istisnalardır. Try-catch bloğunda yakalanmaları zorunlu değildir. Örnek:
NullPointerException,ArrayIndexOutOfBoundsException.
15. SOLID prensiplerinden bahseder misin?
- Single Responsibility Principle (SRP): Bir sınıfın yalnızca bir sorumluluğu (veya bir amacı) olmalıdır.
- Open/Closed Principle: Sınıflar genişletilmeye açık, ancak değiştirmeye kapalı olmalıdır.
- Liskov Substitution Principle: Alt sınıflar, üst sınıflarının yerine kullanılabilir olmalıdır.
- Interface Segregation Principle: Kullanıcılar gereksiz metotlara bağımlı olmamalıdır, arayüzler spesifik olmalıdır.
- Dependency Inversion Principle: Yüksek seviyeli modüller, düşük seviyeli modüllere bağımlı olmamalıdır. Her ikisi de bir soyutlamaya bağımlı olmalıdır.
16. Spring ile Spring Boot farkı nedir?
- Spring: Bir Java framework'üdür ve uygulama geliştirme için temel araçlar sağlar. Yapılandırma işlemleri manuel olarak yapılır (XML veya Annotation tabanlı).
- Spring Boot: Spring Framework üzerine kurulmuş bir projedir. Otomatik yapılandırma (Auto-Configuration) özelliği sağlar, bağımlılık yönetimini kolaylaştırır ve gömülü sunucular (embedded servers) içerir. Spring Boot ile daha hızlı bir şekilde uygulama geliştirilir.
17. Bean nedir? Niye oluşturulur? Bahseder misin?
- Bean, Spring IoC (Inversion of Control) container tarafından yönetilen bir nesnedir.
- Uygulama içinde bağımlılık yönetimi ve yeniden kullanılabilirlik sağlamak için oluşturulur.
- Spring, Bean'leri anotasyonlar (ör.
@Component,@Service) veya XML tabanlı yapılandırmalarla yönetir.
18. Spring Bean'lerini nasıl inject ediyorsun? Birkaç yöntemi var, onlardan da bahseder misin?
- Constructor Injection: Bağımlılıklar, sınıfın constructor'ı aracılığıyla atanır.
- Setter Injection: Bağımlılıklar, setter metotları kullanılarak atanır.
- Field Injection:
@Autowiredanotasyonu doğrudan sınıf değişkenlerinde kullanılır (tavsiye edilmez, test edilebilirliği düşürür).
19. @Component ve @Service anotasyonlarının farkı nedir?
- @Component: Genel bir Spring Bean tanımlayıcısıdır. Herhangi bir bileşen (component) için kullanılabilir.
- @Service: Daha spesifik bir anotasyondur. İş mantığı (business logic) içeren sınıflar için kullanılır.
- Teknik olarak işlevsellik farkı yoktur, ancak kodun okunabilirliğini artırır.
20. Servlet nedir? Daha önce duymuş muydun?
- Servlet, Java'nın web tabanlı uygulamalar geliştirmek için sunduğu bir API'dir.
- HTTP isteklerini işler ve dinamik içerikler (ör. HTML, JSON) döndürür.
- Servlet'ler genellikle Spring MVC'de DispatcherServlet gibi yapılarda soyutlanmıştır.
21. @Transactional anotasyonu nedir?
- @Transactional, Spring'de işlemleri (transactions) yönetmek için kullanılan bir anotasyondur.
- Veritabanı işlemlerinde
commitverollbackyönetimini sağlar. - Metot veya sınıf düzeyinde uygulanabilir.
22. @Transactional propagation type'lardan REQUIRED ile REQUIRED_NEW farkını biliyor musun?
- REQUIRED: Mevcut bir transaction varsa onu kullanır, yoksa yeni bir transaction oluşturur.
- REQUIRED_NEW: Her zaman yeni bir transaction oluşturur, mevcut transaction'ı askıya alır.
23. Hibernate nedir?
- Hibernate, Java için bir ORM (Object-Relational Mapping) aracıdır. Veritabanı işlemlerini nesne bazlı bir yaklaşımla gerçekleştirmeyi sağlar.
24. Spring Security'den bahseder misin? Projeye nasıl ekliyoruz ve eklediğimizde neler oluyor?
- Spring Security, uygulamalar için kimlik doğrulama (authentication) ve yetkilendirme (authorization) sağlar.
- Spring Security eklendiğinde, varsayılan olarak temel bir güvenlik yapılandırması aktif olur (ör. HTTP Basic Authentication).
- Özelleştirmek için
SecurityFilterChainveyaWebSecurityConfigurerAdapterkullanılır.
25. Thread Safety nedir? Nasıl sağlanır?
- Thread Safety, birden fazla thread'in aynı anda bir nesneye erişirken tutarsızlıklara neden olmamasıdır.
- Thread Safety sağlamak için şu yöntemler kullanılabilir:
- volatile anahtar kelimesini kullanarak sağlayabiliriz fakat bu sadece visibility problemine çözüm olur.
- Synchronized blok veya metotlar kullanabiliriz.
- Immutable Objects kullanımı.
- ReentratLock kullanarak.
- wait & notify metotlarını kullanarak.
26. Elimizde bir milyon tane Integer türünde sayı var. Kullanıcı bir sayı girdiğinde (örneğin 10), bu sayının listede kaç kez geçtiğini döndüren bir yapı oluşturmak istiyoruz. Örneğin, 10 sayısı 3 kez tekrar ediyorsa sonuç 3, hiç geçmiyorsa sonuç 0 olacak. Bu problemi hangi yapı ile çözerdin? Nasıl bir yol izlerdin? (kodlama istenmiyor)
Cevap: HashMap
- HashMap tercih edilir çünkü:
- Anahtar (key) olarak sayıyı, değer (value) olarak tekrar sayısını saklayabilir.
- O(1) zaman karmaşıklığı ile hızlı ekleme ve arama işlemi sağlar.
- TreeMap de kullanılabilir, ancak O(log n) zaman karmaşıklığı nedeniyle HashMap kadar hızlı değildir.
27. @PreAuthorize anotasyonu nedir?
- @PreAuthorize, Spring Security'de metod seviyesinde yetkilendirme kontrolü yapmak için kullanılan bir anotasyondur.
- Metot çağrılmadan önce, kullanıcının belirtilen yetkilere sahip olup olmadığını kontrol eder.
- Örneğin:
@PreAuthorize("hasRole('ADMIN')"): Yalnızca ADMIN rolüne sahip kullanıcılar bu metodu çağırabilir.@PreAuthorize("#user.id == authentication.principal.id"): Kullanıcı bazlı kontrol yapılabilir.
28. Microservice mimarisinde iki servis var, bunlar birbiriyle iletişim halinde ve bir servis çöktü. Ne olur? Ne yaparsın?
-
Durum: Bir servis çöktüğünde, diğer servis ona bağımlıysa istekler başarısız olur. Bu, sistemin tamamının etkilenmesine neden olabilir. Dağıtık bir sistemde CAP teorimine uygun yapı kurulmalıdır. Buradaki Partiton Tolerance'a uyarsak bu sorunları en aza indiririz.
-
Ne yapılır?
- Circuit Breaker (Devre Kesici) Kullanımı: Çöken servise yapılan istekler belirli bir süreliğine durdurulur. Ör: Netflix Hystrix, Resilience4j.
- Fallback Mekanizması: Çöken servise alternatif bir cevap döndürmek veya kullanıcıya uygun bir hata mesajı göstermek için kullanılır.
- Retry Mekanizması: Servis tekrar aktif olduğunda işlemleri denemek için kullanılır.
- Asenkron İletişim: Servisler arasındaki bağımlılığı azaltmak için mesajlaşma kuyrukları (RabbitMQ, Kafka) kullanılabilir.
29. Optimistic ve Pessimistic Locking nedir?
Detaylı bilgi için Medium yazımı inceleyebilirsiniz: Hibernate Optimistic ve Pessimistic Locking Nedir?
30. Microservice projesinde bir servis yavaşladı. Response time yükseldi ve sistemi yavaşlattı. Ne yaparsın?
-
Durum: Yavaşlayan bir servis tüm sistemi etkileyebilir, çünkü diğer servisler ona bağımlı olabilir.
-
Ne yapılır?
- Servisin performansını izlemek için monitoring araçları (Prometheus, Grafana, ELK Stack) kullanılır.
- Yavaşlayan servis için belirli bir zaman sınırı (timeout) koyulur.
- Yavaşlayan servise yapılan istekler bir süre kesilir ve fallback mekanizması devreye alınır.
- Yükü dengelemek için yük dengeleyiciler (Load Balancer) kullanılabilir.
- Servise daha fazla kaynak (CPU, bellek) atanarak yanıt süresi iyileştirilebilir.
- Eğer mümkünse, yavaşlayan servisin sık kullanılan yanıtları bir önbellekte (Redis, Memcached) saklanabilir.
- Yavaşlayan servisin iç işlemleri gözden geçirilip, optimizasyon yapılabilir.
- Thread dump alarak bir deadlock ya da uzun süren bir işlem var mı diye kontrol edilebilir.
- I/O problemlerine veya CPU kullanımına odaklanabiliriz.
31. Apache Kafka'nın genel yapısından bahsedebilir misin?
Apache Kafka, yüksek performanslı, dağıtık bir mesajlaşma platformudur. Genellikle olay tabanlı mimarilerde, büyük veri işleme veya asenkron iletişim gereksinimlerinde tercih edilir.
Kafka'nın temel yapısına gelirsek:
-
Producer: Verileri Kafka'ya gönderen bileşendir. Mesajlar belirli bir topic'e yazılır. Örneğin, bir mikro hizmet veriyi işledikten sonra Kafka'ya mesaj bırakabilir.
-
Topic: Kafka'da mesajlar topic adı verilen mantıksal kategorilere ayrılır. Her topic, birden fazla partition'a bölünerek paralel işleme imkanı sunar.
-
Partition: Her topic birden fazla bölüme ayrılır. Bu bölümler, mesajların disk üzerinde sıralı bir şekilde saklanmasını sağlar. Partition'lar aynı zamanda ölçeklenebilirlik açısından önemlidir. Mesajlar burada offset ile numaralandırılır.
-
Consumer: Kafka'daki mesajları okuyan bileşendir. Tüketiciler, genellikle bir consumer group içinde organize edilir. Böylece aynı mesaj birden fazla tüketiciye atanabilir ya da bölünerek paralel şekilde işlenebilir.
-
Broker: Kafka'nın temel çalışma birimidir. Broker'lar, mesajları saklayan ve istekleri işleyen sunuculardır. Birden fazla broker bir Kafka cluster'ını oluşturur.
Kafka’nın güçlü yönlerinden biri de partition tabanlı yapısı sayesinde yatayda kolayca ölçeklenebilmesidir. Bunun yanında, hem yüksek hacimli veriyi işleyebilir hem de düşük gecikme süresiyle çalışabilir. Ayrıca, mesajlar disk tabanlı loglarda saklandığı için kalıcıdır.
Eğer cluster yönetiminden bahsedecek olursak, eski versiyonlarda Zookeeper kullanılmakta; ancak yeni versiyonlarda Kafka, kendi metadata yönetim sistemine geçmiş durumda. Bu da Zookeeper bağımlılığını ortadan kaldırdı.
Kafka’nın en yaygın kullanım senaryoları arasında olay tabanlı sistemler, log toplama, gerçek zamanlı veri işleme ve mikro hizmetler arasında asenkron iletişim sağlama bulunur.
32. Monolith ile Microservice mimarilerinin farkı nedir? Hangisi daha avantajlıdır?
Monolith, tüm uygulamanın tek bir kod tabanı ve süreçte çalıştığı bir mimaridir. Geliştirmesi ve dağıtımı başlangıçta daha kolaydır, ancak büyüdükçe karmaşıklaşır ve bakım zorlaşır.
Microservice, uygulamanın küçük, bağımsız servislerden oluştuğu bir yapıdır. Her servis kendi veri tabanına ve bağımsız süreçlerine sahiptir. Ölçeklenebilirlik ve hata izolasyonu açısından daha avantajlıdır, ancak dağıtık yapısı nedeniyle yönetimi daha karmaşıktır.
Hangi mimari daha avantajlı?
Küçük projelerde monolith tercih edilirken, büyük ve uzun vadeli projelerde microservice daha uygun olur. Birinin diğerine bir üstünlüğü yoktur.
33. Bir Spring Boot projesini başlatırken, örneğin IDE'den run tuşuna bastığında neler olur?
Bir Spring Boot uygulamasını run ettiğimde ilk olarak SpringApplication.run() metodu çağrılır ve bu, uygulamanın tüm başlangıç sürecini tetikler.
İlk olarak, ApplicationContext oluşturulur. Bu aşamada Spring, projemdeki tüm Bean'leri tarar, bağımlılıkları enjekte eder ve IoC container'ını hazırlar. Eğer bir web uygulamasıysa, gömülü bir sunucu (örneğin Tomcat) otomatik olarak başlatılır.
Ayrıca, Spring Boot’un auto-configuration özelliği devreye girer ve kullandığım bağımlılıklara göre varsayılan yapılandırmalar uygulanır. Örneğin, bir veri tabanı bağımlılığı varsa, Spring bunun için otomatik bir DataSource oluşturur.
Uygulamanın başlangıç sürecinde, eğer CommandLineRunner veya ApplicationRunner implement ettiysem, bunlar çalıştırılır. Bu, uygulama başlangıcında özel işlemler yapmak istediğimde kullanılır.
Kısacası, Spring Boot benim için birçok yapılandırmayı otomatik yapar ve uygulamamı minimum manuel ayarla çalıştırır.
34. Bir projede memory leak olsun istemeyiz. Bunu önlemek için geliştirme aşamasında nelere dikkat edersin?
Memory leak gerçekten kritik bir problem. Geliştirme sırasında buna dikkat etmek için genelde şunları yapıyorum:
Öncelikle, kullandığım kaynakları düzgün bir şekilde kapattığımdan emin oluyorum. Örneğin, bir dosya ya da veritabanı bağlantısı açıyorsam, bunu mutlaka try-with-resources ile yönetiyorum ki açık kalıp bellek sızıntısına neden olmasın.
Statik değişkenler konusunda da hassasım. Özellikle büyük nesneleri statik alanlarda tutmak gibi bir şey yapmamaya çalışıyorum, çünkü bu nesneler garbage collector tarafından temizlenemez.
Bir de, listener’lar ve callback’ler kullandığım projelerde, bunların yaşam döngüsünü düzgün yönetmek önemli. Eğer artık kullanılmayan bir listener varsa, onu mutlaka kayıttan kaldırırım.
Koleksiyonlarda büyük verilerle çalışıyorsam, bu verileri gerektiği gibi temizlediğimden emin olurum. Mesela bir Map içinde veri tutuyorsam, kullanım ömrü bittiğinde eski kayıtları silerim.
Son olarak, geliştirme aşamasında VisualVM veya benzeri profiling araçlarıyla uygulamayı analiz ederim. Bu, potansiyel memory leak’leri erken fark etmemi sağlar.
Amacım, yazdığım kodun uzun süreli çalışsa bile bellek yönetiminde sorun yaratmamasını sağlamak.
35. Parallelism ve Concurrency aynı şeyler mi?
Hayır, Parallelism ve Concurrency aynı şeyler değildir.
Concurrency, aynı anda birden fazla görevin yönetilmesi anlamına gelir. Ancak bu görevler fiziksel olarak aynı anda çalışıyor olmayabilir. Örneğin, tek bir işlemci üzerinde bir görev durdurulup başka bir görev çalıştırılabilir. Concurrency'de odak, görevlerin birbiriyle çakışmadan çalıştırılmasıdır.
Parallelism ise fiziksel olarak birden fazla görevin aynı anda çalıştırılmasıdır. Genellikle çok çekirdekli işlemcilerde görülür. Her çekirdek bir görevi aynı anda çalıştırabilir.
Özetle:
- Concurrency, görevlerin bir arada yönetilmesiyle ilgilidir.
- Parallelism, görevlerin aynı anda çalıştırılmasıdır.
İkisi farklı kavramlardır ama birlikte kullanılabilirler. Örneğin, bir sistem hem concurrent hem de parallel olabilir.
36. Hibernate cache seviyelerini duymuş muydun?
Detaylı bilgi için Medium yazımı inceleyebilirsiniz: Hibernate First Level ve Second Level Cache Nedir?
37. ArrayList varken LinkedList neden kullanırız?
ArrayList ve LinkedList'in farklı kullanım senaryoları vardır. LinkedList kullanmayı tercih edeceğim durumlar:
-
Sık Ekleme/Çıkarma İşlemleri:
LinkedList, özellikle liste başına veya ortasına ekleme/çıkarma işlemlerinde daha hızlıdır (O(1)). Çünkü elemanlar dinamik olarak bağlanır ve diğer elemanların kaydırılmasına gerek kalmaz. -
Büyük Listeler:
Eğer liste çok büyükse ve sık sık elemanlar arasında gezinme yerine ekleme/çıkarma yapıyorsam, LinkedList daha avantajlıdır.
Ancak, rastgele erişim gerektiğinde (örneğin get(i)) ArrayList çok daha hızlıdır (O(1)), çünkü LinkedList’in rastgele erişim süresi O(n)’dir. Bu yüzden, kullanım senaryosuna göre hangisini seçeceğimi belirlerim.
38. Microservice mimarisinde transaction yönetimini nasıl sağlıyorsun?
Detaylı bilgi için Medium yazımı inceleyebilirsiniz: Microservice Mimarisinde Transaction Yönetimi
39. DDD nedir?
DDD, yani Domain-Driven Design, iş gereksinimlerini doğru bir şekilde yazılıma yansıtmak için geliştirilmiş bir yaklaşım. Ben genellikle karmaşık projelerde kullanıyorum, çünkü bu yaklaşım sayesinde domain’i anlamlı parçalara ayırabiliyorum. Mesela, Bounded Context kavramı burada devreye giriyor. Her bounded context, iş alanının belirli bir bölümüne odaklanmamı sağlıyor ve farklı ekiplerin bağımsız çalışmasına olanak tanıyor.
Ayrıca Ubiquitous Language sayesinde, iş birimleriyle konuşurken aynı terimleri kullanıyoruz. Örneğin, finans sektöründe çalışıyorsam "hesap bakiyesi" veya "ödeme" gibi kavramlar yazılım kodlarında da aynı şekilde geçiyor.
DDD'nin bana en çok katkı sağladığı nokta, karmaşık iş kurallarını daha anlaşılır ve sürdürülebilir bir şekilde modellemek oluyor. Bu sayede projeler büyüdüğünde bile kontrol edilebilir kalıyor.
40. CQRS nedir?
CQRS, yani Command Query Responsibility Segregation, basitçe veri yazma ve veri okuma işlemlerini birbirinden ayırıyor. Ben genelde bu yapıyı performans problemleri olan projelerde kullanıyorum. Örneğin, bir kullanıcı sistemi geliştirdiğimizi düşünelim: Kullanıcı verilerini güncelleme (command) işlemleriyle sadece veri okuma (query) işlemlerini ayırdığınızda, her birine özel optimizasyon yapabiliyorsunuz.
Mesela okuma tarafında farklı bir veri modeli kullanarak çok hızlı bir sorgulama yapabiliyorum. Yazma tarafında ise daha kompleks iş kuralları uygulayabiliyorum. Özellikle büyük veri setlerinde CQRS sayesinde çok ciddi performans artışı elde ettim.
Genelde Event Sourcing ile birlikte kullanıyorum. Her değişikliği bir event olarak kaydettiğimde, sistem geçmişe yönelik tüm değişiklikleri izleyebiliyor.
41. Kafka ile RabbitMQ farkını biliyor musun?
Kafka, daha çok yüksek hacimli veri akışı ve olay tabanlı sistemler için kullanılıyor. Örneğin, log analitiği ya da gerçek zamanlı veri işleme gibi durumlarda tercih ederim. Mesajlar Kafka’da log olarak saklanır ve tüketildikten sonra bile sistemde kalır. Bu, mesajların yeniden oynatılmasını mümkün kılar. Ayrıca, Kafka’yı bir mesaj kuyruğundan çok bir veri akış platformu olarak görüyorum.
RabbitMQ ise daha klasik bir mesajlaşma sistemi. Özellikle point-to-point veya publish/subscribe modelleri için ideal. Eğer bir mesajın sadece bir tüketiciye ulaşmasını istiyorsam ya da hızlı bir şekilde mesaj alıp iletmem gerekiyorsa RabbitMQ’yu tercih ederim. RabbitMQ daha düşük hacimli ama daha hızlı teslimat gerektiren senaryolarda avantajlı oluyor.
Kısacası: Kafka’yı veri akışı ve olay bazlı sistemler için, RabbitMQ’yu ise hızlı ve güvenilir mesaj iletimi gereken durumlarda tercih ediyorum.
42. Spring Boot uygulamasının başlangıç süresini nasıl optimize edersiniz? Özellikle büyük ve bağımlı bir uygulamada bunu nasıl sağlarsınız?
Spring Boot başlangıç süresini iyileştirmek için @Lazy anotasyonu ile bean başlatmalarını gerektiğinde yapılacak hale getiririm. Ayrıca, bağımlı konfigürasyonları ve gereksiz Spring starter modüllerini projeden çıkartırım. Bir başka strateji olarak, uygulamayı native bir imaj haline getirip GraalVM ile başlatma süresini azaltmak da mümkündür.43. Garbage Collection (GC) ayarlarını nasıl optimize edersiniz? Özellikle yüksek bellek tüketimi olan bir Spring Boot uygulamasında hangi ayarları tercih edersiniz?
Yüksek bellek tüketimi olan bir Spring Boot uygulamasında genellikle G1 Garbage Collector kullanmayı tercih ederim. JVM ayarlarını özelleştirerek maksimum heap boyutunu (Xmx) belirlerim ve XX:MaxGCPauseMillis ile beklenen GC süresini sınırlandırırım. GC loglarını inceleyerek sık veya uzun süren duraklamaları belirleyip gerektiğinde bellek yönetimi için farklı GC algoritmaları (örneğin ZGC veya Shenandoah) deneyebilirim.44. Spring Cloud bileşenlerinden hangilerini kullandınız? Özellikle Netflix OSS araçları (Eureka, Ribbon, Hystrix) hakkında deneyiminiz var mı?
Eureka ile mikroservisler arasında dinamik servis keşfi sağladım. Yük dengeleme için Ribbon’u, Circuit Breaker için ise Hystrix veya Resilience4j’yi kullanarak uygulamanın kesintisiz çalışmasını garanti altına alıyorum. Özellikle Hystrix ile fallback mekanizmaları kurarak bir serviste sorun çıktığında diğer servislerin etkilenmesini önledim.45. Config Server kullanarak yapılandırma yönetimini nasıl merkezi hale getirirsiniz? Config Server’ın faydaları nelerdir?
Config Server, her bir servisin yapılandırmasını merkezi olarak yönetmemi sağlıyor. Özellikle farklı ortamlarda (prod, dev, test) kullanılacak yapılandırmaları kolayca yönetmek için Spring Cloud Config Server ile her bir servise özel ayarları tanımlar ve git gibi bir kaynak yönetim sistemi ile entegre ederim. Böylece yapılandırmalar bir merkezden güncellenebilir ve değişikliklerde otomatik olarak yeniden yüklenir.46. Spring Boot üzerinde uzun süre çalışan işlemler için nasıl optimizasyon yaparsınız? Timeout ve retry gibi stratejileri nasıl belirlersiniz?
Uzun süren işlemleri yönetmek için, zaman aşımı (timeout) sürelerini @Timeout anotasyonları veya özel konfigürasyonlarla belirlerim. Circuit Breaker desenini, özellikle mikroservisler arasındaki çağrılarda Hystrix veya Resilience4j kullanarak uygularım, bu sayede uzun süren işlemler devre dışı bırakılarak sistem performansının düşmesini engeller. Retry stratejileri için ise belirli aralıklarla yeniden denemeler yapılır, ancak her deneme arasında artan bir süre bırakılarak aşırı yükün önüne geçilir.47. OAuth2 ile güvenlik sağlama konusunda neler biliyorsun?
OAuth2, kullanıcıların yetkilendirme süreçlerini üçüncü taraf sağlayıcılar (Google, Facebook vb.) üzerinden yönetmesini sağlar.48. Mikroservislerde güvenlik açıklarını tespit etmek için hangi araçlar kullanılabilir?
OWASP ZAP, Burp Suite, SonarQube, Snyk gibi araçlar güvenlik açıklarını tespit etmek için kullanılabilir. Ayrıca, runtime güvenliği için Falco, Aqua ve Prisma gibi araçlar da tercih edilebilir.49. Mikroservislerde backpressure nasıl yönetilir?
Backpressure, bir servisin aşırı yüklenmesini önlemek için kullanılan bir mekanizmadır. Bu, istekleri sınırlayarak, kuyruk uzunluğunu kontrol ederek veya istemcilerin istek hızını yavaşlatarak sağlanabilir. Reactive programming ve akış kontrol mekanizmaları (örneğin, Reactive Streams) bu süreçte yardımcı olabilir.50. Dağıtık sistemlerde cache kullandınız mı? Eğer kullandıysanız, nasıl bir yaklaşım izlediniz ve hangi problemleri çözmek için kullandınız?
Dağıtık sistemlerde cache, performans ve ölçeklenebilirlik açısından kritik bir rol oynayabilir. Örneğin, yoğun bir kullanıcı trafiği altında çalışan bir e-ticaret platformunu ele alalım. Burada, ürün listeleme sayfalarının hızlıca yüklenmesi gerekiyor ve kullanıcıların aynı verilere sıkça eriştiği düşünülürse, cache oldukça faydalı bir çözüm olabilir.
Böyle bir senaryoda, Redis gibi bir in-memory cache çözümü tercih edilebilir. Kullanıcı bir ürün bilgisi talep ettiğinde, önce cache’e bakılır; eğer veri cache’te mevcut değilse, veritabanından çekilip hem kullanıcıya sunulur hem de cache’e yazılır. Bu, "Read-Through" adı verilen bir stratejiyle yapılabilir. Ayrıca, verilerin güncelliğini sağlamak için TTL (Time-to-Live) mekanizması kullanılabilir. Örneğin, ürün bilgileri 24 saat boyunca cache’te tutulabilir, ancak stok durumu veya fiyat gibi dinamik veriler için daha kısa TTL süreleri belirlenebilir.
Bunun dışında, popüler ürünlerin önceden tahmin edilip cache’e alınması (prefetching) veya cache miss durumlarında performansı artıran farklı stratejiler uygulanabilir. Cache’in dolması durumunda LRU (Least Recently Used) gibi bir politika ile eski ya da az kullanılan veriler çıkarılarak yer açılabilir.
Dağıtık sistemlerde ölçeklenebilirliği sağlamak için de Redis Cluster gibi bir çözüm kullanılabilir. Consistent hashing ile verilerin farklı node’lara dengeli şekilde dağıtılması sağlanabilir ve sistemin ölçeklenebilirliği artırılabilir.
51. Sisteminizde bir endpoint aşırı yüklenmeye başladı ve bu yüklenme diğer servislerin performansını etkiliyor. Bu durumda ne yapardınız?
Rate Limiting: API'yi kullanan her kullanıcı veya istemci için saniyede belirli bir istek sınırı koyarak aşırı yüklenmeyi azaltırım.Caching: Eğer bu API statik veya sıkça tekrarlanan veriler sağlıyorsa, önbellekleme yaparım. Örneğin, son kullanıcıya gönderilen veriyi bir süre için cache’te tutarım.
Queueing (Kuyruklama): İstekleri bir kuyrukta işleme alarak yoğun talebi düzenlerim. Bu, sistemin tamamen çökmesini önleyebilir.
Yatay Ölçekleme: API'nin bulunduğu servisi ölçeklendirmek, yani daha fazla sunucuya dağıtmak da bir çözüm olabilir.
52. Sisteminizde bir mikroservis, diğer tüm servislere bağımlı ve bu bağımlılık sistemi yavaşlatıyor. Bu durumda ne yaparsınız?
Mikroservislerin bağımlılıklarını azaltmak için olay tabanlı mimari (Event-Driven Architecture) kullanabilirim. Örneğin, bağımlı servislerden alınan verileri bir mesaj kuyruğu (Kafka, RabbitMQ gibi) üzerinden işlemek bu problemi hafifletir.Servisin tek bir işlemi bloke etmemesi için asenkron iletişim veya yedek veri sunumunu (fallback mekanizması) devreye alabilirim.
Servislerin işlevlerini daha bağımsız hale getirmek için Domain-Driven Design (DDD) yaklaşımıyla bağımlılıkları yeniden değerlendirebilirim.
53. Spring Data JPA kullanarak karmaşık bir sorgu oluşturdunuz ancak performans sorunları yaşadınız. Hangi araçları veya teknikleri kullanarak bu performans sorunlarını analiz eder ve çözersiniz?
EXPLAIN ile sorgunun execution planını analiz ederim.
- Hibernate logging'i açıp üretilen SQL sorgularını incelerim.
- Gereksiz EAGER fetch'leri LAZY fetch ile değiştiririm.
- Sorguyu optimize etmek için indeks eklerim veya mevcut indeksleri kontrol ederim.
- Büyük veri setlerinde Pageable ile pagination kullanırım.
- Gerekli alanları çekmek için DTO uygularım
54. Veritabanı normalizasyonu nedir?
Veritabanı normalizasyonu, bir veritabanındaki veri tekrarını azaltmak ve veri tutarlılığını sağlamak için tasarım kurallarının uygulanması sürecidir. Bu işlem, veritabanını bir dizi mantıksal tablolara bölerek, ilişkisel veri modeline uygun hale getirir. Amaç, veri anomalilerini önlemek, depolama alanını optimize etmek ve sorgu performansını artırmaktır. Normalizasyon genellikle 1NF (Birinci Normal Form) ile başlar ve 3NF (Üçüncü Normal Form) veya ihtiyaç duyulursa daha ileri aşamalara kadar devam eder.
55. Immutability nedir? niye kullanıyoruz?
Detaylı bilgi için Medium yazımı inceleyebilirsiniz: Java’da Immutable Nedir? Neden Kullanılır?
56. Qualifier anotasyonunu neden kullanırız?
Spring'te birden fazla bean tanımlı olduğunda, hangi bean'in kullanılacağını belirlemek için kullanılır. Eğer aynı türde birden fazla bean tanımlanmışsa (örneğin, Service sınıfından iki farklı implementasyon), @Qualifier ile hangi bean'in kullanılacağını belirtiriz.