Spring Java'da modern, ölçeklenebilir web uygulamaları oluşturmaya yönelik reaktif, engellemeyen bir web çerçevesidir. Spring Framework'ün bir parçasıdır ve Java'da reaktif programlamayı uygulamak için Reactor kütüphanesini kullanır. WebFlux, WebFlux ile çok sayıda eş zamanlı isteği ve veri akışını işleyebilen yüksek performanslı, ölçeklenebilir web uygulamaları oluşturabilirsiniz. Basit REST API'lerinden gerçek zamanlı veri akışına ve sunucu tarafından gönderilen olaylara kadar çok çeşitli kullanım örneklerini destekler. Spring WebFlux, reaktif akışlara dayalı bir programlama modeli sağlar; bu, eş zamanlı olmayan ve engellemeyen işlemleri veri işleme aşamalarından oluşan bir işlem hattında birleştirmenize olanak tanır. Ayrıca reaktif veri erişimi, reaktif güvenlik ve reaktif test desteği de dahil olmak üzere reaktif web uygulamaları oluşturmaya yönelik zengin bir dizi özellik ve araç sağlar. : Resmi Bahar belgesinden "Reaktif" terimi, G/Ç olaylarına tepki veren ağ bileşenleri, fare olaylarına tepki veren kullanıcı arayüzü denetleyicileri ve diğerleri gibi değişime tepki verme etrafında oluşturulan programlama modellerini ifade eder. Bu anlamda engellememe tepkiseldir, çünkü artık engellenmek yerine, işlemler tamamlandığında veya veriler kullanılabilir hale geldikçe bildirimlere tepki verme modundayız. Diş açma modeli Reaktif programlamanın temel özelliklerinden biri, birçok eşzamanlı web çerçevesinde kullanılan geleneksel istek başına iş parçacığı modelinden farklı olan iş parçacığı modelidir. Geleneksel modelde, gelen her isteği işlemek için yeni bir iş parçacığı oluşturulur ve bu iş parçacığı, istek işlenene kadar engellenir. Bu, yüksek hacimli isteklerle uğraşırken ölçeklenebilirlik sorunlarına yol açabilir; istekleri işlemek için gereken iş parçacığı sayısı çok artabilir ve iş parçacığı bağlamı değiştirme bir darboğaz haline gelebilir. Buna karşılık WebFlux, az sayıda iş parçacığının çok sayıda isteği karşılayabildiği, engellemeyen, olaya dayalı bir model kullanır. Bir istek geldiğinde, mevcut iş parçacıklarından biri tarafından işlenir ve bu iş parçacığı daha sonra gerçek işlemeyi bir dizi eşzamansız göreve devreder. Bu görevler engelleyici olmayan bir şekilde yürütülür ve görevler arka planda yürütülürken iş parçacığının diğer istekleri işlemeye devam etmesine olanak tanır. Spring WebFlux'ta (ve genel olarak engellemeyen sunucularda), uygulamaların engellemediği varsayılır. Bu nedenle, engellemeyen sunucular, istekleri işlemek için küçük, sabit boyutlu bir iş parçacığı havuzu (olay döngüsü çalışanları) kullanır. Klasik bir Servlet Container'ın basitleştirilmiş iş parçacığı modeli şuna benzer: WebFlux istek işleme biraz farklı olsa da: Kaputun altında Devam edelim ve parlak teorinin arkasında ne olduğunu görelim. tarafından oluşturulan oldukça minimalist bir uygulamaya ihtiyacımız var. Kod mevcuttur. Spring Initializr GitHub deposunda İş parçacığıyla ilgili tüm konular CPU'ya oldukça bağımlıdır. Genellikle istekleri işleyen işlem parçacıklarının sayısı sayısıyla ilişkilidir Eğitim amaçlı olarak, Docker kapsayıcısını çalıştırırken CPU'ları sınırlayarak bir havuzdaki iş parçacığı sayısını kolayca değiştirebilirsiniz: CPU çekirdeği . docker run --cpus=1 -d --rm --name webflux-threading -p 8081:8080 local/webflux-threading Bir havuzda hâlâ birden fazla iş parçacığı görüyorsanız sorun değil. WebFlux tarafından belirlenen olabilir. varsayılanlar Uygulamamız basit bir falcıdır. endpoint'i çağırdığınızda, ile 5 kayıt alacaksınız. Her ayarlama, size verilen karmayı temsil eden bir tam sayıdır. Evet, çok cömertiz çünkü uygulama yalnızca pozitif sayılar üretiyor. Artık kötü şans yok! /karma balanceAdjustment Varsayılan işleme Çok basit bir örnekle başlayalım. Sonraki denetleyici yöntemi, 5 karma öğesi içeren bir Flux döndürür. @GetMapping("/karma") public Flux<Karma> karma() { return prepareKarma() .map(Karma::new) .log(); } private Flux<Integer> prepareKarma() { Random random = new Random(); return Flux.fromStream( Stream.generate(() -> random.nextInt(10)) .limit(5)); } yöntemi burada çok önemli bir şeydir. Tüm Reaktif Akış sinyallerini gözlemler ve bunları INFO düzeyindeki günlüklere kadar takip eder. log curl günlük çıktısı aşağıdaki gibidir: localhost:8081/karma Görebildiğimiz gibi, IO iş parçacığı havuzunda işlem yapılıyor. Konu adı anlamına gelir. Görevler, onları gönderen iş parçacığında hemen yürütüldü. Reactor bunları başka bir havuza planlamak için herhangi bir talimat görmedi. ctor-http-nio-2 reactor-http-nio-2 Geciktirme ve paralel işleme Bir sonraki işlem, yayılan her öğeyi 100 ms geciktirecek (diğer bir deyişle veritabanı emülasyonu) @GetMapping("/delayedKarma") public Flux<Karma> delayedKarma() { return karma() .delayElements(Duration.ofMillis(100)); } Orijinal çağrısında zaten bildirilmiş olduğundan buraya yöntemini eklememize gerek yok. karma() log Günlüklerde bir sonraki resmi görebiliriz: Bu sefer IO iplik yalnızca ilk eleman alındı. Geri kalan 4'ünün işlenmesi bir iş parçacığı havuzuna ayrıldı. reactor-http-nio-4 parallel Javadoc'u bunu doğrular: delayElements Sinyaller geciktirilir ve paralel varsayılan Zamanlayıcıda devam eder Çağrı zincirinin herhangi bir yerinde komutunu belirterek aynı etkiyi gecikmeden elde edebilirsiniz. .subscribeOn(Schedulers.parallel()) zamanlayıcının kullanılması, birden fazla görevin farklı iş parçacıklarında aynı anda yürütülmesine izin vererek performansı ve ölçeklenebilirliği artırabilir; bu, CPU kaynaklarını daha iyi kullanabilir ve çok sayıda eşzamanlı isteği işleyebilir. parallel Bununla birlikte, kod karmaşıklığını ve bellek kullanımını da artırabilir ve maksimum çalışan iş parçacığı sayısı aşılırsa potansiyel olarak iş parçacığı havuzunun tükenmesine yol açabilir. Bu nedenle iş parçacığı havuzunu kullanma kararı, uygulamanın özel gereksinimlerine ve değiş tokuşlarına dayanmalıdır. parallel Alt zincir Şimdi daha karmaşık bir örneğe bakalım. Kod hala oldukça basit ve anlaşılır ancak çıktı çok daha ilginç. kullanacağız ve falcıyı daha getireceğiz. Her Karma örneği için, orijinal ayarlamayı 10 ile çarpacak ve zıt ayarlamaları üreterek, orijinali telafi eden dengeli bir işlemi etkili bir şekilde yaratacaktır. flatMap adil hale @GetMapping("/fairKarma") public Flux<Karma> fairKarma() { return delayedKarma() .flatMap(this::makeFair); } private Flux<Karma> makeFair(Karma original) { return Flux.just(new Karma(original.balanceAdjustment() * 10), new Karma(original.balanceAdjustment() * -10)) .subscribeOn(Schedulers.boundedElastic()) .log(); } Gördüğünüz gibi Flux'u bir Elastik iş parçacığı havuzuna abone olmalıdır. İlk iki Karma için kayıtlarımızda neler olduğuna bir göz atalım: makeFair's boundedElastic Reactor, IO iş parçacığındabalanceAdjustment ile ilk öğeye abone olur balanceAdjustment=9 Daha sonra, havuzu iş parçacığında ve ayarlamalar yayarak Karma adaleti üzerinde çalışır boundedElastic boundedElastic-1 90 -90 İlkinden sonraki öğeler paralel iş parçacığı havuzuna abone olur (çünkü zincirde hâlâ öğeler var) delayedElements zamanlayıcı boundedElastic nedir ? İş yüküne bağlı olarak çalışan iş parçacıklarının sayısını dinamik olarak ayarlayan bir iş parçacığı havuzudur. Veritabanı sorguları ve ağ istekleri gibi G/Ç bağlantılı görevler için optimize edilmiştir ve çok fazla iş parçacığı oluşturmadan veya kaynak israfına yol açmadan çok sayıda kısa süreli görevi gerçekleştirecek şekilde tasarlanmıştır. Varsayılan olarak, iş parçacığı havuzunun maksimum boyutu, kullanılabilir işlemci sayısının 10 ile çarpılmasıyla , ancak gerekirse farklı bir maksimum boyut kullanacak şekilde yapılandırabilirsiniz. boundedElastic bulunur gibi eşzamansız bir iş parçacığı havuzu kullanarak, iş parçacıklarını ayırmak için görevleri boşaltabilir ve diğer istekleri işlemek için ana iş parçacığını serbest bırakabilirsiniz. İş parçacığı havuzunun sınırlı yapısı, iş parçacığı açlığını ve aşırı kaynak kullanımını önleyebilir; havuzun esnekliği ise iş yüküne bağlı olarak çalışan iş parçacığı sayısını dinamik olarak ayarlamasına olanak tanır. boundedElastic Diğer iş parçacığı havuzu türleri Kullanıma hazır sınıfı tarafından sağlanan iki tür havuz daha vardır: Scheduler : Bu, eşzamanlı yürütme için tasarlanmış tek iş parçacıklı, serileştirilmiş bir yürütme bağlamıdır. Bir görevin sırayla yürütüldüğünden ve iki görevin aynı anda yürütülmediğinden emin olmanız gerektiğinde kullanışlıdır. single : Bu, herhangi bir iş parçacığı değişimi olmadan çağıran iş parçacığında görevleri hemen yürüten bir zamanlayıcının önemsiz, işlemsiz bir uygulamasıdır. immediate Çözüm Spring WebFlux'taki iş parçacığı modeli, engellemesiz ve eşzamansız olacak şekilde tasarlanmıştır ve minimum kaynak kullanımıyla çok sayıda isteğin verimli bir şekilde işlenmesine olanak tanır. WebFlux, bağlantı başına özel iş parçacıklarına güvenmek yerine, gelen istekleri işlemek ve işi çeşitli iş parçacığı havuzlarından çalışan iş parçacıklarına dağıtmak için az sayıda olay döngüsü iş parçacığı kullanır. Ancak iş parçacığının tükenmesini önlemek ve sistem kaynaklarının verimli kullanımını sağlamak için kullanım durumunuz için doğru iş parçacığı havuzunu seçmeniz önemlidir.