Reactive Core

All lectures for UZ purposes
Daraja, Dars
Mavjud
  • Server so'rovlarini qayta ishlash uchun ikki darajali qo'llab-quvvatlash vositalari mavjud.

    • HttpHandler: HTTP-so'rovlarini Reactive Streams spetsifikatsiyasiga mos ravishda bloklanmaydigan kiritish-chiqarish bilan qayta ishlash uchun asosiy shartnoma, shuningdek Reactor Netty, Undertow, Tomcat, Jetty va har qanday Servlet 3.1+ konteynerlari uchun adapterlar.

    • WebHandler API: So'rovlarni qayta ishlash uchun bir oz yuqoriroq darajadagi umumiy veb-API bo'lib, uning asosida anotatsiyalangan kontrollerlar va funksional tugatish nuqtalari kabi aniq dasturlash modellari quriladi.

  • Klient qismi uchun HTTP-so'rovlarini bloklanmaydigan kiritish-chiqarish va Reactive Streams spetsifikatsiyasiga mos ravishda bajarish uchun asosiy ClientHttpConnector shartnomasi, shuningdek Reactor Netty, reaktiv Jetty HttpClient va Apache HttpComponents uchun adapterlar mavjud. Ilovalarda foydalaniladigan yuqoriroq darajadagi WebClient ushbu asosiy shartnomaga asoslanadi.

  • Klient va server uchun HTTP-so'rovlar va javoblar tarkibini serializatsiya va deserializatsiya qilish uchun kodeklar mavjud.

HttpHandler

HttpHandler — bu so'rov va javobni qayta ishlash uchun bitta metoddan iborat oddiy shartnoma. U qasddan qat'iy va uning asosiy va yagona maqsadi — turli HTTP-server API-lari ustidagi oddiy abstraksiyani taqdim etishdir.

Quyidagi jadvalda qo'llab-quvvatlanadigan server API-lari ta'riflangan:

Server nomi Foydalaniladigan server API-si Reactive Streams qo'llab-quvvatlash

Netty

Netty API

Reactor Netty

Undertow

Undertow API

spring-web: Reactive Streams ko'prigi uchun adapter

Tomcat

Servlet 3.1 asosidagi bloklanmaydigan kiritish-chiqarish; byte[] ga qarshi ByteBuffers o'qish va yozish uchun Tomcat API

spring-web: Servlet 3.1 bloklanmaydigan kiritish-chiqarishdan Reactive Streams ko'prigiga

Jetty

Servlet 3.1 asosidagi bloklanmaydigan kiritish-chiqarish; byte[] ga qarshi ByteBuffers yozish uchun Jetty API

spring-web: Servlet 3.1 bloklanmaydigan kiritish-chiqarishdan Reactive Streams ko'prigiga

Servlet 3.1 konteyner

Servlet 3.1 asosidagi bloklanmaydigan kiritish-chiqarish

spring-web: Servlet 3.1 bloklanmaydigan kiritish-chiqarishdan Reactive Streams ko'prigiga

Quyidagi jadvalda serverdan bo'lgan bog'lanishlar ta'riflangan (ko'proq ma'lumot uchun qo'llab-quvvatlanadigan versiyalarga qarang):

Server nomi Guruh identifikatori Artefakt nomi

Reactor Netty

io.projectreactor.netty

reactor-netty

Undertow

io.undertow

undertow-core

Tomcat

org.apache.tomcat.embed

tomcat-embed-core

Jetty

org.eclipse.jetty

jetty-server, jetty-servlet

Quyidagi kod parchalarida HttpHandler adapterlarini har bir server API bilan qanday ishlatilishi ko'rsatilgan:

Reactor Netty

Java
HttpHandler handler = ...
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create().host(host).port(port).handle(adapter).bind().block();
Kotlin
val handler: HttpHandler = ...
val adapter = ReactorHttpHandlerAdapter(handler)
HttpServer.create().host(host).port(port).handle(adapter).bind().block()

Undertow

Java
HttpHandler handler = ...
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();
Kotlin
val handler: HttpHandler = ...
val adapter = UndertowHttpHandlerAdapter(handler)
val server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build()
server.start()

Tomcat

Java
HttpHandler handler = ...
Servlet servlet = new TomcatHttpHandlerAdapter(handler);
Tomcat server = new Tomcat();
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootContext = server.addContext("", base.getAbsolutePath());
Tomcat.addServlet(rootContext, "main", servlet);
rootContext.addServletMappingDecoded("/", "main");
server.setHost(host);
server.setPort(port);
server.start();
Kotlin
val handler: HttpHandler = ...
val servlet = TomcatHttpHandlerAdapter(handler)
val server = Tomcat()
val base = File(System.getProperty("java.io.tmpdir"))
val rootContext = server.addContext("", base.absolutePath)
Tomcat.addServlet(rootContext, "main", servlet)
rootContext.addServletMappingDecoded("/", "main")
server.host = host
server.setPort(port)
server.start()

Jetty

Java
HttpHandler handler = ...
Servlet servlet = new JettyHttpHandlerAdapter(handler);
Server server = new Server();
ServletContextHandler contextHandler = new ServletContextHandler(server, "");
contextHandler.addServlet(new ServletHolder(servlet), "/");
contextHandler.start();
ServerConnector connector = new ServerConnector(server);
connector.setHost(host);
connector.setPort(port);
server.addConnector(connector);
server.start();
Kotlin
val handler: HttpHandler = ...
val servlet = JettyHttpHandlerAdapter(handler)
val server = Server()
val contextHandler = ServletContextHandler(server, "")
contextHandler.addServlet(ServletHolder(servlet), "/")
contextHandler.start();
val connector = ServerConnector(server)
connector.host = host
connector.port = port
server.addConnector(connector)
server.start()

Servlet 3.1+ konteyner

Har qanday Servlet 3.1+ konteynerida WAR-faylni joylashtirish uchun AbstractReactiveWebInitializer ni kengaytirib, WAR-faylga kiritishingiz mumkin. Ushbu klass HttpHandler ni ServletHttpHandlerAdapter ga o'rab, uni Servlet sifatida ro'yxatdan o'tkazadi.

WebHandler API

org.springframework.web.server paketi HttpHandler shartnomasiga asoslanib, bir nechta WebExceptionHandler, bir nechta WebFilter va bir WebHandler komponentidan iborat tarmoqli umumiy veb-API ni ta'minlaydi. Tarmoq WebHttpHandlerBuilder bilan oddiygina Spring'dan ApplicationContext ni ko'rsatish orqali yig'ilishi mumkin, bu erda komponentlar avtomatik ravishda aniqlanadi va/yoki komponentlarni konstruktorga ro'yxatdan o'tkazish orqali.

HttpHandler ning maqsadi turli HTTP-serverlardan foydalanishni ob'ektlashtirish bo'lsa, WebHandler API veb-ilovalarda odatda foydalaniladigan ko'proq funktsiyalar to'plamini taqdim etishga qaratilgan, masalan:

  • Foydalanuvchi sessiyasi atributlar bilan.

  • So'rov atributlari.

  • So'rov uchun ruxsat etilgan Locale yoki Principal.

  • Parslangan va keshlangan forma ma'lumotlariga kirish.

  • Ko'p komponentli ma'lumotlar uchun abstraksiyalar.

  • va yana ko'p narsalar...

Maxsus binlar turlari

Quyidagi jadvalda WebHttpHandlerBuilder tomonidan Spring'dan bo'lgan ApplicationContext da avtomatik ravishda aniqlanishi mumkin bo'lgan yoki to'g'ridan-to'g'ri ro'yxatdan o'tkazilgan komponentlar keltirilgan:

Bin nomi Bin turi Hisoblagich Ta'rif

<any>

WebExceptionHandler

0..N

WebFilter va maqsadli WebHandler dan bo'lgan tarmoq nusxalaridan xatoliklarni qayta ishlashni ta'minlaydi.

<any>

WebFilter

0..N

Qolgan filtrlar tarmog'i va maqsadli WebHandler oldidan va keyinchalik intervenlik uslubidagi logikani qo'llaydi.

webHandler

WebHandler

1

So'rovni qayta ishlovchi.

webSessionManager

WebSessionManager

0..1

ServerWebExchange uchun metod orqali ochilgan WebSession nusxalarini boshqaruvchi. Standart DefaultWebSessionManager.

serverCodecConfigurer

ServerCodecConfigurer

0..1

ServerWebExchange uchun metodlar orqali ochilgan forma ma'lumotlari va ko'p komponentli ma'lumotlar uchun HttpMessageReader nusxalariga kirishni ta'minlaydi. Standart bo'lib ServerCodecConfigurer.create().

localeContextResolver

LocaleContextResolver

0..1

ServerWebExchange uchun metod orqali ochilgan LocaleContext uchun tanlov vositasi. Standart AcceptHeaderLocaleContextResolver.

forwardedHeaderTransformer

ForwardedHeaderTransformer

0..1

Yuborilgan turdagi sarlavhalarini ishlatish yoki ular orqali chiqarish, yoki faqat ularni chiqarib yoo'q qilish uchun mo'ljallangan. Standart bo'lib ishlatilmaydi.

Forma ma'lumotlari

ServerWebExchange forma ma'lumotlariga kirish uchun quyidagi metodni ta'minlaydi:

Java
Mono<MultiValueMap<String, String>> getFormData();
Kotlin
suspend fun getFormData(): MultiValueMap<String, String>

The DefaultServerWebExchange uses the configured HttpMessageReader to parse form data (application/x-www-form-urlencoded) into a MultiValueMap. Standart bo'lib FormHttpMessageReader ServerCodecConfigurer bini orqali konfiguratsiya qilingan.

Ko'p komponentli ma'lumotlar

ServerWebExchange ko'p komponentli ma'lumotlarga kirish uchun quyidagi metodni ta'minlaydi:

Java
Mono<MultiValueMap<String, Part>> getMultipartData();
Kotlin
suspend fun getMultipartData(): MultiValueMap<String, Part>

DefaultServerWebExchange multipart/form-data tarkibini MultiValueMap ga parslash uchun konfiguratsiyalangan HttpMessageReader<MultiValueMap<String, Part>> ni ishlatadi. Standart bo'lib bu DefaultPartHttpMessageReader, bu hech qanday tashqi bog'lanishlarni o'z ichiga olmaydi. Alternativ ravishda Synchronoss NIO Multipart kutubxonasiga asoslangan SynchronossPartHttpMessageReader dan foydalanishingiz mumkin. Ikkalasi ham ServerCodecConfigurer bini orqali sozlanadi.

Ko'p komponentli ma'lumotlarni oqimli parslash uchun HttpMessageReader<Part> dan qaytarilgan Flux<Part> dan foydalanishingiz mumkin. Masalan, anotatsiyalangan kontrollda @RequestPart dan foydalanish mavhumlangan kirish imkoniyatini ta'minlaydi va shuning uchun barcha ko'p komponentli ma'lumotlarni to'liq parslashni talab qiladi. Boshqa tomondan, siz @RequestBody annotatsiyasidan foydalanib, tarkibni Flux<Part> ga dekodlashingiz mumkin, MultiValueMap ga to'plamay.

Yuborilgan sarlavhalar

Agar so'rov proxy-xizmatdan o'tsa (masalan, xost va port o'zgarishi mumkin). Bu, mijozni to'g'ri xost, port va sxemani ko'rsatadigan havolalarni yaratishda qiyinchiliklarga olib kelishi mumkin.

RFC 7239 HTTP sarlavhasini aniqlaydi Forwarded, bu proxy-xizmatlar asl so'rov haqidagi ma'lumotlarni taqdim etish uchun ishlatilishi mumkin. Boshqa noan'anaviy sarlavhalar mavjud, jumladan X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto, X-Forwarded-Ssl va X-Forwarded-Prefix.

ForwardedHeaderTransformer - bu komponent, u so'rov xosti, porti va sxemasini yuborilgan sarlavhalar asosida o'zgartiradi va keyin ushbu sarlavhalarni olib tashlaydi. Agar siz uni forwardedHeaderTransformer nomli bin sifatida e'lon qilsangiz, u aniqlanadi va ishlatiladi.

Yuborilgan sarlavhalar uchun ba'zi xavfsizlik ehtiyot choralari mavjud, chunki ilova sarlavhalar kutilganidek proxy-xizmat tomonidan qo'shilganmi yoki yomon niyatli mijoz tomonidanmidi, bilishi mumkin emas. Shuning uchun ishonch chegarasidagi proxy-xizmat tashqi manbalardan keladigan ishonchsiz ma'lumotlarni olib tashlash uchun sozlangan bo'lishi kerak. Shuningdek, removeOnly=true bilan ForwardedHeaderTransformer ni sozlashingiz mumkin, va bu holda u sarlavhalarni olib tashlaydi, lekin ularni ishlatmaydi.

5.1 versiyasida ForwardedHeaderFilter eskirgan holga keltirildi va ForwardedHeaderTransformer bilan almashtirildi, shuning uchun yuborilgan sarlavhalar erta, almashinuv yaratishdan oldin qabul qilinishi mumkin. Agar filtr hali ham sozlangan bo'lsa, u filtrlar ro'yxatidan chiqariladi va uning o'rniga ForwardedHeaderTransformer ishlatiladi.

Filtrlar

WebHandler API'sida siz WebFilter dan foydalanib, qolgan filtrlar tarmog'i va maqsadli WebHandler oldidan va keyinchalik intervenlik uslubidagi logikani qo'llashingiz mumkin. WebFlux konfiguratsiyasidan foydalanganda WebFilter ni ro'yxatdan o'tkazish juda oson – uni Spring bin sifatida e'lon qilish va (ixtiyoriy ravishda) ustunlik darajasini belgilash uchun bin e'lonida @Order annotatsiyasidan foydalanish yoki Ordered klassini amalga oshirish kifoya.

CORS

Spring WebFlux kontrollerlar uchun annotatsiyalar yordamida CORS konfiguratsiyasini nozik qo'llab-quvvatlashni ta'minlaydi. Ammo, agar siz uni Spring Security bilan ishlatsangiz, himoyalangan CorsFilter ga tayanishingizni tavsiya qilamiz.

Exceptions

WebHandler API'sida siz WebExceptionHandler dan foydalanib, WebFilter va maqsadli WebHandler dan bo'lgan tarmoq nusxalaridan bo'lgan xatolarni qayta ishlashingiz mumkin. WebFlux konfiguratsiyasidan foydalanganda WebExceptionHandler ni ro'yxatdan o'tkazish Spring bin sifatida e'lon qilish kabi oson va (ixtiyoriy ravishda) ustunlik darajasini belgilash uchun bin e'lonida @Order annotatsiyasidan foydalanish yoki Ordered klassini amalga oshirishga o'xshash oson.

Quyidagi jadvalda mavjud WebExceptionHandler realizatsiyalari ta'riflangan:

Xatolik qayta ishlovchi Ta'rif

ResponseStatusExceptionHandler

Xatolikni loyiha orqali HTTP holat kodiga mos keladigan javobni o'rnatish orqali ResponseStatusException turidagi xatoliklarni qayta ishlashni ta'minlaydi.

WebFluxResponseStatusExceptionHandler

ResponseStatusExceptionHandler ning kengaytmasi, bu har qanday xatolik uchun @ResponseStatus ga asoslangan HTTP holat kodini ham aniqlay oladi.

Ushbu qayta ishlovchi WebFlux Config'da e'lon qilingan.

Kodeklar

spring-web va spring-core modullari byte'li tarkibni yuqori darajada ob'ektlarga va ulardan serializatsiya va deserializatsiya vositalarini taqdim etadi, bu esa Reactive Streams spetsifikatsiyasidan bloklanmaydigan kiritish-chiqarish va qayta aloqa orqali amalga oshiriladi. Quyida ushbu qo'llab-quvvatlovchi vositalar ta'riflangan:

  • Encoder va Decoder — bu HTTP protokoliga bog'liq bo'lmagan tarkibni kodlash va dekodlash uchun past darajadagi shartnomalar.

  • HttpMessageReader va HttpMessageWriter — bu HTTP xabarlar tarkibini kodlash va dekodlash uchun shartnomalar.

  • Encoder ni EncoderHttpMessageWriter ga o'ramoq uchun uni veb-ilovada foydalanish uchun moslash mumkin, Decoder ni esa DecoderHttpMessageReader ga o'ramoq mumkin.

  • DataBuffer har xil byte buferlari (masalan, ByteBuf, java.nio.ByteBuffer uchun Netty va hokazolar) bilan ishlashni abstrakt qiladi va bütün kodeklar ham aynan shunga ishlaydi.

spring-core moduli byte[], ByteBuffer, DataBuffer, Resource va String ning encoder va decoder realizatsiyalarini o'z ichiga oladi. spring-web moduli Jackson JSON, Jackson Smile, JAXB2, Protocol Buffers va boshqa kodeklar va dekoderni web-muvofiqlashtirilgan HTTP xabarlarini yozish va o'qish vositalari bilan birga forma ma'lumotlari, ko'p komponentli tarkib, server tomonidan yuborilgan hodisalar va boshqalarni o'z ichiga oladi.

ClientCodecConfigurer va ServerCodecConfigurer odatda ilovada kodeklarni sozlash va moslashtirish uchun ishlatiladi.

Jackson JSON

JSON formati va binary JSON (Smile) Jackson kutubxonasi mavjud bo'lganda qo'llab-quvvatlanadi.

Jackson2Decoder quyidagicha ishlaydi:

  • Asinxron, bloklanmaydigan Jackson kutubxonasi parseri byte bo'laklar oqimini JSON ob'ektini ifodalovchi TokenBuffer nusxalariga birlashtiradi.

  • Har bir TokenBuffer Jackson kutubxonasidagi ObjectMapper ga yuqori darajada ob'ekt yaratish uchun o'tkaziladi.

  • Agar bitta qiymatli Mono publikatoriga dekodlash qilinadigan bo'lsa, bitta TokenBuffer mavjud.

  • Ko'p qiymatli Flux publikatoriga dekodlash qilinadigan bo'lsa, har bir TokenBuffer to'liq shakllangan ob'ekt uchun etarli byte ma'lumotlari olinganligi bilan ObjectMapper ga o'tkaziladi. Kiruvchi tarkib JSON massivi yoki har qanday JSON oqimi formati, masalan, NDJSON, JSON Lines yoki JSON Text Sequences bo'lishi mumkin.

Jackson2Encoder quyidagicha ishlaydi:

  • Bitta qiymatli publikator (masalan, Mono) uchun uni ObjectMapper orqali oddiygina serializatsiya qilamiz.

  • Ko'p qiymatli publikator (application/json) default bo'lib, qiymatlarni Flux#collectToList() yordamida to'plab, keyin hosil bo'lgan to'plamni serializatsiya qilamiz.

  • Ko'p qiymatli publikator (application/x-ndjson yoki application/stream+x-jackson-smile kabi oqimda ishlaydigan media turi bilan), har bir qiymatni JSON oqimi formati yordamida kodlash, yozish va tushirishni amalga oshiramiz. Kodlovchida boshqa oqim media turlari ham ro'yxatdan o'tkazilishi mumkin.

  • SSE (server tomonidan yuborilgan hodisalar) holatida Jackson2Encoder har bir hodisaga chaqiriladi va chiqishi kechikishsiz uzatishga ishonch hosil qilish uchun tushiriladi.

Default bo'lib Jackson2Encoder va Jackson2Decoder String turidagi elementlarni qo'llab-quvvatlamaydi. Buning o'rniga default bo'lib CharSequenceEncoder bilan serializatsiyalashgan JSON-tarkibini qabul qilamiz. Agar Flux<String> dan JSON massivini yaratishni xohlasangiz, Flux#collectToList() ni ishlating va Mono<List<String>> ni kodlang.

Forma ma'lumotlari

FormHttpMessageReader va FormHttpMessageWriter application/x-www-form-urlencoded tarkibini dekodlash va kodlashni qo'llab-quvvatlaydi.

Server tomonida, formadan olingan tarkibga bir nechta joydan kirish talab etiladigan holatlarda, ServerWebExchange maxsus getFormData() metodini taqdim etadi, bu esa FormHttpMessageReader orqali tarkibni parslash va keyin natijalarni qayta kirish uchun keshlash imkoniyatini taqdim etadi.

Bir marta getFormData() dan foydalanilgandan so'ng, dastlabki xom tarkib so'rov tanasidan o'qilishi mumkin emas. Shu sababli, ilovalardan ServerWebExchange orqali keshlangan forma ma'lumotlariga kirish uchun ketma-ket foydalanishni talab qiladi, xom so'rov tanasidan o'qish o'rniga.

Ko'p komponentlilik

MultipartHttpMessageReader va MultipartHttpMessageWriter "multipart/form-data" tarkibini dekodlash va kodlashni qo'llab-quvvatlaydi. O'z navbatida MultipartHttpMessageReader haqiqiy parslashni Flux<Part> ga amalga oshirish uchun boshqa HttpMessageReader ga vakillik beradi va keyin qismlarini MultiValueMap ga to'playdi. Standart bo'lib DefaultPartHttpMessageReader ishlatiladi, lekin bu ServerCodecConfigurer orqali o'zgartirilishi mumkin. DefaultPartHttpMessageReader Javadoc ga qo'shimcha ma'lumot olish uchun qarang.

Server tomonida, ko'p komponentli forma tarkibiga bir nechta joydan kirish talab etiladigan holatlarda, ServerWebExchange maxsus getMultipartData() metodini taqdim etadi, bu esa MultipartHttpMessageReader orqali tarkibni parslash va keyin natijalarni qayta kirish uchun keshlash imkoniyatini taqdim etadi.

Bir marta getMultipartData() dan foydalanilgandan so'ng, dastlabki xom tarkib so'rov tanasidan o'qilishi mumkin emas. Shu sababli, ilovalardan getMultipartData() parametridan foydalanib komponentlarni qayta foydalanish uchun Map ko'rinishida olish yoki bir martalik kirishni SynchronossPartHttpMessageReader dan foydalanib olish talab qilinadi.

Chegaralar

Decoder va HttpMessageReader realizatsiyalari, kirish ma'lumotlar oqimini butunlay yoki qisman buferlashda, xotirada buferlashning maksimal byte hajmiga ega bo'lishi mumkin. Ba'zi hollarda buferlash kirish ma'lumotlarini yig'ib, bitta obyekt sifatida taqdim etish zarurligidan kelib chiqadi – masalan, @RequestBody byte[] bilan annotatsiyalangan metod, x-www-form-urlencoded ma'lumotlar va hk. Oqimda buferlash sodir bo'lganda esa, kirish oqimi ajratilgan bo'lishi mumkin – masalan, matnli ajratkichlar, JSON oqimidagi obyektlar va hk. Ushbu oqim hollari uchun cheklash himoyalangan obyekt bilan bog'liq byte hajmiga nisbatan qo'llaniladi.

Bufer hajmlarini sozlash uchun, Decoder yoki HttpMessageReader maxInMemorySize xususiyatini ochadiganligini tekshirish mumkin, va agar bo'lsa, Javadoc default qiymatlari haqida batafsil ma'lumot beradi. Server tomonida ServerCodecConfigurer barcha kodeklar uchun bir joydan o'rnatish imkoniyatiga ega. Klient tomonida barcha kodeklar uchun cheklashni WebClient.Builder'da o'zgartirish mumkin.

Ko'p komponentli parsashtirish uchun maxInMemorySize xususiyati xom komponentlar hajmini cheklaydi. Fayl komponentlari uchun esa bu diskda yoziladigan chegarani belgilaydi. Diskda yozilgan fayl komponentlari uchun har bir komponent uchun disk maydoni hajmini cheklash uchun maxDiskUsagePerPart xususiyati mavjud. Ko'p komponentli so'rovdagi umumiy komponentlar sonini cheklash uchun maxParts xususiyati mavjud. WebFlux'da barcha uchta qismlarni sozlash uchun oldindan konfiguratsiya qilingan MultipartHttpMessageReader nusxasini ServerCodecConfigurer'da belgilash kerak.

Oqimda uzatish

HTTP javobida (masalan, text/event-stream, application/x-ndjson) ma'lumotlarni oqimda uzatishda, iloji boricha erta uzilgan mijozni aniqlash uchun ma'lumotlarni davriy uzatish muhimdir. Bunday uzatish faqat izoh, bo'sh SSE hodisasi yoki boshqa "no-op" ma'lumotlar, ular samarador qilib heartbeat xabariga xizmat qiladi.

DataBuffer

DataBuffer WebFlux'dagi byte bufer uchun taqdim etilgan ko'rinishdir. Ba'zi serverlarda, masalan, Netty kabi byte buferlari poolda biriktirilgan va referensiyalar bo'yicha hisoblanadi va iste'mol qilinganda ozod qilinishi kerak, aks holda xotira oqishi sodir bo'lishi mumkin.

WebFlux'dagi ilovalar odatda to'g'ridan-to'g'ri byte buferlar iste'mol qilinmaganligini, yuqori darajadagi ob'ektlarga va teskari kodlangan kodeklarni ishlatish yoki o'z kodeklaringizni yaratmaguningizcha, bu haqida xavotirlanmasliklari kerak.

Loglash

Spring WebFlux'dagi DEBUG darajasidagi loglash ixcham, oddiy va odam uchun qulay qilib loyihalashtirilgan. U eng muhim bo'lgan ma'lumotlar bitlariga bag'ishlangan, bu ma'lumotlar tez-tez ishlatiladi va boshqa bo'lsa faqat maxsus muammoni tuzatish uchun ishlatiladi.

TRACE darajasidagi loglash DEBUG ga o'xshash tamoyillarga amal qiladi (va, masalan, juda ko'p bo'lmasligi kerak), lekin har qanday muammoni tuzatish uchun ishlatilishi mumkin. Bundan tashqari ba'zi log xabarlari turli darajadagi detalda bo'lishi mumkin TRACE va DEBUG.

Tegishli loglash loglar tajribasidan kelib chiqqan. Agar biror narsani loglashda noto'g'ri ekanligini sezsangiz, iltimos, bizga xabar bering.

Log identifikatori

WebFlux'da bitta so'rov bir nechta oqimlarda ishlashi mumkin, shunda oqim identifikatori log yozuvlarini ma'lum bir so'rovga bog'lash uchun foydasiz. Shuning uchun, WebFlux log xabarlari default bo'lib ma'lum bir so'rov identifikatori bilan prefiksga ega.

Server tomonida log identifikatori ServerWebExchange atributida saqlanadi (LOG_ID_ATTRIBUTE), va ushbu identifikator asosida to'liq formatlangan prefiks ServerWebExchange#getLogPrefix() dan olinadi. WebClient tomonida log identifikatori ClientRequest atributida saqlanadi (LOG_ID_ATTRIBUTE), va to'liq formatlangan prefiks ClientRequest#logPrefix() dan olinadi.

Xavfli ma'lumotlar

DEBUG va TRACE darajasidagi loglar xavfli ma'lumotlarni qayd qilishi mumkin. Shu sababli forma parametrlari va sarlavhalari default bo'lib maskalanadi va ularni to'liq log qilishni faqat siz explicit faollashtirishingiz kerak.

Quyidagi misolda server tomonidagi so'rovlar uchun bu qanday amalga oshirilishi ko'rsatilgan:

Java
@Configuration
@EnableWebFlux
class MyConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().enableLoggingRequestDetails(true);
}
}
Kotlin
@Configuration
@EnableWebFlux
class MyConfig : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
configurer.defaultCodecs().enableLoggingRequestDetails(true)
}
}

Quyidagi misolda klient tomonidagi so'rovlar uchun bu qanday amalga oshirilishi ko'rsatilgan:

Java
Consumer<ClientCodecConfigurer> consumer = configurer ->
configurer.defaultCodecs().enableLoggingRequestDetails(true);
WebClient webClient = WebClient.builder()
.exchangeStrategies(strategies -> strategies.codecs(consumer))
.build();
Kotlin
val consumer: (ClientCodecConfigurer) -> Unit  = { configurer -> configurer.defaultCodecs().enableLoggingRequestDetails(true) }
val webClient = WebClient.builder()
.exchangeStrategies({ strategies -> strategies.codecs(consumer) })
.build()

Appenders

Loglash kutubxonalari, masalan SLF4J va Log4J 2, bloklanmaydigan loglash uchun asinxron appenders taqdim etadi. Ular ba'zi kamchiliklarga, masalan, logga kiritilishi kerak bo'lgan xabarlarni o'tkazib yuborishi mumkin bo'lgan xabarlarni o'tkazib yuborishi mumkin bo'lsa-da, ular reaktiv, bloklanmaydigan ilovalar uchun mavjud bo'lgan eng yaxshi variantlardir.

Custom kodeklar

Ilovalar qo'shimcha media turlarini qo'llab-quvvatlash uchun yoki standard kodeklar orqali qo'llab-quvvatlanmaydigan maxsus logikani amalga oshirish uchun maxsus kodeklarni ro'yxatdan o'tkazishi mumkin.

Konfiguratsion parametrlar, dasturchilar tomonidan ifodalangan, standard kodeklar uchun qo'llanilishi mumkin. Custom kodeklar bunday sozlamalar bilan mos kelishi lozim, masalan, buferlashni majburlash yoki xavfsizlik ma'lumotlarini log qilish.

Quyidagi misolda klient tomonidagi so'rovlar uchun bu qanday amalga oshirilishi ko'rsatilgan:

Java
WebClient webClient = WebClient.builder()
.codecs(configurer -> {
        CustomDecoder decoder = new CustomDecoder();
        configurer.customCodecs().registerWithDefaultConfig(decoder);
})
.build();
Kotlin
val webClient = WebClient.builder()
.codecs({ configurer ->
        val decoder = CustomDecoder()
        configurer.customCodecs().registerWithDefaultConfig(decoder)
 })
.build()
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION