Circuit-breakers
ஒன்று அல்லது மற்றொன்று பதிலளிக்காத சேவைக்கு அதிக அளவு கோரிக்கைகள் செய்யப்படுவதைத் தவிர்க்க இப்போதெல்லாம் பயன்படுத்தப்படுகிறது. எடுத்துக்காட்டாக, ஒரு சேவை நிறுத்தப்படும் போது, எந்த காரணத்திற்காகவும், ஒரு சர்க்யூட்-பிரேக்கர், அதன் பெயர் குறிப்பிடுவது போல, சர்க்யூட்டை உடைக்க வேண்டும். வேறு வார்த்தைகளில் கூறுவதானால், குதிரைப் பந்தயத்தின் முடிவுகளைப் பெற ஒரே நேரத்தில் 1 மில்லியன் கோரிக்கைகள் செய்யப்படும் சூழ்நிலையில், இந்தக் கோரிக்கைகள் இதை கையாளக்கூடிய மற்றொரு சேவைக்கு திருப்பி விடப்பட வேண்டும் என்று நாங்கள் விரும்புகிறோம்.
இந்த பிற சேவை அதன் பிரதியாக இருக்கலாம் அல்லது அசல் சேவை தோல்வி தொடர்பான பிற செயல்பாடுகளைச் செய்ய இது முற்றிலும் பயன்படுத்தப்படலாம். இறுதி இலக்கு எப்போதும் தேவையற்ற அழைப்புகளை உடைத்து வேறு எங்காவது ஓட்டத்தை நடத்துவதாகும். 2017
இல், Michael Nygard
சர்க்யூட் பிரேக்கர் வடிவமைப்பு வடிவத்தை மென்பொருள் மேம்பாட்டு வடிவமைப்பில் முன்னணியில் கொண்டு வந்தார். இது அவரது வெளியீட்டில் செய்யப்பட்டது!
circuit breaker
வடிவமைப்பு முறை உண்மையான மின்னணு மற்றும் மின்சுற்றுகளால் ஈர்க்கப்பட்டுள்ளது. இருப்பினும், ஒரு பொதுவான கருத்தின் அடிப்படையில், சர்க்யூட்-பிரேக்கர் யோசனை உண்மையில் 1879
இல் Thomas Edison
கண்டுபிடிக்கப்பட்டது. அந்தக் காலத்தைப் போலவே, நிரம்பி வழியும் மின்னோட்டத்தைக் கையாள வேண்டும். மிக மிக எளிமையான சொற்களில், இந்த விஷயத்தில் மென்பொருள் கட்டமைப்பிற்கு இதைத்தான் நாங்கள் பயன்படுத்துகிறோம். கணினி போதுமான மீள்தன்மை உள்ளதா என்பதை உறுதிப்படுத்துவதே முக்கிய குறிக்கோள். இது எவ்வளவு மீள்தன்மையுடன் இருக்க வேண்டும் மற்றும் எவ்வளவு fault-tolerant
வேண்டும் என்பது உண்மையில் இந்த முறையைச் செயல்படுத்துவதற்குப் பொறுப்பான பொறியாளர்களின் பார்வையில் உள்ளது. அதன் பின்னணியில் உள்ள யோசனை என்னவென்றால், சில நிபந்தனைகளின் கீழ், ஒரு குறிப்பிட்ட கோரிக்கையின் ஓட்டத்தை அதே endpoint
பின்னால் உள்ள மற்றொரு கிடைக்கக்கூடிய ஓட்டத்திற்கு தடையின்றி திருப்பிவிட விரும்பலாம்.
A
முதல் B
வரையிலான கோரிக்கையை நிறைவேற்ற விரும்புகிறோம் என்று வைத்துக் கொள்வோம். அவ்வப்போது, B தோல்வியடையும் மற்றும் C
எப்போதும் கிடைக்கும். B
சீரற்ற முறையில் தோல்வியுற்றால், எங்கள் சேவையை முழுமையாகக் கிடைக்கச் செய்ய C
அடைய விரும்புகிறோம். இருப்பினும், B
க்கு கோரிக்கைகளை மீண்டும் செய்ய, B
மீண்டும் தோல்வியடையாமல் இருப்பதை உறுதிசெய்ய விரும்புகிறோம். B க்கு சீரற்ற கோரிக்கைகளைச் செய்ய நமது கணினியை உள்ளமைக்கலாம் மற்றும் தோல்வியின் விகிதம் ஒரு குறிப்பிட்ட நிலைக்குச் சென்றவுடன் மட்டுமே B
க்கு முழுமையாக திரும்ப முடியும்.
பிழையின் போதும் தாமதத்தின் போதும் C கோரிக்கையை நாங்கள் செய்ய விரும்பலாம். B
மிகவும் மெதுவாக இருந்தால், எல்லா கோரிக்கைகளையும் C
க்கு மீண்டும் அனுப்ப விரும்பலாம். வரையறுக்கப்பட்ட எண்ணிக்கையிலான முயற்சிகளுக்குப் பிறகு C
அடைய முயற்சிப்பது, கோரிக்கை வகைகள், ஒரே நேரத்தில் உள்ள நூல்கள் மற்றும் பல விருப்பங்கள் போன்ற பல சாத்தியமான உள்ளமைவுகள் உள்ளன, இது short-circuiting
என்றும் அழைக்கப்படுகிறது, மேலும் இது பெரும்பாலும் தற்காலிக நடவடிக்கையாகும்.
சர்க்யூட் பிரேக்கர் என்றால் என்ன என்பது பற்றிய நமது அறிவை மேலும் புரிந்து கொள்வதற்கு, ஒரு சர்க்யூட் பிரேக் என்பது நமது பயன்பாட்டில் ஒரு நிறுவனமாக செயல்படுகிறது என்பதை நாம் புரிந்து கொள்ள வேண்டும். சர்க்யூட் பிரேக்கருக்கு மூன்று முக்கிய நிலைகள் உள்ளன. இது மூடப்பட்டதாகவோ, திறந்ததாகவோ அல்லது பாதியாகவோ இருக்கலாம். மூடப்பட்ட நிலை என்றால், எங்கள் விண்ணப்ப ஓட்டங்கள் சாதாரணமாக இயங்குவதாகும். அனைத்து கோரிக்கைகளும் சேவை Bக்கு செல்லும் என்பதை அறிந்து, சேவை Aக்கான கோரிக்கைகளை நாங்கள் பாதுகாப்பாக செய்யலாம். திறந்த நிலை என்றால் சேவை Bக்கான அனைத்து கோரிக்கைகளும் தோல்வியடையும். தோல்வியைப் பிரதிநிதித்துவப்படுத்த நாங்கள் வரையறுத்துள்ள விதிகள் நிகழ்ந்துவிட்டன, இனி நாங்கள் சேவை B ஐ அடைய மாட்டோம். இந்த விஷயத்தில், விதிவிலக்கு எப்போதும் வழங்கப்படும். half-open
நிலை என்பது எங்கள் சர்க்யூட்-பிரேக்கர் மீண்டும் செயல்படுகிறதா என்பதைப் பார்க்க, சேவை B இல் சோதனைகளைச் செய்யுமாறு அறிவுறுத்தப்படும்.
ஒவ்வொரு வெற்றிகரமான கோரிக்கையும் சாதாரணமாக கையாளப்படும், ஆனால் அது C க்கு தொடர்ந்து கோரிக்கைகளை வைக்கும். நாங்கள் அமைத்துள்ள சரிபார்ப்பு விதிகளின்படி B எதிர்பார்த்தபடி நடந்துகொண்டால், எங்கள் சர்க்யூட் பிரேக்கர் ஒரு மூடிய நிலைக்குத் திரும்பும், சேவை A உருவாக்கத் தொடங்கும் பிரத்தியேகமாக சேவைக்கான கோரிக்கைகள் B. பெரும்பாலான பயன்பாடுகளில், ஒரு சர்க்யூட்-பிரேக்கர் டெக்கரேட்டர் வடிவமைப்பு முறையைப் பின்பற்றுகிறது. எவ்வாறாயினும், இது கைமுறையாக செயல்படுத்தப்படலாம், மேலும் சர்க்யூட்-பிரேக்கர்களை செயல்படுத்துவதற்கான மூன்று நிரல் வழிகளைப் பார்ப்போம் மற்றும் இறுதியாக AOP- அடிப்படையிலான செயல்படுத்தலைப் பயன்படுத்துவோம். குறியீடு GitHub இல் கிடைக்கிறது.
இந்த கட்டுரையின் கடைசி கட்டத்தில், கார் ரேஸ் விளையாட்டைப் பற்றி பார்ப்போம். இருப்பினும், நாங்கள் அங்கு செல்வதற்கு முன், circuit breaker
இயங்கும் பயன்பாட்டை உருவாக்குவதற்கான சில அம்சங்களை உங்களுக்கு வழிகாட்ட விரும்புகிறேன்.
Kystrixs
, ஒரு சிறிய DSL
ஆக, Johan Haleby
கண்டுபிடித்து உருவாக்கப்பட்ட ஒரு அற்புதமான நூலகம் ஆகும். ஸ்பிரிங் மற்றும் ஸ்பிரிங் வெப்ஃப்ளக்ஸ் உடன் ஒருங்கிணைப்பு உள்ளிட்ட பல சாத்தியக்கூறுகளை நூலகம் வழங்குகிறது. அதைப் பார்த்துவிட்டு கொஞ்சம் விளையாடுவது சுவாரஸ்யமானது:
<dependency> <groupId>se.haleby.kystrix</groupId> <artifactId>kystrix-core</artifactId> </dependency> <dependency> <groupId>se.haleby.kystrix</groupId> <artifactId>kystrix-spring</artifactId> </dependency>
நான் ஒரு உதாரணத்தை உருவாக்கியுள்ளேன், இது GitHub இல் உள்ள தொகுதியிலிருந்து- paris-to-berlin-kystrix-runnable-app இல் அமைந்துள்ளது. முதலில், குறியீட்டைப் பார்ப்போம்:
@GetMapping("/{id}") private fun getCars(@PathVariable id: Int): Mono<Car> { return if (id == 1) Mono.just(Car("Jaguar")) else { hystrixObservableCommand<Car> { groupKey("Test2") commandKey("Test-Command2") monoCommand { webClient.get().uri("/cars/carros/1").retrieve().bodyToMono<Car>() .delayElement(Duration.ofSeconds(1)) } commandProperties { withRequestLogEnabled(true) withExecutionTimeoutInMilliseconds(5000) withExecutionTimeoutEnabled(true) withFallbackEnabled(true) withCircuitBreakerEnabled(false) withCircuitBreakerForceClosed(true) } fallback { Observable.just(Car("Tank1")) } }.toMono() } }
இந்த குறியீடு உதாரணத்தின் கட்டளை 2 ஐக் குறிக்கிறது. கட்டளைக்கான குறியீட்டை சரிபார்க்கவும் 1. இங்கே என்ன நடக்கிறது என்றால், நாம் விரும்பும் கட்டளையை monoCommand
மூலம் வரையறுக்கிறோம். இங்கே, நாம் அழைக்க வேண்டிய முறையை வரையறுக்கிறோம். commandProperties
இல், circuit-breaker
மாற்ற நிலையை திறக்கும் விதிகளை நாங்கள் வரையறுக்கிறோம். துல்லியமாக 1 வினாடி நீடிக்கும் வகையில் எங்கள் அழைப்பை வெளிப்படையாக தாமதப்படுத்துகிறோம்.
அதே நேரத்தில், 5000
மில்லி விநாடிகளின் காலக்கெடுவை நாங்கள் வரையறுக்கிறோம். இதன் பொருள் நாம் ஒருபோதும் காலக்கெடுவை அடைய மாட்டோம். இந்த எடுத்துக்காட்டில், Id
மூலம் நாம் அழைப்புகளைச் செய்யலாம். இது ஒரு சோதனை மட்டுமே என்பதால், Id=1
, காரின் Id
, circuit-breaker
தேவையில்லாத ஜாகுவார் என்று கருதுகிறோம். ஃபால்பேக் முறையில் வரையறுக்கப்பட்டுள்ளபடி நாம் ஒருபோதும் Tank1 ஐப் பெற மாட்டோம் என்பதும் இதன் பொருள். நீங்கள் இன்னும் கவனிக்கவில்லை என்றால், குறைப்பு முறையை கவனமாக பாருங்கள். இந்த முறை ஒரு Observable
பயன்படுத்துகிறது. WebFlux
Observable
வடிவமைப்பு முறையின்படி செயல்படுத்தப்பட்டாலும், Flux
சரியாக கவனிக்கத்தக்கது அல்ல.
இருப்பினும், ஹிஸ்ட்ரிக்ஸ் இரண்டையும் ஆதரிக்கிறது. இதை உறுதிப்படுத்த, பயன்பாட்டை இயக்கவும், http://localhost:8080/cars/2 இல் உங்கள் உலாவியைத் திறக்கவும். ஸ்பிரிங் பூட்டின் தொடக்கத்தில் நீங்கள் அழைப்புகளைச் செய்யத் தொடங்கினால், இறுதியில் நீங்கள் ஒரு Tank1 செய்தியைப் பெறலாம் என்பதைப் புரிந்துகொள்வது அவசியம். ஏனென்றால், இந்த செயல்முறையை நீங்கள் எவ்வாறு இயக்குகிறீர்கள் என்பதைப் பொறுத்து தொடக்கத் தாமதமானது 5 வினாடிகளை மிக எளிதாகத் தாண்டும். இரண்டாவது எடுத்துக்காட்டில், டேங்க் 2 க்கு எங்கள் உதாரணத்தை ஷார்ட் சர்க்யூட் செய்யப் போகிறோம்:
@GetMapping("/timeout/{id}") private fun getCarsTimeout(@PathVariable id: Int): Mono<Car> { return if (id == 1) Mono.just(Car("Jaguar")) else { hystrixObservableCommand<Car> { groupKey("Test3") commandKey("Test-Command3") monoCommand { webClient.get().uri("/cars/carros/1").retrieve().bodyToMono<Car>() .delayElement(Duration.ofSeconds(1)) } commandProperties { withRequestLogEnabled(true) withExecutionIsolationThreadInterruptOnTimeout(true) withExecutionTimeoutInMilliseconds(500) withExecutionTimeoutEnabled(true) withFallbackEnabled(true) withCircuitBreakerEnabled(false) withCircuitBreakerForceClosed(true) } fallback { Observable.just(Car("Tank2")) } }.toMono() } }
இந்த எடுத்துக்காட்டில், எங்கள் circuit-breaker
ஒரு திறந்த நிலை திரும்பும் டேங்க் 2 க்கு பதிலளிக்கும். ஏனென்றால், நாங்கள் இங்கே 1 வி தாமதத்தை ஏற்படுத்துகிறோம், ஆனால் எங்கள் சர்க்யூட் பிரேக் நிலை 500எம்எஸ் குறிக்குப் பிறகு தூண்டுகிறது என்பதைக் குறிப்பிடுகிறோம். hystrix
எவ்வாறு செயல்படுகிறது என்பதை நீங்கள் அறிந்திருந்தால், kystrix
முன்னோக்கி நகர்வது வேறுபட்டதல்ல என்பதை நீங்கள் காண்பீர்கள். இந்த கட்டத்தில் ஹிஸ்ட்ரிக்ஸ் எனக்கு வழங்காதது, விளையாட்டை உருவாக்க எனக்கு தேவையானதை வழங்குவதற்கான தடையற்ற, சிரமமில்லாத வழியாகும். Kystrix
வாடிக்கையாளர் அடிப்படையில் செயல்படுவதாகத் தெரிகிறது. இதன் பொருள், எங்கள் முக்கிய சேவையின் பின்னால் உள்ள சேவைகளுக்கு கோரிக்கைகளை முன்வைக்கும் முன், எங்கள் குறியீட்டை அறிவிக்க வேண்டும்.
Resilience4J
சர்க்யூட்-பிரேக்கரின் முழுமையான செயலாக்கமாக பலரால் குறிப்பிடப்படுகிறது. எனது முதல் சோதனைகள் சர்க்யூட்-பிரேக்கர்களின் சில முக்கிய அம்சங்களை ஆராய்வது பற்றியது. அதாவது, காலக்கெடு மற்றும் வெற்றிகரமான கோரிக்கைகளின் அதிர்வெண் ஆகியவற்றின் அடிப்படையில் செயல்படக்கூடிய சர்க்யூட் பிரேக்கரைப் பார்க்க விரும்பினேன். பல்வேறு வகையான short-circuiting
மாட்யூல்களை உள்ளமைக்க Resilience4J
அனுமதிக்கிறது. இவை 6
வெவ்வேறு வகைகளாகப் பிரிக்கப்பட்டுள்ளன: CircuitBreaker
, Bulkhead
, Ratelimiter
, Retry
, மற்றும் Timelimiter
. இவை அனைத்தும் வடிவமைப்பு வடிவங்களின் பெயர்கள். CircuitBreaker
தொகுதி இந்த மாதிரியின் முழுமையான செயலாக்கத்தை வழங்குகிறது.
எங்களிடம் உள்ளமைக்கக்கூடிய அளவுருக்கள் நிறைய உள்ளன, ஆனால் முக்கியமாக, CircuitBreaker
தொகுதியானது, தோல்வியென அடையாளம் காணக்கூடியவற்றை உள்ளமைக்க அனுமதிக்கிறது, அரை-திறந்த நிலையில் மற்றும் நெகிழ் சாளரத்தில் எத்தனை கோரிக்கைகளை அனுமதிக்கிறோம், நேரம் அல்லது எண்ணிக்கை, கோரிக்கைகளின் எண்ணிக்கையை மூடிய நிலையில் வைத்திருக்கிறோம். பிழையின் அதிர்வெண்ணைக் கணக்கிட இது முக்கியம். முக்கியமாக, இந்த CircuitBreaker
தொகுதி கோரிக்கைகளின் விகிதத்தில் எங்களுக்கு உதவும் என்று கூறலாம், ஆனால் அது உண்மையாக இருக்க வேண்டிய அவசியமில்லை.
நீங்கள் அதை எவ்வாறு விளக்குகிறீர்கள் என்பதைப் பொறுத்தது. தவறுகளைச் சமாளிப்பதற்கான ஒரு வழி என்று நினைப்பது ஒரு சிறந்த வழியாகத் தெரிகிறது. அவை காலக்கெடு அல்லது விதிவிலக்கிலிருந்து வந்தாலும், இங்குதான் அவை Bulkhead
, மேலும் கோரிக்கைகளை வேறு எங்காவது தடையின்றி திருப்பிவிடலாம். இது ஒரு விகித வரம்பு அல்ல.
அதற்கு பதிலாக, இது Bulkhead
வடிவமைப்பு வடிவத்தை செயல்படுத்துகிறது, இது ஒரு ஒற்றை இறுதிப்புள்ளியில் அதிக செயலாக்கத்தைத் தடுக்கப் பயன்படுகிறது. இந்தச் சந்தர்ப்பத்தில், Bulkhead
எங்களின் கோரிக்கைகளை, கிடைக்கக்கூடிய அனைத்து இறுதிப்புள்ளிகளிலும் விநியோகிக்கப்படும் வகையில் செயல்படுத்த அனுமதிக்கிறது. Bulkhead
என்ற பெயர் பல்வேறு சீல் செய்யப்பட்ட பெட்டிகளில் இருந்து வந்தது, ஒரு பெரிய கப்பல் மூழ்காமல் இருக்க வேண்டும், விபத்து ஏற்பட்டால், மற்றும் கப்பல்களைப் போலவே, நூல் குளத்தில் எத்தனை நூல்கள் கிடைக்கும் மற்றும் அவற்றின் குத்தகை நேரம் ஆகியவற்றை நாம் வரையறுக்க வேண்டும். .
RateLimiter
தொகுதி கோரிக்கைகளின் விகிதத்தைக் கையாள வடிவமைக்கப்பட்டுள்ளது. இதற்கும் Bulkhead
தொகுதிக்கும் இடையே உள்ள வேறுபாடு இன்றியமையாதது, ஒரு குறிப்பிட்ட புள்ளி வரையிலான கட்டணங்களை நாம் பொறுத்துக்கொள்ள விரும்புகிறோம். அதற்காக நாம் தோல்வியை ஏற்படுத்த வேண்டிய அவசியமில்லை என்பதே இதன் பொருள். வடிவமைப்பில் ஒரு குறிப்பிட்ட மதிப்புக்கு மேலான விகிதத்தை நாங்கள் பொறுத்துக்கொள்ள மாட்டோம் என்று கூறுகிறோம். கூடுதலாக, கோரிக்கையை நாங்கள் திருப்பிவிடலாம் அல்லது கோரிக்கையைச் செயல்படுத்த அனுமதி வழங்கப்படும் வரை அதை நிறுத்தி வைக்கலாம். Retry
தொகுதியானது மற்ற தொகுதிக்கூறுகளுடன் பொதுவானதாக இல்லாததால், புரிந்துகொள்வது மிகவும் எளிதானது.
எங்களின் வரையறுக்கப்பட்ட வரம்பை அடையும் வரை, ஒரு குறிப்பிட்ட இறுதிப் புள்ளியில் மீண்டும் முயற்சிகளின் எண்ணிக்கையை வெளிப்படையாக அறிவிக்கிறோம். Timelimiter
தொகுதியானது CircuitBreaker
தொகுதியின் எளிமைப்படுத்தலாகக் காணப்படலாம், அதில் அவை இரண்டும் காலக்கெடுவை உள்ளமைப்பதற்கான வாய்ப்பைப் பகிர்ந்து கொள்கின்றன. இருப்பினும், Timelimiter
ஸ்லைடிங் விண்டோக்கள் போன்ற பிற அளவுருக்களைச் சார்ந்து இல்லை, மேலும் இது இன்-பில்ட் தோல்வி த்ரெஷோல்ட் கணக்கீட்டையும் கொண்டிருக்கவில்லை.
எனவே, ஒரு குறிப்பிட்ட சேவையை அழைக்கும் போது காலக்கெடுவைக் கையாள்வதில் நாங்கள் முற்றிலும் ஆர்வமாக இருந்தால், மற்றும் பிற சாத்தியமான தவறுகளுக்கு நாங்கள் காரணியாக இருக்கவில்லை என்றால், நாம் Timelimiter
உடன் சிறப்பாக செயல்படலாம்.
இந்த தொகுதியில், நான் resilience4j
kotlin நூலகத்தைப் பயன்படுத்த முடிவு செய்துள்ளேன்:
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-kotlin</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-retry</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-circuitbreaker</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-ratelimiter</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-timelimiter</artifactId> </dependency>
இந்தச் செயலாக்கம் GitHub இல் ரெப்போவில் கிடைக்கிறது. முதலில் TimeLimiter
வடிவத்தைப் பார்ப்போம்:
var timeLimiterConfig: TimeLimiterConfig = TimeLimiterConfig.custom() .timeoutDuration(Duration.ofMillis(100)) .build() var timeLimiter: TimeLimiter = TimeLimiter.of("backendName", timeLimiterConfig) private suspend fun getPublicCar(): Car { return timeLimiter.decorateSuspendFunction { getPrivateCar() }.let { suspendFunction -> try { suspendFunction() } catch (exception: Exception) { Car("Opel Corsa") } } } private suspend fun getPrivateCar(): Car { delay(10000) return Car("Lancya") }
இந்தச் சந்தர்ப்பத்தில், decorateSuspendFunction
செயல்பாட்டைப் பயன்படுத்தி, TimeLimiter
செயல்பாட்டின் மூலம் எங்கள் getPrivateCar
function
நாங்கள் அலங்கரிக்கிறோம். இது காலாவதியை ஏற்படுத்தும், நாம் அழைக்கும் செயல்பாடு அதிக நேரம் எடுத்தால், லான்சியாவிற்குப் பதிலாக ஓப்பல் கோர்சாவைப் பெறுவோம். இதை முயற்சிக்க, பயன்பாட்டை இயக்கி, http://localhost:8080/cars/timelimiter/normal/1 ஐ திறக்கலாம்.
செயல்படுத்துவதைப் பார்க்கும்போது, நாம் ஒருபோதும் Lancya
பெற முடியாது என்பதைக் காண்கிறோம். ஏனென்றால், நாங்கள் வேண்டுமென்றே 10s
காத்திருக்கிறோம், அதைத் திருப்பித் தருவோம். எங்கள் TimeLimiter
மிகக் குறைந்த காலக்கெடுவைக் கொண்டுள்ளது, எனவே இது ஒருபோதும் வேலை செய்யாது. ஒரு TimeLimiter
புரிந்து கொள்ள மிகவும் எளிமையானது. ஒரு CircuitBreaker
, மறுபுறம், வேறு கதையாக இருக்கலாம். இது எவ்வாறு செய்யப்படலாம் என்பதற்கான எடுத்துக்காட்டு:
val circuitBreakerConfig = CircuitBreakerConfig.custom() .failureRateThreshold(20f) .slowCallRateThreshold(50f) .slowCallDurationThreshold(Duration.ofMillis(1000)) .waitDurationInOpenState(Duration.ofMillis(1000)) .maxWaitDurationInHalfOpenState(Duration.ofMillis(1000)) .permittedNumberOfCallsInHalfOpenState(500) .minimumNumberOfCalls(2) .slidingWindowSize(2) .slidingWindowType(COUNT_BASED) .build() val circuitBreaker = CircuitBreakerRegistry.of(circuitBreakerConfig).circuitBreaker("TEST") private suspend fun getPublicCar(id: Long): Car { return circuitBreaker.decorateSuspendFunction { getPrivateCar(id) }.let { suspendFunction -> try { suspendFunction() } catch (exception: Exception) { Car("Opel Corsa") } } } private fun getPrivateCar(id: Long): Car { if (id == 2L) { throw RuntimeException() } return Car("Lancya") }
இந்த வழக்கில், சொத்துடன் தோல்வி விகிதம் 20%
க்கும் குறைவாக இருந்தால், எங்கள் சர்க்யூட் பிரேக்கர் சர்க்யூட்டை மூட வேண்டும் என்று நாங்கள் கூறுகிறோம். மெதுவான அழைப்புகளுக்கும் ஒரு வரம்பு இருக்கும், ஆனால் இந்த விஷயத்தில், இது 50% க்கும் குறைவாக இருக்கும். மெதுவான அழைப்பு 1 வினாடிக்கு மேல் நீடிக்க வேண்டும் என்று நாங்கள் கூறுகிறோம். அரை-திறந்த நிலையின் கால அளவு 1 வினாடியாக இருக்க வேண்டும் என்பதையும் நாங்கள் குறிப்பிடுகிறோம். இதன் பொருள், நடைமுறையில், நாம் திறந்த நிலை, அரை திறந்த நிலை அல்லது மூடிய நிலை ஆகியவற்றைக் கொண்டிருப்போம்.
நாங்கள் அதிகபட்சமாக 500 அரை-திறந்த நிலை கோரிக்கைகளை அனுமதிக்கிறோம் என்றும் கூறுகிறோம். பிழை கணக்கீடுகளுக்கு, சர்க்யூட் பிரேக்கர் அதை எந்த குறியில் செய்யும் என்பதை அறிந்து கொள்ள வேண்டும். சுற்று எப்போது மூட வேண்டும் என்பதை தீர்மானிக்க இது முக்கியம். இந்தக் கணக்கீட்டிற்கு குறைந்தபட்சம் 2 கோரிக்கைகள் தேவைப்படும், minimumNumberOfCalls
சொத்துடன். கோரிக்கைகள் ஒரு பாதுகாப்பான தோல்வி வரம்பை அடைந்தால், அரை-திறந்த நிலை என்பதை நினைவில் கொள்க?
இந்த உள்ளமைவில், பிழையின் அதிர்வெண்ணைக் கணக்கிட்டு, மூடிய நிலைக்குத் திரும்பலாமா வேண்டாமா என்பதைத் தீர்மானிக்க, நெகிழ் சாளரத்தில் குறைந்தபட்சம் 2
கோரிக்கைகளைச் செய்ய வேண்டும். நாம் கட்டமைத்த அனைத்து மாறிகளின் துல்லியமான வாசிப்பு இதுவாகும். பொதுவாக, இதன் பொருள் என்னவென்றால், மாற்றுச் சேவைக்கு எங்கள் பயன்பாடு பல அழைப்புகளைச் செய்யும், ஒன்று இருந்தால், அது திறந்த நிலையிலிருந்து மூடிய நிலைகளுக்கு மிக எளிதாக மாறாது, அதைச் செய்வதற்கான வெற்றி விகிதம் பாதியில் 80% ஆக இருக்க வேண்டும். திறந்த நிலைகள் மற்றும் திறந்த நிலைக்கான காலக்கெடு ஏற்பட்டிருக்க வேண்டும்.
அத்தகைய காலக்கெடுவைக் குறிப்பிட பல வழிகள் உள்ளன. எங்கள் எடுத்துக்காட்டில், maxDurationInHalfOpenState
1s என்று கூறுகிறோம். இதன் பொருள், எங்கள் காசோலை மூடப்பட்ட நிலையின் நிலையைப் பூர்த்தி செய்யவில்லை என்றாலோ அல்லது இந்த காலக்கெடு இன்னும் ஏற்படவில்லை என்றாலோ மட்டுமே, எங்கள் CircuitBreaker
நிலையைத் திறந்து வைத்திருக்கும். இந்த CircuitBreaker
வரையறுக்கப்பட்ட நடத்தையைப் பின்பற்றுவதும் கணிப்பதும் கடினமாக இருக்கலாம், ஏனெனில் குறிப்பிட்ட வேலையில்லா நேரங்கள், விகிதங்கள் மற்றும் கோரிக்கைகளின் பிற அம்சங்கள் சரியாகப் பிரதிபலிக்க முடியாது, ஆனால் இந்த முடிவுப் புள்ளியில் பல கோரிக்கைகளைச் செய்தால், அதைப் பார்ப்போம். மேலே விவரிக்கப்பட்ட நடத்தை எங்கள் அனுபவத்துடன் பொருந்துகிறது.
எனவே, முடிவுப் புள்ளிகளுக்கு பல கோரிக்கைகளை முயற்சிப்போம்: http://localhost:8080/cars/circuit/1 மற்றும் http://localhost:8080/cars/circuit/2 . 1 இல் முடிவது வெற்றிகரமான கார் மீட்டெடுப்பின் இறுதிப் புள்ளியாகும், மேலும் 2 இல் முடிவடைவது ஒரு குறிப்பிட்ட காரைப் பெறுவதில் தோல்வியின் இறுதிப் புள்ளியாகும். குறியீட்டைப் பார்க்கும்போது, 2-ஐத் தவிர வேறு எதுவும் Lancya
பதிலளிப்பதாகப் பெறுவதைக் காண்கிறோம். A 2
, என்றால் நாம் உடனடியாக இயக்க நேர விதிவிலக்கை எறிந்து விடுகிறோம், அதாவது Opel Corsa
ஒரு பதிலாகப் பெறுகிறோம்.
எண்ட்பாயிண்ட் 1
க்கு நாம் கோரிக்கை வைத்தால், Lancya
ஒரு பதிலாகப் பார்ப்போம். கணினி தோல்வியடையத் தொடங்கினால், நீங்கள் 2,\; சிறிது நேரத்திற்குப் பிறகு Lancya
திரும்புவது நிலையானதாக இருக்காது என்பதை நீங்கள் காண்பீர்கள். System
திறந்த நிலையில் இருப்பதாகவும் மேலும் கோரிக்கைகள் அனுமதிக்கப்படவில்லை என்றும் தெரிவிக்கும்.
2021-10-20 09:56:50.492 ERROR 34064 --- [ctor-http-nio-2] .fcbrrcCarControllerCircuitBreaker : io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'TEST' is OPEN and does not permit further calls
எங்கள் சர்க்யூட் பிரேக்கர் ஒரு வெற்றிகரமான கோரிக்கைக்குப் பிறகு அரை-திறந்த நிலைக்குச் செல்லும், மேலும் இது இயல்பாக்குவதற்கு முன்பு 1 க்கு சில கோரிக்கைகளை மீண்டும் செய்ய வேண்டும். Lancya
மீண்டும் பெறுவதற்கு முன், நாங்கள் இரண்டு முறை Lancya
Opel Corsa
மாறுவோம். இந்த எண்ணை 2 என்று வரையறுத்துள்ளோம். இது பிழைக் கணக்கீட்டிற்கான குறைந்தபட்ச அளவாகும். நாம் ஒரு தோல்வியை மட்டுமே ஏற்படுத்தி, தோல்வியடையாத இறுதிப்புள்ளியை தொடர்ந்து அழைத்தால், என்ன நடக்கிறது என்பது பற்றிய தெளிவான படத்தைப் பெறலாம்:
2021-10-20 11:53:29.058 ERROR 34090 --- [ctor-http-nio-4] .fcbrrcCarControllerCircuitBreaker : java.lang.RuntimeException 2021-10-20 11:53:41.102 ERROR 34090 --- [ctor-http-nio-4] .fcbrrcCarControllerCircuitBreaker : io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'TEST' is OPEN and does not permit further calls
இந்த ஓப்பன்-ஸ்டேட்டஸ் மெசேஜ், உண்மையாக இருந்தபோதிலும், தோல்வியடையாத எண்ட்பாயிண்டிற்கு 2 கோரிக்கைகளை நான் செய்த பிறகு நடந்தது. இதனால் தான் மாநிலம் பாதியிலேயே திறக்கப்பட்டுள்ளதாக கூறப்படுகிறது.
முந்தைய பிரிவில், எந்த ஸ்பிரிங் தொழில்நுட்பத்தையும் பயன்படுத்தாமல், மிகவும் நிரல் முறையில் செயல்படுத்துவது எப்படி என்று பார்த்தோம். WebFlux
MVC
வகை சேவையை வழங்க மட்டுமே ஸ்பிரிங் பயன்படுத்தினோம். மேலும், சேவைகளைப் பற்றி நாங்கள் எதையும் மாற்றவில்லை. பின்வரும் பயன்பாட்டில், பின்வரும் நூலகங்களை ஆராய்வோம்:
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-all</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-reactor</artifactId> </dependency>
குறியீடு எவ்வாறு செய்யப்படுகிறது என்பதைப் பார்க்கும்போது, ஒரு பெரிய வித்தியாசத்தைக் காணலாம்:
@RestController @RequestMapping("/cars") class CarController( private val carService: CarService, timeLimiterRegistry: TimeLimiterRegistry, circuitBreakerRegistry: CircuitBreakerRegistry, bulkheadRegistry: BulkheadRegistry ) { private var timeLimiter: TimeLimiter = timeLimiterRegistry.timeLimiter(CARS) private var circuitBreaker = circuitBreakerRegistry.circuitBreaker(CARS) private var bulkhead = bulkheadRegistry.bulkhead(CARS) @GetMapping("/{id}") private fun getCars(@PathVariable id: Int): Mono<Car> { return carService.getCar() .transform(TimeLimiterOperator.of(timeLimiter)) .transform(CircuitBreakerOperator.of(circuitBreaker)) .transform(BulkheadOperator.of(bulkhead)) .onErrorResume(TimeoutException::class.java, ::fallback) } @GetMapping("/test/{id}") private fun getCarsTest(@PathVariable id: Int): Mono<Car> { return carService.getCar() .transform(TimeLimiterOperator.of(timeLimiter)) .transform(CircuitBreakerOperator.of(circuitBreaker)) .transform(BulkheadOperator.of(bulkhead)) .onErrorResume(TimeoutException::class.java, ::fallback) } @GetMapping("/carros/{id}") private fun getCarros(@PathVariable id: Long): Mono<Car> { return Mono.just(Car("Laborghini")) } private fun fallback(ex: Throwable): Mono<Car> { return Mono.just(Car("Rolls Royce")) } }
இந்த எடுத்துக்காட்டில் மற்றும் பின்வருவனவற்றில், நாம் பெரும்பாலும் காலாவதியான பண்புகளைப் பார்க்கப் போகிறோம். இது ஒரு அறிமுகக் கட்டுரை என்பதால் CircuitBreaker
நுணுக்கங்கள் குறைவாகவே உள்ளன. Resilience4J
மூலம் ஸ்பிரிங்க்காக வழங்கப்படும் டெக்கரேட்டர்கள் மூலம் இதை எவ்வளவு எளிதாகச் செயல்படுத்த முடியும் என்பதை இங்கு உணர வேண்டியது முக்கியமானது. இன்னும் ஒரு programmatical
பாணியில் இருந்தாலும், நாம் விரும்பும் short-circuit
வகைகளுடன், carService.getCar()
இலிருந்து நாம் பெறும் ஆரம்ப வெளியீட்டாளரை எளிதாக அலங்கரிக்கலாம்.
இந்த எடுத்துக்காட்டில், நாங்கள் ஒரு TimeLiter
, ஒரு BulkHead
மற்றும் CircuitBreaker
பதிவு செய்கிறோம். இறுதியாக, ஒரு TimeoutException ஏற்பட்டவுடன் தூண்டப்படும் ஃபால்பேக் செயல்பாட்டை நாங்கள் வரையறுக்கிறோம். இவை அனைத்தும் எவ்வாறு கட்டமைக்கப்பட்டுள்ளன என்பதை நாம் இன்னும் பார்க்க வேண்டும். பிற உள்ளமைக்கக்கூடிய தொகுதிகளைப் போலவே வசந்த காலத்தில் Resilience4J ஐ உள்ளமைக்கிறோம். நாங்கள் application.yml
பயன்படுத்துகிறோம்:
resilience4j.circuitbreaker: configs: default: registerHealthIndicator: true slidingWindowSize: 10 minimumNumberOfCalls: 5 permittedNumberOfCallsInHalfOpenState: 3 automaticTransitionFromOpenToHalfOpenEnabled: true waitDurationInOpenState: 5s failureRateThreshold: 50 eventConsumerBufferSize: 10 recordExceptions: - org.springframework.web.client.HttpServerErrorException - java.util.concurrent.TimeoutException - java.io.IOException ignoreExceptions: # - io.github.robwin.exception.BusinessException shared: slidingWindowSize: 100 permittedNumberOfCallsInHalfOpenState: 30 waitDurationInOpenState: 1s failureRateThreshold: 50 eventConsumerBufferSize: 10 ignoreExceptions: # - io.github.robwin.exception.BusinessException instances: cars: baseConfig: default roads: registerHealthIndicator: true slidingWindowSize: 10 minimumNumberOfCalls: 10 permittedNumberOfCallsInHalfOpenState: 3 waitDurationInOpenState: 5s failureRateThreshold: 50 eventConsumerBufferSize: 10 # recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate resilience4j.retry: configs: default: maxAttempts: 3 waitDuration: 100 retryExceptions: - org.springframework.web.client.HttpServerErrorException - java.util.concurrent.TimeoutException - java.io.IOException ignoreExceptions: # - io.github.robwin.exception.BusinessException instances: cars: baseConfig: default roads: baseConfig: default resilience4j.bulkhead: configs: default: maxConcurrentCalls: 100 instances: cars: maxConcurrentCalls: 10 roads: maxWaitDuration: 10ms maxConcurrentCalls: 20 resilience4j.thread-pool-bulkhead: configs: default: maxThreadPoolSize: 4 coreThreadPoolSize: 2 queueCapacity: 2 instances: cars: baseConfig: default roads: maxThreadPoolSize: 1 coreThreadPoolSize: 1 queueCapacity: 1 resilience4j.ratelimiter: configs: default: registerHealthIndicator: false limitForPeriod: 10 limitRefreshPeriod: 1s timeoutDuration: 0 eventConsumerBufferSize: 100 instances: cars: baseConfig: default roads: limitForPeriod: 6 limitRefreshPeriod: 500ms timeoutDuration: 3s resilience4j.timelimiter: configs: default: cancelRunningFuture: false timeoutDuration: 2s instances: cars: baseConfig: default roads: baseConfig: default
இந்த கோப்பு அவர்களின் ரெப்போவில் இருந்து எடுக்கப்பட்ட ஒரு எடுத்துக்காட்டு கோப்பு மற்றும் அதற்கேற்ப எனது உதாரணத்திற்கு மாற்றப்பட்டது. நாம் முன்பு பார்த்தது போல், பல்வேறு வகையான limiters/short-circuit
நிகழ்வுகளுக்கு ஒரு பெயர் உண்டு. உங்களிடம் பல்வேறு பதிவுகள் மற்றும் வெவ்வேறு வரம்புகள் இருந்தால் பெயர் மிகவும் முக்கியமானது. எங்கள் உதாரணத்திற்கு, முன்பு குறிப்பிட்டது போலவே, காலவரையறையில் நாங்கள் ஆர்வமாக உள்ளோம். 2 வினாடிகளுக்கு மட்டுப்படுத்தப்பட்டிருப்பதைக் காணலாம். நாங்கள் சேவையை செயல்படுத்திய விதத்தைப் பார்த்தால், காலக்கெடுவை நாங்கள் கட்டாயப்படுத்துகிறோம்:
@Component open class CarService { open fun getCar(): Mono<Car> { return Mono.just(Car("Fiat")).delayElement(Duration.ofSeconds(10)); } }
பயன்பாட்டைத் தொடங்குவோம், உலாவியில், இங்கு செல்க: http://localhost:8080/cars/test/2 . Fiat
வாங்குவதற்குப் பதிலாக, Rolls Royce
பெறுவோம். காலக்கெடுவை இப்படித்தான் வரையறுத்தோம். அதே வழியில், நாம் எளிதாக CircuitBreaker
உருவாக்கலாம்.
இப்போது வரை, CircuitBreakers
மற்றும் தொடர்புடைய வரம்புகளை செயல்படுத்த மூன்று முக்கிய வழிகளைப் பார்த்தோம். மேலும், நான் உருவாக்கிய பயன்பாட்டின் மூலம் சர்க்யூட் பிரேக்கர்களைச் செயல்படுத்துவதில் எனக்குப் பிடித்த வழியைப் பார்ப்போம், இது பாரிஸிலிருந்து பெர்லினுக்குச் செல்ல சதுரங்களைக் கிளிக் செய்யும் மிகவும் எளிமையான கேம். விளையாட்டை எவ்வாறு செயல்படுத்துவது என்பதைப் புரிந்துகொள்வதற்காக உருவாக்கப்பட்டுள்ளது. இதை எங்கு செயல்படுத்துவது என்பது பற்றி அதிகம் கூறவில்லை. இது எப்படி என்பதை உங்களுடன் பகிர்ந்து கொள்ள நான் வடிவமைத்த ஒரு வழக்கு.
அறிக-எப்போது நான் அதை பின்னர் முடிவு செய்ய உங்களிடமே விட்டு விடுகிறேன். அடிப்படையில், நாங்கள் பல கார்களை உருவாக்கி பெர்லினுக்கு ஒரு வழியை அமைக்க விரும்புகிறோம். இந்த வழித்தடத்தில் உள்ள வெவ்வேறு இடங்களில், சீரற்ற முறையில், பிரச்சனைகளை உருவாக்கும் நகரங்களுக்குச் செல்வோம். எங்களின் circuit breakers
நாங்கள் செல்ல அனுமதிக்கப்படுவதற்கு முன் எவ்வளவு நேரம் காத்திருக்க வேண்டும் என்பதை முடிவு செய்யும். மற்ற கார்களுக்கு எந்த பிரச்சனையும் இல்லை, நாம் சரியான பாதையை தேர்வு செய்ய வேண்டும்.
ஒரு குறிப்பிட்ட நிமிடத்தில் ஒரு குறிப்பிட்ட பிரச்சனை ஒரு நகரத்தில் ஏற்படும் போது அது பதிவு செய்யப்பட்ட கால அட்டவணையை சரிபார்க்க நாங்கள் அனுமதிக்கப்படுகிறோம். நிமிட குறி அதன் 0 குறியீட்டு நிலைகளில் செல்லுபடியாகும். அதாவது 2 என்பது கடிகாரத்தில் உள்ள every
2, 12, 22, 32, 42, 52 நிமிட குறிகளும் இந்த சிக்கலை உருவாக்க செல்லுபடியாகும். சிக்கல்கள் 2 வகைகளாக இருக்கும்: ERROR
மற்றும் TIMEOUT
. ஒரு பிழை தோல்வி உங்களுக்கு 20 வினாடிகள் தாமதத்தை கொடுக்கும்.
ஒரு காலக்கெடு உங்களுக்கு 50 வினாடிகள் தாமதத்தைத் தரும். ஒவ்வொரு நகர மாற்றத்திற்கும், அனைவரும் 10 வினாடிகள் காத்திருக்க வேண்டும். இருப்பினும், காத்திருப்பதற்கு முன், ஃபால்பேக் முறைகளில் இதைச் செய்யும்போது, கார் பின்வரும் நகரத்தின் நுழைவாயிலில் ஏற்கனவே உள்ளது. இந்த வழக்கில், அடுத்த நகரம் தோராயமாக தேர்ந்தெடுக்கப்பட்டது.
application.yml
பயன்படுத்தி எங்கள் resilience4j
பதிவேட்டை எவ்வாறு கட்டமைப்பது என்பதை முன்பே பார்த்தோம். இதைச் செய்த பிறகு, எங்கள் செயல்பாடுகளை எவ்வாறு அலங்கரிப்பது என்பதற்கான சில எடுத்துக்காட்டுகளைப் பார்ப்போம்:
@TimeLimiter(name = CarService.CARS, fallbackMethod = "reportTimeout") @CircuitBreaker(name = CarService.CARS, fallbackMethod = "reportError") @Bulkhead(name = CarService.CARS) open fun moveToCity(id: Long): Mono<RoadRace> { val myCar = roadRace.getMyCar() if (!myCar.isWaiting()) { val destination = myCar.location.forward.find { it.id == id } val blockage = destination?.blockageTimeTable?.find { it.minute.toString().last() == LocalDateTime.now().minute.toString().last() } blockage?.let { roadBlockTime -> when (roadBlockTime.blockageType) { BlockageType.TIMEOUT -> return Mono.just(roadRace).delayElement(Duration.ofSeconds(10)) BlockageType.ERROR -> return Mono.create { it.error(BlockageException()) } BlockageType.UNKNOWN -> return listOf(Mono.create { it.error(BlockageException()) }, Mono.just(roadRace).delayElement(Duration.ofSeconds(10))).random() else -> print("Nothing to do here!") } } destination?.let { myCar.delay(10) myCar.location = it myCar.formerLocations.add(myCar.location) } } return Mono.just(roadRace) } private fun reportError(exception: Exception): Mono<RoadRace> { logger.info("---- **** error reported") roadRace.getMyCar().delay(20L) roadRace.getMyCar().randomFw() roadRace.errorReports.add("Error reported! at ${LocalDateTime.now()}") return Mono.create { it.error(BlockageException()) } } private fun reportTimeout(exception: TimeoutException): Mono<RoadRace> { logger.info("---- **** timeout reported!") roadRace.getMyCar().delay(50L) roadRace.getMyCar().randomFw() roadRace.errorReports.add("Timeout reported! at ${LocalDateTime.now()}") return Mono.just(roadRace) }
நாம் பார்க்க முடியும் என, அசல் சேவை அழைப்புகள் நேரடியாக சிறுகுறிப்புகளைப் பயன்படுத்தி அலங்கரிக்கப்பட்டுள்ளன! தொகுப்பில் AOP
தொகுதி இருப்பதால் மட்டுமே இதைச் செய்ய முடியும்:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
AOP
, அல்லது Aspect Oriented Programming
என்பது OOP
அடிப்படையிலான மற்றொரு நிரலாக்க முன்னுதாரணமாகும். இது OOP
க்கு ஒரு நிரப்பியாகக் கருதப்படுகிறது, மேலும் துல்லியமாக எத்தனை சிறுகுறிப்புகள் வேலை செய்கின்றன. துல்லியமான வெட்டுப்புள்ளிகளில் அசல் முறையைச் சுற்றி, முன் அல்லது பின் பிற செயல்பாடுகளைத் தூண்டுவதற்கு இது அனுமதிக்கிறது. எடுத்துக்காட்டில் இருந்து நீங்கள் பார்க்க முடியும் என, நாங்கள் காலக்கெடு அல்லது பிழைகளை உருவாக்குகிறோம். BlockageException
, ஃபால்பேக் முறையிலும் உருவாக்கப்படுகிறது. இது ஒரு சிக்கலைக் குறிக்கவில்லை. பதிலைத் தவிர.
இருப்பினும், பயன்பாடு WebSockets,
எனவே, இந்த பிழை பயன்பாட்டில் காணப்படாது. இதுவரை, இதுதான் விளையாட்டு. ஒரு நெகிழ்வான பயன்பாட்டைச் செயல்படுத்தும்போது சிறுகுறிப்புகளைப் பயன்படுத்துவது எப்படி நம் வாழ்க்கையை மிகவும் எளிதாக்குகிறது என்பதைக் காட்டுவதை மையமாகக் கொண்டு இதை நான் செயல்படுத்தினேன். எங்களிடம் சர்க்யூட் பிரேக்கர்களை மட்டும் செயல்படுத்தவில்லை, ஆனால் WebSockets
, Spring WebFlux
, Docker
, NGINX
, typescript
மற்றும் பல போன்ற பிற தொழில்நுட்பங்களும் செயல்படுத்தப்பட்டுள்ளன. ஒரு பயன்பாட்டில் சர்க்யூட் பிரேக்கர்ஸ் எவ்வாறு இயங்கும் என்பதைப் பார்க்க இவை அனைத்தும் செய்யப்பட்டுள்ளன. இந்தப் பயன்பாட்டுடன் நீங்கள் விளையாட விரும்பினால், திட்டத்தின் மூலத்திற்குச் சென்று இயக்கவும்:
make docker-clean-build-start
பின்னர் இந்த கட்டளையை இயக்கவும்:
curl -X POST http://localhost:8080/api/fptb/blockage -H "Content-Type: application/json" --data '{"id":1,"name":"Paris","forward":[{"id":2,"name":"Soissons","forward":[{"id":5,"name":"Aken","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":6,"name":"Heerlen","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":7,"name":"Düren","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":3,"name":"Compiègne","forward":[{"id":5,"name":"Aken","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":6,"name":"Heerlen","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":7,"name":"Düren","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":4,"name":"Reims","forward":[{"id":5,"name":"Aken","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":6,"name":"Heerlen","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]},{"id":7,"name":"Düren","forward":[{"id":8,"name":"Berlin","forward":[],"blockageTimeTable":[]}],"blockageTimeTable":[]}],"blockageTimeTable":[]}],"blockageTimeTable":[]}'
இந்த கோரிக்கையின் பேலோட் தொகுதி from-paris-to-berlin-city-generator
பயன்படுத்தி உருவாக்கப்படுகிறது. இந்த தொகுதியை நீங்கள் பார்த்தால், புரிந்துகொள்வது மிகவும் எளிமையானது மற்றும் விளையாட்டிற்கான உங்கள் சொந்த வரைபடத்தை நீங்கள் உருவாக்க முடியும் என்பதை நீங்கள் காண்பீர்கள்! இறுதியாக, http://localhost:9000 க்குச் செல்லவும், உங்கள் பயன்பாடு இயங்க வேண்டும்! இப்போது, நீங்கள் விளையாட்டை விளையாட வலது சதுரங்களில் கிளிக் செய்ய வேண்டும். நீங்கள் வெற்றி பெற விரும்பினால் சிவப்பு நிறத்தில் கிளிக் செய்ய வேண்டாம். சர்க்யூட் பிரேக்கரை நீங்கள் பார்க்க விரும்பினால், தயவுசெய்து பயன்பாட்டுப் பதிவுகளை இயக்கவும்:
docker logs from_paris_to_berlin_web -f
தோல்வியை ஏற்படுத்த சிவப்பு சதுரங்களை வெளிப்படையாகக் கிளிக் செய்யவும்.
உங்கள் பயன்பாடு சிறியதாக இருக்கும் சந்தர்ப்பங்களில் Kystrix
சிறந்தது, மேலும் DSL இன் பயன்பாட்டை மிகவும் குறைவாக வைத்திருப்பதை உறுதிசெய்ய வேண்டும். சர்க்யூட்-பிரேக்கரால் பாதிக்கப்படும் முறைகளை அலங்கரிப்பதற்கான எளிதான வழியை இது வழங்கவில்லை என்பதுதான் தெரிகிறது. Resilience4J
சர்க்யூட் பிரேக்கர்களுடன் நிறுவனப் பணிகளுக்கு சிறந்த தேர்வாகத் தெரிகிறது. இது சிறுகுறிப்பு அடிப்படையிலான நிரலாக்கத்தை வழங்குகிறது, அனைத்து நன்மைகள் வான் AOP ஐப் பயன்படுத்துகிறது, மேலும் அதன் தொகுதிகள் பிரிக்கப்படுகின்றன. ஒரு வகையில், பயன்பாட்டில் உள்ள முக்கியமான புள்ளிகளுக்கும் இது மூலோபாய ரீதியாகப் பயன்படுத்தப்படலாம். பயன்பாட்டின் பல அம்சங்களை உள்ளடக்கிய முழுமையான கட்டமைப்பாகவும் இது பயன்படுத்தப்படலாம்.
நாம் தேர்ந்தெடுக்கும் பிராண்ட் எதுவாக இருந்தாலும், எப்பொழுதும் ஒரு நெகிழ்வான பயன்பாட்டைக் கொண்டிருப்பதே குறிக்கோள். இந்தக் கட்டுரையில், சர்க்யூட் பிரேக்கர்கள் மற்றும் எனது கண்டுபிடிப்புகளை மிக உயர்ந்த மட்டத்தில் நான் தனிப்பட்ட முறையில் எப்படி அனுபவித்தேன் என்பதற்கான சில உதாரணங்களைக் காட்டினேன். இதன் பொருள், சர்க்யூட் பிரேக்கர்கள் என்றால் என்ன, லிமிட்டர்கள் என்ன செய்ய முடியும் என்பதை அறிய விரும்பும் மக்களுக்காக இந்த கட்டுரை எழுதப்பட்டுள்ளது.
circuit breakers
போன்ற மீள்திறன் பொறிமுறைகள் மூலம் எங்கள் பயன்பாடுகளை மேம்படுத்துவது பற்றி சிந்திக்கும்போது சாத்தியக்கூறுகள் மிகவும் வெளிப்படையாக முடிவற்றவை. எங்களிடம் உள்ள வளங்களை சிறப்பாகப் பயன்படுத்த, இந்த முறை ஒரு பயன்பாட்டை நன்றாகச் சரிசெய்ய அனுமதிக்கிறது. பெரும்பாலும் மேகக்கணியில், நமது செலவுகளை மேம்படுத்துவதும், உண்மையில் எத்தனை ஆதாரங்களை நாம் ஒதுக்க வேண்டும் என்பதும் மிக முக்கியமானது.
CircuitBreakers
உள்ளமைப்பது லிமிட்டர்களைப் பொறுத்தவரை ஒரு அற்பமான செயல் அல்ல, மேலும் செயல்திறன் மற்றும் நெகிழ்ச்சியின் உகந்த நிலைகளை அடைய அனைத்து உள்ளமைவு சாத்தியக்கூறுகளையும் நாம் உண்மையில் புரிந்து கொள்ள வேண்டும். சர்க்யூட் பிரேக்கர்களைப் பற்றிய இந்த அறிமுகக் கட்டுரையில் நான் விரிவாகச் செல்ல விரும்பாததற்கு இதுவே காரணம்.
Circuit-breakers
பல்வேறு வகையான பயன்பாடுகளுக்குப் பயன்படுத்தலாம். பெரும்பாலான மெசேஜிங் மற்றும் ஸ்ட்ரீமிங் வகையான பயன்பாடுகளுக்கு இது தேவைப்படும். பெரிய அளவிலான தரவைக் கையாளும் பயன்பாடுகளுக்கு, அதிக அளவில் கிடைக்க வேண்டும், சில வகையான சர்க்யூட் பிரேக்கரைச் செயல்படுத்தலாம். பெரிய ஆன்லைன் சில்லறை விற்பனை கடைகள் தினசரி அடிப்படையில் பெரிய அளவிலான தரவுகளைக் கையாள வேண்டும் மற்றும் கடந்த காலத்தில், Hystrix
பரவலாகப் பயன்படுத்தப்பட்டது. தற்போது, நாம் Resilience4J
இன் திசையில் நகர்வது போல் தோன்றுகிறது, இது இதை விட பலவற்றை உள்ளடக்கியது.
இந்த கட்டுரையை நான் செய்ததைப் போலவே நீங்கள் ரசித்தீர்கள் என்று நம்புகிறேன்! கீழேயுள்ள இணைப்புகளில் ஏதேனும் சமூகத்தில் நீங்கள் வழங்க விரும்பும் மதிப்பாய்வு, கருத்துகள் அல்லது கருத்துகளை இடவும். இந்தக் கட்டுரையைச் சிறப்பாகச் செய்ய நீங்கள் எனக்கு உதவ விரும்பினால் நான் மிகவும் நன்றியுள்ளவனாக இருக்கிறேன். இந்த பயன்பாட்டின் அனைத்து மூலக் குறியீட்டையும் GitHub இல் வைத்துள்ளேன். படித்ததற்கு நன்றி!