de RDX

REST in Peace: Microservices vs monoliths in real-life examples

REST in Peace Microservices vs monoliths in real life
Credit de imagine

Am consultat o duzină de proiecte de microservicii. Unele au fost grozave (acesta este viitorul!) iar unele au fost la fel de frustrante (cine a inventat această porcărie?)

Contează execuția, nu abordarea. Puteți reuși sau eșua cu oricare dintre ele. Nu accepta doar propaganda iubirii / urii de acolo.

Iată câteva experiențe pe care le-am avut care arată cum atât monolitii, cât și microserviciile își au locul lor.

Alegerea instrumentului potrivit pentru locul de muncă potrivit

Echipa mea a construit o aplicație pentru citirea știrilor. Trebuia să răzuiască articole, să extragă conținut, să clasifice, să difuzeze un API, să afișeze panoul de administrare și să gestioneze utilizatorii.

  • Scrapy (Python 2 în acel moment) este liderul când vine vorba de răzuirea web. Deci, am creat un microserviciu care a răzuit adresele URL. (Iată un pic mai mult despre Imagine Docker de 15 MB cu Tor, Privoxy și un manager de proces dacă ești curios.)
  • Ziar (python 3) este una dintre cele mai bune biblioteci de extragere a articolelor open source. Așadar, am creat un microserviciu care, având o adresă URL de intrare, returnează conținutul extras.
  • R are câteva biblioteci bune pentru clasificare. Un coleg cu cunoștințe bune despre R a creat un serviciu pentru clasificarea articolelor folosind API-ul REST al lui R.
  • ActiveAdmin este una dintre cele mai bune și mai ușoare interfețe de panou de administrare. De mult timp, îl folosim pentru ecranele de administrare și l-am conectat și în câteva zile și aici.
  • În cele din urmă pentru gateway-ul API, am folosit Node.js cu PașaportJS (pentru mai multe autentificări) și ElasticSearch.

Înainte de această mare rescriere, vechea noastră aplicație era un monolit Rails. A încercat să reinventeze tot ceea ce am menționat anterior. Vă puteți imagina compromisurile în cod, efort și timp pentru calitate, progres și rezultat.

Monolitii răi încearcă să reinventeze lumea. Ei cred că codul și modelele de proiectare sunt soluție la tot. Se străduiesc să construiască componente reutilizabile, biblioteci și, de asemenea, să devină o platformă pe parcurs. Dar de obicei nu ajung să reușească la niciunul dintre aceste obiective.

Takeaway # 1: Microserviciile sunt o soluție de afaceri, nu doar o soluție tehnologică. Îi scutesc pe dezvoltatori de a pierde timpul reinventând probleme tehnice deja rezolvate.

Nu-mi pasă dacă le numiți „Servicii”, „Arhitectură orientată spre servicii” sau „Microservicii”. Odată ce am trecut de cuvintele cheie, „monolit vs microservicii” se reduce la „1 serviciu vs. N servicii”.

Pentru aplicația noastră, „N servicii” s-a dovedit a fi stiva dorită.

Aplicații Monster CRUD

Unele proiecte de întreprindere pot fi pur și simplu clasificate ca aplicații monstru CRUD (Create-Read-Update-Delete). Sunt un flux nesfârșit de forme, relații de date, transformări și o „logică de afaceri” extrem de complicată. Domeniul de aplicare este imens, dar publicul este mic.

Nimănui nu îi pasă de cele mai bune practici din experiența utilizatorului și este obișnuit să existe ecrane rapide și urâte care să facă treaba.

Am avut un astfel de proiect de transformare a întreprinderii. Vechiul monolit era o integrare bazată pe vizualizarea bazei de date. A fost destul de bine conceput și a necesitat doar câțiva oameni pentru întreținere, inclusiv interfețele de utilizator urâte.

Noile servicii de backend au fost în mare parte scrise în Java, deci a fost dificil de dezvoltat, integrat, partajat și menținut compatibilitatea. Și noile servicii front-end au fost trase în lumea în continuă schimbare a aplicațiilor cu o singură pagină.

Implementarea a necesitat o configurare imensă de automatizare a infrastructurii. Aceasta a fost acum câțiva ani, înainte ca ecosistemul de instrumente pentru dezvoltatori să se maturizeze. La acel moment, fiecare modificare a contractului trebuia coordonată și actualizată manual. A fost opusul scenariului anterior – efortul / ieșirea / cheltuielile generale ale microserviciilor s-a simțit mult mai mare decât cel al vechiului monolit.

Takeaway # 2: Ai grija. Tratarea microserviciilor ca împărțirea straturilor de cod în cutii cu docuri poate duce la „moartea cu o mie de tăieri”.

Îmblânzirea unui copac imens de dependență

Am avut o altă transformare de aplicație de întreprindere moștenită, care a făcut multe lucruri, cum ar fi răzuirea produselor și agregarea paralelă. A fost un monolit complicat, deja tulburat.

Când facem o mulțime de funcții de afaceri ortogonale într-o singură aplicație, aceasta provoacă un arbore de dependență imens în timp de compilare, cu tone de biblioteci și cadre. În consecință, amprenta timpului de rulare, ciclul de viață și timpii de construcție au fost, de asemenea, lungi. Acest lucru a contribuit la adevărata problemă: dezvoltatorii nu au putut repeta repede și, ca urmare, timpul de introducere pe piață a caracteristicilor a suferit.

Timpul necesar pentru codificarea unei caracteristici simple: câteva zile.

Timp pentru actualizarea unei versiuni de bibliotecă (guice): 1 săptămână.

Timpul necesar pentru actualizarea unei versiuni cadru (primăvară): pentru totdeauna.

Lucruri banale au avut șansa să se rupă de fiecare dată când se estimează. Chiar și un mic refactor a durat mult. Se pare că moartea cu o mie de tăieturi este posibilă și cu monolitii.

Am împărțit proiectul în niște limite funcționale. Ne-am asigurat în mod activ să nu partajăm bibliotecile și să evităm blocajul arborelui de dependență.

De exemplu, am folosit o bibliotecă client modernă pentru publicarea mesajelor prin PubSub pentru microservicii. Dar arborele mare de dependență al monolitului nu ne-a permis să folosim aceeași bibliotecă. Așa că am folosit un client PubSub bazat pe HTTP diferit.

Tranziționarii la microservicii fac adesea greșeala clasică de a partaja prea multe biblioteci și astfel recreează aceiași arbori de dependență în timp de compilare (un „monolit distribuit”).

Dar evitând funcționalitatea de partajare, am putea folosi diferite biblioteci pentru a realiza aceleași sarcini fără a fi nevoie să actualizăm lumea.

Unul dintre servicii a necesitat o mulțime de concurențe (~ 1k căutări pentru fiecare cerere). Inițial, a folosit RxJava. Dar ar putea fi rescris în orice zi în Golang cu același contract API și nimănui nu i-ar păsa de arborele dependenței.

Takeaway # 3: Cu microserviciile, nu veți mai auzi niciodată termenul „rescriere mare” sau „sistem vechi”, deoarece nu există sisteme mari.

Mitul scalabilității

Echipa mea a dezvoltat o aplicație de evaluare a codului. A fost 90% CRUD, interfață cu utilizatorul și rapoarte și 10% evaluare complexă a codului pentru o duzină de limbi.

Înainte de a intra, a fost o serie de microservicii – unul pentru fiecare tip de limbă, ascultând cozi de mesaje diferite. Avea un front-end-as-a-service separat, panoul de administrare-as-a-service și așa mai departe. Raționamentul lor original? Scalabilitate.

Am ucis totul și am construit un monolit mai bun. A fost realizat complet ca o singură aplicație Rails – interfață cu utilizatorul, administrator, back-end și interfață candidat.

Partea de evaluare a codului a rulat ca o lucrare de fundal (ActiveJob). Am dezvăluit acest lucru prin containere Docker simple, fără stare, unice. Contractul de bază pentru evaluarea codului s-a schimbat din REST / JSON în fișier / stdin / stdout. S-a redus mult mai bine decât vechiul sistem, pentru că trebuia doar să creștem lucrătorii de bază pentru a face mai multe evaluări de cod.

Ceea ce arăta ca o aplicație sofisticată din exterior – suportând 8 limbaje majore de programare cu evaluare inteligentă – a fost extrem de simplu din interior.

Takeaway # 4: Nu aveți nevoie de microservicii pentru a rula mai multe instanțe ale unui serviciu sau lucrător. Monolitii buni se pot extinde și pentru anumite clase de probleme.

Este foarte posibil să creați monoliti scalabili și microservicii nescalabile. Totul se rezumă la cât de bine aplicați principiile care stau la baza fiecăruia.

Microserviciile ca produse

Unul dintre cele mai satisfăcătoare proiecte de microservicii la care am lucrat a abordat microserviciile ca produse. Clienții noștri erau oameni extrem de inteligenți, tehnofuncționali și foloseau în mod clar microserviciile ca instrument de afaceri.

Au modelat fiecare serviciu ca produs, apoi au lansat mai multe produse către clienți diferiți. Au aliniat versiunile de produse într-un mod în care fiecare să poată beneficia de API-urile altuia. La rândul lor, au creat un ecosistem strălucitor. Le-a făcut un lider de piață pe verticală.

În prezent, întreprinderea medie folosește cel puțin o duzină de produse software și integrări. Consumatorul mediu de cloud utilizează mai multe produse cloud. Acum văd chiar și persoanele non-tehnice care folosesc micro-produse și micro-aplicații. De exemplu, un instrument pentru interviuri, unul pentru urmărirea vacanțelor, unul pentru fișele de plată etc. Oamenii îmbrățișează instrumente mai mici, mai specializate, care fac treaba corectă.

Takeaway # 5: Suntem ferm și ferm în epoca micro-produselor, micro-aplicațiilor și micro-servicii. Mai bine învață să o faci bine.

Există această frică constantă de a învăța automat să fure locuri de muncă de programare. Majoritatea joburilor de programare devin API-uri astăzi.

Tranzacții distribuite

Unul dintre cele mai frecvente argumente împotriva utilizării microserviciilor este riscul asociat tranzacțiilor distribuite.

Apelați la un sistem de gateway de plată extern care deduce bani, dar care poate eșua la apelul dvs. de apel? Aveți mai multe mecanisme de conectare (cum ar fi e-mail sau OAuth)? Apelați produse SaaS de la terțe părți care nu au opțiune de revenire? Folosiți API-uri Cloud și găleți de stocare care nu respectă limita tranzacției? Aveți fluxuri de lucru care acoperă mai multe cicluri de viață ale cererii către același serviciu?

Apoi, ați distribuit deja tranzacțiile într-un fel sau altul, indiferent dacă vă place sau nu.

Întreaga idee că un sistem și o singură cerere pot reprezenta sau controla întreaga stare tranzacțională a problemei de afaceri este o fantezie. Dacă vă puteți modela integrările externe fără blocări și tranzacții distribuite, atunci puteți modela și cele interne.

Takeaway # 6: Blocările și tranzacțiile distribuite nu sunt gratuite nici cu Monoliths.

Unelte vs Oameni

Da, mai multe servicii înseamnă mai multe instrumente. Aceasta implică integrarea continuă și implementarea continuă (CI / CD), automatizarea infrastructurii, instrumentele dezvoltatorilor, capacitatea de a proiecta API-uri bune, partajarea contractelor, documentarea, inteligența și bibliotecile clientului, procesele, testarea și multe alte instrumente.

Trebuie să fii cel puțin atât de înalt pentru a călători în microservicii.

Dacă o organizație nu are robustețea și maturitatea inginerească pentru a rula fără efort o mână de servicii (12factor, CI, CD, integrare, testare etc.), va fi un dezastru să treci la multe dintre ele.

Mulți oameni care provin dintr-o mentalitate monolită fac Design mare în față. Microserviciile sunt cele mai bune atunci când sunt in fata ta. Doar aruncați toate cazanele, implementați API-ul într-un mod fără sens și investiți timp în teste de calitate / unitate de bună calitate. Ca și în cazul instrumentelor VS – microserviciile necesită o schimbare a mentalității și o mulțime de dezvățând.

Vestea bună este că multe dintre aceste probleme de scule au soluții inginerești bune. Instrumente Docker, Kubernetes, REST, Swagger, Falcor, gRPC, CI / CD Pipeline, PaaS, Cloud și așa mai departe. Ecosistemul din jurul microserviciilor s-a maturizat deja destul de mult și se îmbunătățește tot timpul.

Vestea proastă este că microserviciile nu pot fi învățate ca un cadru sau un instrument. Au nevoie de un abordare holistică asta vine cu experiența. Aveți nevoie de oameni buni, care nu sunt doar codificatori buni cu forță brută, ci și ingineri bine rotunzi, cu o bază solidă în întregul ciclu de viață al dezvoltării software-ului, de la dezvoltare până la testare până la implementare.

Există întreprinderi mari care necesită luni pentru fiecare integrare. Și apoi există companii moderne precum Google, Facebook și Netflix care rulează mii de servicii integrate la o calitate și viteză mult mai mari. Diferența nu este doar instrumentele, ci oamenii implicați și abordarea lor inginerească.

Takeaway # 7: Microserviciile sunt punctul culminant al practicilor multiple de inginerie. Au o curbă abruptă de învățare, dezvățare și transformare.

Concluzie

Abordarea microserviciilor este doar un alt instrument din trusa de instrumente a soluționistului. Și un instrument este doar un instrument. Poate ajunge să fie un activ comercial puternic sau un obstacol neproductiv pentru dezvoltatori. Indiferent dacă avem dreptate sau greșim, totul se rezumă la modul în care folosim acest instrument.