Flux asosida katta hajmdagi so'rovlarni optimallashtirish

Flux asosida katta hajmdagi so'rovlarni optimallashtirish

1. Nima uchun Flux?

Mavjud biznes mantiqi ketma-ket aylanish asosida ishlardi. Ma'lumotlar ro'yxatini birma-bir aylanib, tashqi API yoki DB ga murojaat qilib, har bir natijani to'plab, keyingi mantiqni bajaradigan juda an'anaviy tuzilma edi.

Dastlab, ma'lumotlar miqdori unchalik ko'p emas edi, shuning uchun katta muammolar yuzaga kelmadi. Ammo xizmat skalasi oshgani sayin, qayta ishlanishi kerak bo'lgan variantlar va qarash ob'ektlarining ko'payishi bilan samaradorlik pasayishi jiddiy ravishda boshlanmoqda.

Xususan, tashqi xizmatlar yoki DB ga bo'lgan bog'liqligi yuqori tuzilmalarda tarmoq I/O kutish vaqti to'planishi natijasida umumiy javob vaqti keskin oshdi.

Masalan, o'rtacha javob vaqti 200ms bo'lgan API ni 100 marta ketma-ket chaqirsak, oddiy hisoblashlar bilan 20 soniyadan ortiq vaqt sarflangan bo'lishi mumkin. Muammo shundaki, CPU resurslari etarlicha qolganiga qaramay, ko'p vaqt I/O kutish holatida sarflanmoqda.

Ya'ni, tizim resurslarini to'g'ri ishlata olmagan samarali bo'lmagan tuzilma edi.

Mavjud usul quyidagi xususiyatlarga ega edi.

Birinchidan, oldingi so'rov tugamog'i kerak edi, shundan keyingisi boshlanishi mumkin edi.

Ikkinchisi, tarmoq javob kutish vaqti to‘liq javob vaqtiga qo‘shildi.

Uchinchisi, ma’lumotlar soni oshgani sari javob vaqti chiziqli ravishda oshdi.

To'rtinchisi, tashqi API kechikishi bo'lsa, butun xizmat javob vaqti ham sekinlashdi.

Xususan, katta miqdordagi variant ma'lumotlarini ko'rish muhitlarida bunday muammolar yanada jiddiy ko'rinishda oshkor bo'ldi. Haqiqiy ish muhitida ma'lum vaqt oralig'ida yuzlab so'rovlar bir vaqtning o'zida sodir bo'ldi, bu jarayonda javob kechikishi va vaqt tugash muammolari takrorlanib turdi.

Buni hal qilish uchun birinchi navbatda parallel işlashni hisobga oldik.

Agar mustaqil koʻrish faoliyati boʻlsa, tartibda ishlash zarur emas edi.

Xususan, ko'p ishlov berish CPU hisoblashdan ko'ra tarmoq I/O kutishiga asoslangan bo'lganligi sababli, faqat parallel hisoblashni to'g'ri qo'llash orqali katta samaradorlik yaxshilanishini umid qilgan edik. Ushbu jarayonda tanlangan texnologiya Reactor asosidagi Flux edi. Flux oddiy kolleksiyalarni takrorlash vositasi emas, balki ma'lumotlarni oqim shaklida qayta ishlashga imkon beruvchi, parallel hisoblash va asinxron bajarishni tabiatda birlashtira oladigan Reactive Stream asosidagi kutubxona.

Xususan, quyidagi sabablar tufayli Fluxni tanladik.

Birinchidan, katta hajmdagi ma'lumotlarni oqim shaklida barqaror qayta ishlash mumkin bo'ldi.

Ikkinchidan, parallel yuklarni (parallel rail) foydalanib, parallel ishlov berishni osonlik bilan tashkil qilish mumkin bo'ldi.

Uchinchisi, Scheduler asosida thread resurslarini aniq boshqarish imkonini berdi.

To'rtinchisi, Backpressure asosida tuzilma orqali nazoratsiz thread ko'payishini oldini olish imkonini berdi.

Beshinchi, mavjud Java va Spring asosidagi tizimlar bilan tabiiy ravishda integratsiya qilish imkoniyatiga ega bo'lganmiz. Eng muhim jihati, “umumiy qayta ishlash vaqtini eng uzoq davom etadigan bitta so‘rov darajasigacha qisqartirish imkoniyati” edi.

Mavjud ketma-ket qayta ishlash usulida agar n ta so‘rov bo‘lsa, umumiy bajarilish vaqti quyidagi kabi tuzilgan edi.

Mavjud usul :

n × o'rtacha javob vaqti

Biroq parallel qayta ishlash tuzilmasida quyidagi ko'rinishda yaxshilanish kuzatilgan.

Yaxshilash usuli:

MAX(javob vaqt) + α(tafovut yuklama)

Ya'ni, agar parallel ishlash soni etarlicha ta'minlansa, umumiy javob vaqti eng uzoq davom etadigan bitta vazifa vaqti darajasiga yaqinlashadi.

2. Tatbiq jarayoni va amalga oshirish strategiyasi

Amalda tatbiq jarayoni faqatgina asinxron chaqiruvlarni qo'llash bilan hal qilinadigan muammo emas edi. Ishlayotgan muhitda nafaqat samaradorlik, balki barqarorlik, ma'lumotlar to'g'riligi va ip resurslarini boshqarish ham birga e'tiborga olinishi kerak edi.

Xususan, eng muhim bo'lgan qism “paralel ishlovdan keyin natijalarni yana sinkron ravishda qaytarish kerak” degan cheklov edi. Haqiqiy biznes mantiqida barcha so'rov natijalari to'planmaguncha keyingi bosqichdagi hisob-kitob va keyingi ishlov berish mantiqi amalga oshirilishi mumkin emasdi.

Ya'ni, so'rovning o'zi paralel ishlov berilishi kerak, ammo yakuniy natijalar mutlaqo sinkron ravishda birlashtirilishi lozim edi.

(1) Flux asosidagi oqimni tashkil etish

Avvalam bor, so‘rov target ma'lumotlarini Flux.fromIterable() orqali oqim shakliga o‘zgartirdik. Keyin .parallel(size) dan foydalanib, parallel railni tashkil etdik.

Bu yerda o'lchov qiymati faqat CPU yadro soniga asoslangan emas. Tashqi API javob vaqti, DB yuklanishi, tarmoq kechikishi, server xotira holati kabi omillarni ham hisobga olib, paralel ishlov berish sonini sozladik.

Paralel soni haddan tashqari oshirilsa, aksincha, tashqi xizmatlarga ortiqcha yuk keltirib chiqarishi mumkin. Shuning uchun ishqor muhitida quyidagi mezonlarni ham hisobga oldik.

• Tashqi API stavkasi cheklovi

• DB ulanish havzasi hajmi

• O'rtacha javob vaqt

• Server xotira ishlatilishi

• CPU foydalanish darajasi

• Tarmoq kechikish holati

(2) Scheduler optimallashtirish

Parallel ishlov berishda yana bir muhim omil iplarni boshqarish edi.

Dastlabki holatda oddiy parallel() dan foydalandim, lekin haqiqiy ish muhitida iplar boshqarish strategiyasi juda muhim ekanligini aniqladim.

Xususan, tarmoq I/O ga asoslangan ishlar uchun blocking xavfi mavjudligi sababli, odatiy CPU hisoblashga mo'ljallangan iplar to'plamidan foydalanish maqbul emas edi. Buni hal qilish uchun Schedulers.boundedElastic() dan foydalandim. boundedElastic - bu Reactor tomonidan taqdim etilgan elastik iplar to'plamidir. Zarurat tug'ilganda iplarni kengaytiradi, lekin cheksiz o'sishni oldini olish uchun cheklovlar qo'yilgan.

Ya'ni, tizim barqarorligini saqlab qolgan holda I/O kutish markazidagi ishlar uchun mos struktura taqdim etildi.

Xususan, quyidagi afzalliklar mavjud edi.

Birinchidan, zarur bo'lganda iplarni egiluvchan ravishda kengaytirish mumkin edi.

Ikkinchidan, bo'sh iplar avtomatik ravishda tozalanadi.

Uchinchisi, cheksiz ip yaratish orqali OOM xavfini kamaytira oldik.

To'rtinchisi, Blocking I/O muhitida ham barqaror ishladi.

Amaliyot muhitida oddiy ishlashdan ko'ra “barqaror resurslardan foydalanish” juda muhim edi. boundedElastic bunday operatsion barqarorlik nuqtai nazaridan juda mos keladigan tanlov edi.

(3) CountDownLatch asosidagi sinxronlash

Eng asosiy muammo asinkron va sinxronni qanday birlashtirish edi. Asinkron qayta ishlash orqali so'rov tezligini sezilarli darajada yaxshilash mumkin bo'ldi, lekin oxir-oqibat barcha so'rov natijalari to'planishi kerak edi, shunda keyingi biznes lojiqasi bajarilishi mumkin edi.

Ya'ni, so'rov jarayoni asinkron, lekin oxirgi oqimni sinxron ravishda boshqarish kerak bo'lgan tuzilma edi. Buni hal qilish uchun CountDownLatch dan foydalandim. Har bir ip parallel ravishda API ni chaqiradi va natijani responseBodyList ga saqlaydi.

Va ishlar tugagach, countDown() chaqirildi. Asosiy oqimda esa, await() yordamida barcha ishlar tugagunga qadar kutishni tartibga solganmiz.

Tuzilish quydagi kabi.

• Asinxron: Har bir ipda API'ni parallel ravishda chaqirib, natijalarni responseBodyList ga saqlaydi

• Sinxron: CountDownLatch.await() orqali barcha iplarning tugashini kutish uchun asosiy oqim kutmoqda

Ushbu usulning eng katta afzalligi shundaki, mavjud biznes mantiq tuzilishini sezilarli darajada o'zgartirmasdan, parallel ishlov berishni xavfsiz ravishda kiritish mumkin edi.

Ya'ni, mavjud sinxron asosidagi biznes tuzilishini saqlab qolgan holda, ichki tekshirish mantiqini paralel qilish imkonimiz bo'ldi.

3. Muammo hal qiling va ish faoliyatini yaxshilash natijalari

Flux asosida parallel qayta ishlash tuzilmasini qo'llaganidan so'ng, ish faoliyati juda katta darajada yaxshilandi. An'anaviy ketma-ket qayta ishlash usulida ma'lumotlar soni ko'paygani sayin, javob vaqti chiziqli ravishda oshdi.

Masalan, o'rtacha javob vaqti 300ms bo'lgan vazifalarni 100 marta bajarish orqali umumiy javob vaqti taxminan 30 soniyagacha oshishi mumkin edi.

Ammo parallel qayta ishlash tuzilmasi sababli, aksariyat so'rovlar bir vaqtda bajarilgani uchun umumiy javob vaqti eng uzoq davom etadigan yagona so'rov vaqti darajasiga yaqinlashdi. Haqiqiy ish muhiti shunday yaxshilanish natijalari ko'rinishi mumkin.

• Mavjud usul:

n × o'rtacha javob vaqti

• Takomot usuli :

MAX(ay individual javob vaqti) + α(rejalashtirish va qo'shish xarajatlari)

ayniqsa tarmoq kechikishi yuz beradigan muhitda parallel ishlash samarasi juda katta bo'lib ko'rindi. Avvalgi usullarda ma'lum bir API javobi sekinlashsa, butun jarayon sekinlashardi.

Boshqa tomondan, parallel ishlash qurilmasida ba'zi so'rovlar sekin bo'lsa ham, boshqa so'rovlar bir vaqtda qayta ishlanishi mumkin edi, shuning uchun umumiy hissiy ishlash juda oshdi.

Shuningdek, CPU foydalanish darajasi jihatidan ham ancha samarali natijalarga erishildi. Avvaliga vaqtning aksariyati I/O kutish bilan o'tkazilardi, lekin parallel qayta ishlashdan keyin bo'sh vaqt sezilarli darajada kamaydi.

Ishlash nuqtai nazaridan ham ijobiy o'zgarishlar bo'ldi.

Birinchidan, ommaviy imkoniyatlarni ko'rib chiqishda vaqt o'tishi tez-tez yuz berishi kamaydi.

Ikkinchidan, pik soatlar vaqtida javob barqarorligi yaxshilandi.

Uchinchisi, tashqi API kechikish holatlarida butun xizmat uzilishiga olib keluvchi foiz kamaydi.

To'rtinchisi, parallel ishlov berish sonini muhitga qarab o'zgartirish imkoniyati mavjud bo'lib, bu operatsion moslashuvchanlikni oshirdi.

Maxsus ravishda parallel raqamlarni boshqarish orqali samaradorlik va barqarorlikni osonlik bilan muvozanatlash mumkinligi juda foydali bo'ldi.

4. Xulosa

Ushbu optimizatsiya tajribasi orqali faqatgina eng so'nggi texnologiyalardan foydalanishdan ko'ra muhimroq narsa - bu “biznes cheklovlariga mos keladigan eng yaxshi vositalar kombinatsiyasini” topish kerakligini yana bir bor his qildim.

Ammo haqiqiy ish sharoitida nafaqat samaradorlik, balki barqarorlik, ma'lumotlarning to'g'riligi va operatsion texnik xizmat ko'rsatishni ham birga hisobga olish kerak edi.

Xususan, barcha ishlarni majburiy ravishda to'liq asinxron tuzilishga o'zgartirish har doim to'g'ri javob emasligini ham o'rgandik.

Amaliy loyihada keyingi bosqich mantiqiy bajarilishi uchun barcha natijalar albatta kerak bo'lganligi sababli, asinxron qayta ishlov berishdan so'ng sinkron natijalarni yig'ish albatta zarur bo'ldi.

Bu jarayonda CountDownLatch kabi sinxronizatsiya vositalarini birgalikda ishlatadigan aralash model juda samarali yechim bo'lishi mumkinligini tasdiqladik.

Shuningdek, Fluxni faqat «eng so'nggi texnologiya» nuqtai nazaridan emas, balki keng hajmdagi I/O ishlarini qayta ishlash muhitiga mos keladigan bajarish modeli sifatida ko'rib chiqgani ham juda muhim tajriba bo'ldi.

Nihoyat, muhim narsa ma'lum bir texnologiyaning o'zi emas, balki hozirgi tizim tuzilishi va ish sharoitiga eng mos usulni tanlash deb o'ylayman.

Bu tajriba oddiy ish faoliyatini oshirishdan ham ko'ra ko'proq ahamiyatga ega edi. Ish sharoitidagi barqarorlik va texnik xizmat ko'rsatishni birgalikda hisobga olgan amaliy optimizatsiya tajribasi deb o'ylayman.

Jack

Site footer