Aplicații modulare în Java. Cum? +1
- 24.03.17 02:54 •
- jetinfosystems •
- # 324810 •
- Habrahabr •
- 42 •
- 3800
- la fel ca Forbes, doar mai bine.
OSGi se grăbește să salveze
Pentru a crea o arhitectură modulară cu adevărat în Java poate utiliza OSGi (Open Services Gateway Initiative) - un caiet de sarcini modul sistem dinamic și platforma de servicii pentru aplicații bazate pe Java (OSGi Alliance Developer). Descrie un model de dezvoltare software în care componentele au trei caracteristici principale ale unei aplicații modulare. Vorbind despre încapsulare (fiecare modul ascunde punerea în aplicare a acestuia din mediul extern), conexiune slabă (modulele interacționează numai cu ajutorul unor contracte de pre-negociate) și dinamice (componentele pot fi înlocuite pe zbor fără oprire întreaga aplicație). Bazele conceptului OSGi sunt două entități: pachete și servicii.
Când se dezvoltă software-ul Java, de regulă se utilizează biblioteci terțe. În lume, bibliotecile Java sunt împachetate în fișiere cu extensia JAR (Java ARchive). o arhivă ZIP obișnuită care conține clase Java (fișiere cu extensia .class). Cu toate acestea, utilizarea bibliotecilor poate fi dificilă.
De îndată ce începeți să utilizați orice bibliotecă, sunteți, de obicei, la dispoziția tuturor claselor din bibliotecă. Ideea este că dezvoltatorii de biblioteci nu au capacitatea de a ascunde clasele care sunt folosite pentru implementarea logicii lor interne. Astfel, dacă utilizați un cod care nu a fost destinat utilizării în afara bibliotecii, este posibil să întâlniți incompatibilități atunci când utilizați o versiune nouă a bibliotecii sau să întrerupeți funcționarea corectă.
O altă problemă este așa-numita JAR Hell, despre care dezvoltatorii au spart multe copii. Esența sa este după cum urmează: odată ce începeți să utilizați diferite versiuni ale unei biblioteci (acest lucru se întâmplă în proiecte mari care evoluează de-a lungul timpului), puteți întâlni că aceeași clasă are metode diferite în diferite versiuni ale bibliotecii. Java este proiectat să utilizeze prima versiune a bibliotecii, care va găsi încărcătorul de clasă. Astfel, dacă adresați codul unei clase la timpul de execuție, veți primi o eroare că metoda pe care o accesați nu există. Acest lucru se datorează faptului că, în stadiul de execuție, Java nu știe nimic despre versiunea bibliotecii care ar trebui folosită în acest sau acel scenariu.
Dezvoltatorii OSGi nu au schimbat structura fișierelor JAR pentru a furniza modularitate, ci au adăugat pur și simplu informații suplimentare care au fost utilizate de mediul OSGi. Mai mult, aceste informații nu afectează utilizarea fișierelor JAR în aplicațiile obișnuite Java. Astfel, pentru a face fișierul JAR un set OSGi, se adaugă date care definesc Export-Package (pachetele din acest set care sunt disponibile pentru utilizare în afara acestuia) și Import-Package (pachetele altor seturi necesare pentru acest set). Este posibil să se precizeze atât versiunea API pe care setul o oferă pentru alte seturi, cât și versiunea sau intervalul de versiuni ale API pe care setul le cere pentru munca lor. Toate clasele setate care nu sunt în secțiunea exportată nu sunt disponibile în afara setului (Private). În acest fel, setul OSGi îndeplinește cerința unei conectivități slabe.
Astăzi, majoritatea bibliotecilor Java sunt deja pregătite pentru OSGi, adică conțin informații pentru a fi executate în containerul OSGi. În plus, există multe instrumente și utilitare cu care puteți crea module pentru OSGi din fișiere JAR obișnuite.
În OSGi, puteți evita cu ușurință situațiile JAR Hell, deoarece dependențele dintre seturi și interfețele furnizate de aceste seturi au versiuni clare. Puteți încărca dinamic și descărca din nou seturi noi la timpul de execuție. OSGi urmărește dependențele dintre seturi și le rezolvă dinamic.
Prin urmare, folosind seturile OSGi, putem dezvolta aplicații modulare care interacționează prin interfețe (API). Dar de unde pot obține o clasă care implementează interfața necesară? Opțiunea "Adăugați la setul API" nu funcționează - în cadrul arhitecturii modulare, am convenit să nu folosim clase interne setate în afara acestor seturi. O altă soluție. aplicați șablonul "fabrică", implementând interfața și adăugați-l la setul API. Dar nici nu este prea reușit. Pentru a ascunde implementarea interfeței, va trebui să dezvoltați o clasă nouă de fiecare dată.
Căutarea implementării interfeței în OSGi se realizează utilizând registrul de servicii. În acest registru, setul poate înregistra o implementare cu interfața sa care o descrie. Un set care utilizează o interfață dintr-un alt set poate găsi în registru implementarea necesară a interfeței de care are nevoie. În mod tipic, serviciile de înregistrări de seturi se execută în containerul OSGi. În plus, în registrul de servicii, aceleași interfețe pot fi înregistrate cu diferite implementări și date suplimentare de identificare. Folosind filtrarea, setul poate selecta cel mai potrivit dintre serviciile prezentate în registru.
Java Virtual Machine
Arhitectura de micro-servicii este un set de module independente - aplicații individuale. Interacțiunea dintre acestea are loc prin intermediul unor interfețe clar definite, folosind protocoale ușoare (REST, Buffer Protocol, MQ, etc.). De fapt, fiecare modul este un microserviciu care execută o anumită sarcină și, de regulă, conține o cantitate minimă de cod. Avantajele acestei abordări în dezvoltarea de software:
- ușurință (atunci când se dezvoltă un micro-serviciu, este implementată doar o parte din funcționalitatea programului).
- simplitatea înlocuirii (dacă serviciul nu face față sarcinilor sale, poate fi rescris și înlocuit cu o nouă versiune fără a opri actualul software).
- reutilizarea (microserviciul poate fi reutilizat acolo unde se potrivește).
Dezvoltatorii aplicațiilor modulare care utilizează OSGi și-au bucurat mult timp de toate aceste avantaje, dar numai în cadrul mașinii virtuale Java. Fiecare set cu OSGi, care publică serviciul în registru, este un microserviciu în Java Virtual Machine, JVM (în lumea OSGi aceste microservicii sunt numite μServices).
Red Hat JBoss Fuse
Noi, la Dzhete, folosim toate avantajele OSGi atunci când dezvoltăm software pentru operatorii de telecomunicații, asigurări, companii de procesare. Pentru a face acest lucru, folosim siguranța Red Hat JBoss (configurația Fuse Fabric). Această platformă oferă un mediu OSGi flexibil pentru executarea unei aplicații modulare.
Continuitatea aplicațiilor, scalarea orizontală ușoară, implementarea ușoară, instrumentele de gestionare a cluster-ului pentru software-ul cluster sunt disponibile în Fuse Fabric. Tehnologia vă permite să implementați mai multe exemple de Red Hat JBoss Fuse și să le îmbinați într-un cluster și oferă, de asemenea, un instrument de management centralizat pentru mediul rezultat.
În cadrul Fabric Fuse, există următoarele abstracții:
Caracteristicile sunt o colecție de seturi OSGi care implementează orice funcție funcțională.
Profilurile reprezintă o colecție de caracteristici care trebuie efectuate într-un singur container și setări de configurare pentru seturile care sunt incluse în caracteristică.
Containerele (containerele) sunt procese JVM individuale care rulează pe un anumit nod al unui cluster Fuse Fabric care rulează un container Red Hat JBoss Fuse.
Orice software bazat pe tehnologia Fuse Fabric constă din seturi OSGi grupate în funcții și implementate într-un singur proces JVM pe unul sau mai multe noduri de cluster, în conformitate cu un profil predefinit.
Mediul Fuse Fabric oferă multe instrumente pentru gestionarea ușoară a clusterului rezultat. Puteți crea profiluri (și bazele lor de containere), crea / șterge / începe / opri containerele de pe orice gazdă din cluster, conectează noi noduri de cluster și așa mai departe. Și toate acestea online - fără a întrerupe funcționarea nodurilor rămase ale clusterului. Este posibil să stocați mai multe versiuni de profile, caracteristici, seturi OSGi.
Datorită tehnologiei Distributed OSGi, seturile OSGi pot interacționa în cadrul unui container și a altor contacte și chiar a unor gazde diferite în mediul primit. În plus (cu costuri minime de dezvoltare), fiecare serviciu care oferă pachetul OSGi poate fi transformat într-un serviciu REST / web care poate fi apelat de la sisteme externe.
Astfel, folosind Fuse Fabric, putem crea arhitectura mikroservisnuyu care acceptă configurarea ușoară și implementarea, performanța izolată a serviciilor din cadrul sale JVM-procese (cu setări specifice ale acestora, de exemplu, diferite setări ale colectorului de gunoi), serviciile interacționează unele cu altele pe utilizând un protocol ușor.
pentru că produs Red Hat JBoss Siguranta se bazeaza pe Open Source Technology stiva Apache ServiceMix, la dispoziția noastră, există tehnologii puternice, cum ar fi Apache ActiveMQ (punerea în aplicare a caietului de sarcini JMS), Apache Camel (punerea în aplicare a modelelor de Enterprise Integration), Apache CXF (bibliotecă pentru REST dezvoltare / web -Servicii), Blueprint (oferă posibilitatea introducerii dependențelor), Spring, etc. Deoarece aceste tehnologii se integrează perfect între ele în Red Hat JBoss Fuse, acest lucru reduce semnificativ timpul de dezvoltare a funcționalității necesare.
Materialul a fost pregătit de experți ai Centrului pentru soluții software de la Jet Infosystems.
Dar mă întreb cum ați pus toate acestea în devmode? Sub standardul build-pack-deploy? Sau ce plug-in folosiți?
Și mi se pare că modularitatea cererii nu este în întregime fundamentată. Pe plan intern, da, are sens pentru cod și teste. Dar din punctul de vedere al jocului este mai bine să ai un singur artefact, mai degrabă decât o grămadă de dzharnikov.
Dacă este necesară modularitatea, în opinia mea, va fi mai bine să rupă aplicația în micro servicii și să începeți fiecare într-un container separat JVM / container, așa cum se întâmplă acum. Singurul scenariu care vine în minte este platforma pentru implementarea diverselor aplicații și micro-servicii cu diferite cicluri de dezvoltare. Ceva ca ESB sau AppServer. De fapt, acolo este în bază și este folosit.
Întrebarea despre ceea ce este mai bine, un container sau o grămadă de microservici - este mare și merită un articol separat. Am vrut mult timp să o scriu, dar necesită încă reflecție.
În cazul meu, aceasta nu este o aplicație, ci un set de module care sunt relativ independente unele de altele. Toată lumea într-un container separat? Și pentru ce? Ei bine, asta este aceasta este o întrebare retorică, deja știu de dragul a ceea ce - vreau doar să remarcăm că nu întotdeauna că pentru ceea ce se fac micile servicii, are loc în viață.
Da, sunt de acord. În acest caz, OSGi ajută cu adevărat ca o singură platformă pentru implementare, dacă există un număr mare de module mai mult sau mai puțin independente.
Eu însumi nu sunt un mare fan al containerelor și microservicii, deoarece instrumente de virtualizare destul de bune sunt deja construite în Java în sine. Containerele complică foarte mult arhitectura și demo-ul și ar trebui folosite numai acolo unde este cu adevărat necesar, și nu prin apelul de modă. De asemenea, nu are sens să se împartă în mod artificial cererea în micro servicii dacă are un singur ciclu funcțional și de dezvoltare.
Și da, este, în general, un ESB (anvelopă). Ie ciclul de dezvoltare este complet diferit, și toate împreună nu degeljatsya niciodată, mai degrabă într-o singură eliberare de 10 la suta la cel mai bun.
Ei bine, apropo, întrebarea este: care este cel mai bun mod de a intra în microserviciile? Ei bine, cu atât mai bine să nu rup, voi încerca să formulez:
* configurare centralizată (de exemplu, pentru 100 de module avem aproximativ 20 de baze de date diferite, iar în cazul microservicii ar trebui să configurez un URL / login
parola în 20 de locuri diferite de neînțeles, așa că sunt într-un singur loc.
* monitorizare centralizată (o copie a JMX și o consolă Hawtio, din care puteți vedea totul).
* instalare și administrare dintr-un singur loc
* Un set de porturi care se strecoară, pentru toate zecile de servicii web / de odihnă. Sau, mai degrabă, un port http și un https. Și încă un set de certificate într-un singur loc.
* Am alocat 16Gb tuturor serviciilor și locuiesc acolo, deoarece consumă memorie ca regulă în momente diferite și în moduri diferite. Nu faptul că acest lucru este bun, dar totuși - 100 de JVM individual ar trebui să fie parametrii reglați pentru fiecare.
> Dar din punctul de vedere al jocului este mai bine să ai un singur artefact, mai degrabă decât o grămadă de djarnikov.
Apropo, pentru karaf artifact - aceasta include caracteristica (a se vedea mai sus cu același post), cu alte cuvinte - un astfel de xml cu dependențe.
Ie karaf știe doar cum să creeze o grămadă de jaruri, interconectate unul cu celălalt. De exemplu, puteți scrie că aveți nevoie de caracteristica "spring-jms", de exemplu, care va fi instalată împreună cu modulul dvs. și trageți împreună cu dependențele tranzitorii. Ei bine, tip ca maven, numai în timpul de funcționare OSGI. Și sunt, de altfel, făcute din pom.xml cu ajutorul pluginului karaf maven, fără efort.
Deci, din punctul de vedere al defilei ... pentru karaf este complet inutil.