Java Mikroservislərinin tərcüməsi və uyğunlaşdırılması : Praktik Bələdçi . Bələdçinin əvvəlki hissələri:
- mikroservislərin əsasları və onların arxitekturası ;
- mikroservislərin yerləşdirilməsi və sınaqdan keçirilməsi .
Java mikroservisini necə davamlı etmək olar?
Xatırladaq ki, siz mikroservislər yaratdığınız zaman siz sinxron HTTP zəngləri və ya asinxron mesajlaşma üçün JVM metodu çağırışları ilə ticarət edirsiniz. Metod çağırışının əsasən tamamlanmasına zəmanət verilsə də (gözlənilməz JVM-nin bağlanması istisna olmaqla), şəbəkə zəngi defolt olaraq etibarsızdır. O, işləyə bilər, lakin müxtəlif səbəblərdən işləməyə bilər: şəbəkə həddən artıq yüklənib, yeni firewall qaydası tətbiq edilib və s. Bunun necə dəyişdiyini görmək üçün BillingService nümunəsinə nəzər salaq.HTTP/REST Davamlılıq Nümunələri
Tutaq ki, müştərilər şirkətinizin saytında elektron kitablar ala bilərlər. Bunu etmək üçün siz indicə faktiki PDF fakturaları yaratmaq üçün onlayn mağazanıza zəng edə biləcək faktura mikroservisini tətbiq etdiniz. Hələlik biz bu zəngi HTTP üzərindən sinxron şəkildə edəcəyik (baxmayaraq ki, bu xidmətə asinxron zəng etmək daha məntiqlidir, çünki PDF generasiyasının istifadəçi baxımından ani olması lazım deyil. Növbəti nümunədə eyni nümunədən istifadə edəcəyik. bölməsinə baxın və fərqlərə baxın).@Service
class BillingService {
@Autowired
private HttpClient client;
public void bill(User user, Plan plan) {
Invoice invoice = createInvoice(user, plan);
httpClient.send(invoiceRequest(user.getEmail(), invoice), responseHandler());
// ...
}
}
Xülasə etmək üçün bu HTTP çağırışının üç mümkün nəticəsi var.
- OK: zəng keçdi, hesab uğurla yaradıldı.
- GECİKME: Zəng keçdi, lakin tamamlanması çox uzun çəkdi.
- XƏTA. Zəng uğursuz oldu, siz uyğun olmayan sorğu göndərmisiniz və ya sistem işləməyə bilər.
Mesajlaşma Dözümlülük Nümunələri
Gəlin asinxron rabitəyə daha yaxından nəzər salaq. Mesajlaşma üçün Spring və RabbitMQ istifadə etdiyimizi fərz etsək, BillingService proqramımız indi bu kimi görünə bilər. Hesab yaratmaq üçün biz indi RabbitMQ mesaj brokerimizə mesaj göndəririk, burada bir neçə işçi yeni mesajlar gözləyir. Bu işçilər PDF hesab-fakturaları yaradır və müvafiq istifadəçilərə göndərirlər.@Service
class BillingService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void bill(User user, Plan plan) {
Invoice invoice = createInvoice(user, plan);
// преобразует счет, например, в json и использует его How тело messages
rabbitTemplate.convertAndSend(exchange, routingkey, invoice);
// ...
}
}
Potensial xətalar indi bir az fərqli görünür, çünki siz sinxron HTTP bağlantısı ilə etdiyiniz kimi dərhal OK və ya XƏTA cavablarını almırsınız. Bunun əvəzinə, yanlış gedə biləcək üç potensial ssenarimiz ola bilər ki, bu da aşağıdakı sualları doğura bilər:
- Mesajım işçi tərəfindən çatdırılıb və istifadə olunubmu? Yoxsa itib? (İstifadəçi hesab-faktura almır).
- Mesajım yalnız bir dəfə çatdırılıb? Yoxsa bir dəfədən çox çatdırılıb və yalnız bir dəfə işlənib? (İstifadəçi çoxlu faktura alacaq).
- Konfiqurasiya: "Mən mübadilə üçün düzgün marşrut açarlarından/adlarından istifadə etdimmi"dən "Mesaj brokerim düzgün şəkildə konfiqurasiya edilib və saxlanılıbmı, yoxsa onun növbələri doludurmu?" (İstifadəçi hesab-faktura almır).
- ActiveMQ kimi JMS tətbiqetmələrindən istifadə edirsinizsə, iki fazalı (XA) öhdəliklərin zəmanəti üçün sürəti dəyişə bilərsiniz.
- Əgər siz RabbitMQ-dan istifadə edirsinizsə, əvvəlcə bu təlimatı oxuyun və sonra təsdiqlər, xətaya dözümlülük və ümumiyyətlə mesajın etibarlılığı haqqında diqqətlə düşünün.
- Bəlkə kimsə Active və ya RabbitMQ serverlərinin konfiqurasiyasını yaxşı bilir, xüsusən də klasterləşdirmə və Docker ilə birlikdə (hər kəs? ;))
Java mikroservisləri üçün hansı çərçivə ən yaxşı həll yolu olardı?
Bir tərəfdən, Spring Boot kimi çox məşhur bir seçim quraşdıra bilərsiniz . Bu, .jar faylları yaratmağı çox asanlaşdırır, Tomcat və ya Jetty kimi daxili veb server ilə gəlir və tez və istənilən yerdə işlədilə bilər. Mikroservis proqramları yaratmaq üçün idealdır. Bu yaxınlarda, qismən reaktiv proqramlaşdırmadan ilhamlanmış bir neçə ixtisaslaşmış mikroservis çərçivələri, Kubernetes və ya GraalVM ortaya çıxdı. Burada daha bir neçə maraqlı iddiaçı var: Quarkus , Micronaut , Vert.x , Helidon . Nəhayət, özünüz üçün seçim etməli olacaqsınız, lakin biz sizə tamamilə standart olmaya biləcək bir neçə tövsiyə verə bilərik: Spring Boot istisna olmaqla, bütün mikroservis çərçivələri adətən inanılmaz dərəcədə sürətli, demək olar ki, dərhal işə salınır. , aşağı yaddaş istifadəsi, sonsuzluğa qədər genişlənmə. Marketinq materialları adətən platformanı behemot Spring Boot-un yanında və ya bir-birinə göstərən təsir edici qrafikalara malikdir. Bu, nəzəri olaraq, bəzən yüklənməsi bir neçə dəqiqə çəkən köhnə layihələri dəstəkləyən tərtibatçıların əsəblərini qoruyur. Və ya buludda işləyən və hazırda 50 ms ərzində ehtiyac duyduqları qədər mikrokonteyneri işə salmaq/dayandırmaq istəyən tərtibatçılar. Problem ondadır ki, bu (süni) çılpaq metal işə salınma vaxtları və yenidən yerləşdirmə vaxtları layihənin ümumi uğuruna çətin ki, kömək edir. Ən azı onlar güclü çərçivə infrastrukturundan, güclü sənədlərdən, icmadan və güclü developer bacarıqlarından daha az təsir göstərir. Buna görə də buna belə baxmaq daha yaxşıdır: Əgər indiyə qədər:- Sadə iş axınları üçün yüzlərlə sorğu yaradaraq ORM-lərinizin geniş şəkildə işləməsinə icazə verirsiniz.
- Orta dərəcədə mürəkkəb monolitinizi idarə etmək üçün sonsuz gigabayta ehtiyacınız var.
- Sizdə o qədər çox kod var və mürəkkəblik o qədər yüksəkdir (biz indi Hibernate kimi potensial yavaş başlanğıclardan danışmırıq) ki, tətbiqinizin yüklənməsi bir neçə dəqiqə çəkir.
Sinxron Java REST zəngləri üçün hansı kitabxanalar daha yaxşıdır?
Aşağı səviyyəli texniki tərəfdə, çox güman ki, aşağıdakı HTTP müştəri kitabxanalarından biri ilə nəticələnəcəksiniz: Java-nın yerli HttpClient (Java 11-dən bəri), Apache-nin HttpClient və ya OkHttp . Qeyd edək ki, mən burada "ehtimal" deyirəm, çünki köhnə JAX-RS müştərilərindən tutmuş müasir WebSocket müştərilərinə qədər başqa seçimlər var . İstənilən halda, tendensiya HTTP müştərisi yaratmaq, HTTP zəngləri ilə məşğul olmaqdan uzaqlaşmaqdır. Bunu etmək üçün, daha ətraflı oxumaq üçün başlanğıc nöqtəsi kimi OpenFeign layihəsinə və onun sənədlərinə nəzər salmalısınız .Asinxron Java mesajlaşması üçün ən yaxşı brokerlər hansılardır?
Çox güman ki, siz məşhur ActiveMQ (Klassik və ya Artemis) , RabbitMQ və ya Kafka ilə qarşılaşacaqsınız .- ActiveMQ və RabbitMQ ənənəvi, tam hüquqlu mesaj brokerləridir. Onlar “ağıllı broker” və “axmaq istifadəçilərin” qarşılıqlı əlaqəsini əhatə edir.
- Tarixən ActiveMQ RabbitMQ/Docker/TestContainer parametrləri ilə yüngülləşdirilə bilən asan daxiletmənin (sınaq üçün) faydasına malikdir.
- Kafkanı ənənəvi “ağıllı” broker adlandırmaq olmaz. Bunun əvəzinə, ağıllı istehlakçıların emal etməsini tələb edən nisbətən "lal" mesaj anbarıdır (log faylı).
Mikroservisləri sınamaq üçün hansı kitabxanalardan istifadə edə bilərəm?
Bu, yığınınızdan asılıdır. Əgər yay ekosisteminiz varsa, çərçivənin xüsusi alətlərindən istifadə etmək müdrik olardı . JavaEE Arquillian kimi bir şeydirsə . Xüsusilə yerli inkişaf və ya inteqrasiya testləri üçün Oracle verilənlər bazasını asanlıqla və tez qurmağa kömək edən Docker-ə və həqiqətən yaxşı Testcontainers kitabxanasına nəzər salmağa dəyər ola bilər . Bütün HTTP serverlərini sınaqdan keçirmək üçün Wiremock-a baxın . Asinxron mesajlaşmanı yoxlamaq üçün ActiveMQ və ya RabbitMQ tətbiq etməyə çalışın və sonra Awaitility DSL istifadə edərək testlər yazın . Bundan əlavə, bütün adi alətləriniz istifadə olunur - Junit , TestNG for AssertJ və Mockito . Nəzərə alın ki, bu tam siyahı deyil. Sevdiyiniz aləti burada tapmasanız, lütfən şərh bölməsində qeyd edin.Bütün Java mikroservisləri üçün girişi necə aktivləşdirmək olar?
Mikroservislər vəziyyətində giriş maraqlı və olduqca mürəkkəb bir mövzudur. Daha az və ya grep əmrləri ilə manipulyasiya edə biləcəyiniz bir günlük faylına sahib olmaq əvəzinə, indi n log faylınız var və siz onların çox dağınıq olmamasını istəyirsiniz. Ağac kəsmə ekosisteminin xüsusiyyətləri bu məqalədə yaxşı təsvir edilmişdir (ingilis dilində). Onu oxumağınızdan əmin olun və mikroservislər baxımından Mərkəzləşdirilmiş giriş bölməsinə diqqət yetirin . Təcrübədə müxtəlif yanaşmalarla qarşılaşacaqsınız: Sistem inzibatçısı müxtəlif serverlərdən log fayllarını toplayan və birləşdirən müəyyən skriptlər yazır və onları yükləmək üçün FTP serverlərinə yerləşdirir. Paralel SSH seanslarında cat/grep/unig/sort kombinasiyalarının işlədilməsi. Bu, Amazon AWS-nin etdiyi şeydir və menecerinizə məlumat verə bilərsiniz. Graylog və ya ELK Stack (Elasticsearch, Logstash, Kibana) kimi alətdən istifadə edinMikroservislərim bir-birini necə tapır?
İndiyə qədər mikroservislərimizin bir-birini tanıdığını və müvafiq IPS-i bildiyini güman etdik. Statik konfiqurasiya haqqında danışaq. Beləliklə, bizim bank monolitimiz [ip = 192.168.200.1] xassələr faylında kodlanmış risk serveri [ip = 192.168.200.2] ilə danışmalı olduğunu bilir. Bununla belə, hər şeyi daha dinamik edə bilərsiniz:- Bütün mikroservislərin öz mikroservislərində application.properties fayllarını yerləşdirmək əvəzinə konfiqurasiyalarını götürdüyü bulud əsaslı konfiqurasiya serverindən istifadə edin.
- Xidmət nümunələriniz yerlərini dinamik olaraq dəyişə bildiyi üçün, xidmətlərinizin harada yaşadığını, IP-lərinin nə olduğunu və onları necə yönləndirəcəyini bilən xidmətlərə baxmağa dəyər.
- İndi hər şey dinamikdir, yeni problemlər ortaya çıxır, məsələn, liderin avtomatik seçilməsi: məsələn, iki dəfə işləməmək üçün müəyyən tapşırıqlar üzərində işləyən usta kimdir? Rəhbər uğursuz olduqda onu kim əvəz edir? Dəyişdirmə nəyə əsaslanaraq həyata keçirilir?
Java mikroservislərindən istifadə edərək avtorizasiya və autentifikasiyanı necə təşkil etmək olar?
Bu mövzu da ayrıca bir hekayəyə layiqdir. Yenə də seçimlər xüsusi təhlükəsizlik çərçivələri ilə sərt kodlanmış əsas HTTPS autentifikasiyasından tutmuş, öz avtorizasiya serveri ilə Oauth2 quraşdırmasını işə salmağa qədər dəyişir.Bütün mühitlərimin eyni göründüyünə necə əmin ola bilərəm?
Mikroservisi olmayan yerləşdirmələr üçün doğru olan, bir xidmətlə yerləşdirmələr üçün də doğrudur. Docker/Testcontainers və Scripting/Ansible birləşməsini sınayın.Sual yoxdur: YAML haqqında qısaca
Gəlin bir anlığa kitabxanalardan və əlaqəli məsələlərdən uzaqlaşaq və Yaml-a qısaca nəzər salaq. Bu fayl formatı de-fakto “konfiqurasiyanın kod kimi yazılması” formatı kimi istifadə olunur. Ansible kimi sadə alətlər və Kubernetes kimi nəhənglər tərəfindən də istifadə olunur. YAML girintisinin ağrısını yaşamaq üçün sadə bir Ansible faylı yazmağa çalışın və gözlənildiyi kimi işləməzdən əvvəl faylı nə qədər redaktə etməlisiniz. Bu formatın bütün əsas IDE-lər tərəfindən dəstəklənməsinə baxmayaraq! Bundan sonra bu təlimatı oxuyub bitirmək üçün geri qayıdın.Yaml:
- is:
- so
- great
Paylanmış əməliyyatlar haqqında nə demək olar? Performans testi? Başqa mövzular?
Bəlkə bir gün, təlimatın gələcək nəşrlərində. Hələlik, hamısı budur. Bizimlə qal!Mikroservislərlə bağlı konseptual problemlər
Java-da mikroservislərin spesifik problemlərindən başqa, deyək ki, istənilən mikroservis layihəsində ortaya çıxan başqa problemlər də var. Onlar əsasən təşkilat, komanda və idarəetmə ilə bağlıdır.Frontend və Backend uyğunsuzluğu
Frontend və Backend uyğunsuzluğu bir çox mikroservis layihələrində çox yayılmış problemdir. Bunun mənası nədi? Yalnız yaxşı köhnə monolitlərdə veb interfeysi tərtibatçılarının məlumat əldə etmək üçün xüsusi bir mənbəsi var idi. Mikroservis layihələrində front-end tərtibatçıları birdən məlumat əldə etmək üçün n mənbəyə sahib olurlar. Təsəvvür edin ki, siz Java-da bir növ IoT (Əşyaların İnterneti) mikroservisləri layihəsi yaradırsınız. Tutaq ki, siz bütün Avropada geodeziya maşınları və sənaye sobalarını idarə edirsiniz. Və bu sobalar sizə öz temperaturları və s. ilə bağlı müntəzəm yeniləmələr göndərir. Gec-tez siz "soba axtarışı" mikroxidmətlərindən istifadə etməklə admin UI-də sobalar tapmaq istəyə bilərsiniz. Backend tərəfdaşlarınızın domenə əsaslanan dizayn və ya mikroservis qanunlarını nə dərəcədə ciddi şəkildə tətbiq etməsindən asılı olaraq , “soba tap” mikroservisi növ, model və ya yer kimi digər məlumatları deyil, yalnız soba identifikatorlarını qaytara bilər. Bunu etmək üçün, frontend tərtibatçıları ilk mikroservisdən aldıqları identifikatorlarla “soba məlumatlarını əldə et” mikro xidmətində bir və ya n əlavə zəng (peycin tətbiqindən asılı olaraq) etməli olacaqlar. Və bu sadə bir nümunə olsa da, real (!) layihədən götürülsə də, belə bir problemi nümayiş etdirir: supermarketlər son dərəcə populyarlaşıb. Çünki onlarla tərəvəz, limonad, dondurulmuş pizza və tualet kağızı almaq üçün 10 fərqli yerə getməyə ehtiyac yoxdur. Bunun əvəzinə bir yerə gedirsiniz. Bu, daha asan və sürətlidir. Eyni şey front-end və mikroservis tərtibatçılarına da aiddir.İdarəetmə gözləntiləri
Rəhbərlik səhv təəssürat altındadır ki, onlar indi (ümumi) layihə üçün sonsuz sayda tərtibatçı işə götürməlidirlər, çünki tərtibatçılar indi bir-birindən tamamilə müstəqil, hər biri öz mikroservislərində işləyə bilər. Yalnız sonda bir az inteqrasiya işi tələb olunur (başlanğıcdan qısa müddət əvvəl). Əslində bu yanaşma son dərəcə problemlidir. Növbəti paraqraflarda bunun səbəbini izah etməyə çalışacağıq.“Kiçik parçalar” “daha yaxşı parçalar”a bərabər deyil.
20 hissəyə bölünmüş kodun mütləq bir parçadan daha keyfiyyətli olacağını düşünmək böyük səhv olardı. Keyfiyyəti sırf texniki nöqteyi-nəzərdən götürsək belə, fərdi xidmətlərimiz hələ də dəstəklənməyən kodun təbəqələrini keçərək verilənlər bazasından istifadəçi seçmək üçün 400 Hazırda gözləmə sorğusunu icra edə bilər. Bir daha Simon Brown sitatına qayıdırıq: monolitləri düzgün qura bilməsəniz, düzgün mikroservislər qurmaq çətin olacaq. Mikroservis layihələrində səhvlərə dözümlülük haqqında danışmaq çox vaxt gec olur. O qədər ki, mikroservislərin real layihələrdə necə işlədiyini görmək bəzən qorxulu olur. Bunun səbəbi Java tərtibatçılarının səhvlərə dözümlülük, şəbəkə və digər əlaqəli mövzuları lazımi səviyyədə öyrənməyə həmişə hazır olmamasıdır. "Parçaların" özləri daha kiçikdir, lakin "texniki hissələr" daha böyükdür. Təsəvvür edin ki, mikroservislər komandanızdan verilənlər bazası sisteminə daxil olmaq üçün texniki mikroservis yazmağı xahiş edirlər, buna bənzər bir şey:@Controller
class LoginController {
// ...
@PostMapping("/login")
public boolean login(String username, String password) {
User user = userDao.findByUserName(username);
if (user == null) {
// обработка варианта с несуществующим пользователем
return false;
}
if (!user.getPassword().equals(hashed(password))) {
// обработка неверного пароля
return false;
}
// 'Ю-ху, залогинorсь!';
// установите cookies, делайте, что угодно
return true;
}
}
İndi komandanız qərar verə bilər (və bəlkə də iş adamlarını buna inandıra bilər) ki, bu, çox sadə və darıxdırıcıdır, giriş xidməti yazmaq əvəzinə, heç bir real və maddi iş tələbləri olmadan həqiqətən faydalı UserStateChanged mikroservisini yazmaq daha yaxşıdır. Bəzi insanlar hazırda Java-ya dinozavr kimi yanaşdıqları üçün gəlin UserStateChanged mikroservisimizi dəbli Erlanqda yazaq. Və gəlin bir yerdə qırmızı-qara ağaclardan istifadə etməyə çalışaq, çünki Stiv Yegge yazıb ki, Google-a müraciət etmək üçün onları içəridən bilmək lazımdır. İnteqrasiya, texniki xidmət və ümumi dizayn baxımından bu, tək bir monolit içərisində spagetti kodu qatlarını yazmaq qədər pisdir. Süni və adi bir nümunə? Bu doğrudur. Ancaq bu, reallıqda baş verə bilər.
Daha az parça - daha az anlayış
Sonra təbii olaraq sual yaranır ki, sistemi bütövlükdə, onun proseslərini və iş axınlarını başa düşmək lazımdır, lakin eyni zamanda siz bir tərtibatçı kimi yalnız təcrid olunmuş mikroservisinizdə işləməyə cavabdehsiniz [95: login-101: updateUserProfile]. Bu, əvvəlki paraqrafla uyğunlaşır, lakin təşkilatınızdan, etibar və ünsiyyət səviyyənizdən asılı olaraq, bu, mikroservis zəncirində təsadüfi bir nasazlıq olarsa, bir çox çaşqınlığa, çiyinlərini çəkməyə və günahlandırmaya səbəb ola bilər. Və baş verənlərə görə bütün məsuliyyəti öz üzərinə götürəcək heç kim yoxdur. Və bu heç də vicdansızlıq məsələsi deyil. Əslində, müxtəlif hissələri birləşdirmək və layihənin ümumi mənzərəsindəki yerini başa düşmək çox çətindir.Rabitə və xidmət
Rabitə və xidmət səviyyəsi şirkətin ölçüsündən asılı olaraq çox dəyişir. Bununla belə, ümumi əlaqə göz qabağındadır: nə qədər çox olsa, bir o qədər problemlidir.- 47 saylı mikroservisi kim idarə edir?
- Onlar mikroservisin yeni, uyğun olmayan versiyasını yerləşdirdilər? Bu harada sənədləşdirilib?
- Yeni funksiya tələb etmək üçün kiminlə danışmalıyam?
- Bu dili bilən yeganə şəxs şirkətdən ayrıldıqdan sonra Erlanqda o mikroservisə kim dəstək verəcək?
- Bütün mikroservis komandalarımız təkcə müxtəlif proqramlaşdırma dillərində deyil, həm də müxtəlif vaxt zonalarında işləyir! Bütün bunları necə düzgün əlaqələndirə bilərik?
GO TO FULL VERSION