Uvod u Dubbo

1. Uvod

Dubbo je RPC i mikroservisni okvir otvorenog koda iz Alibabe.

Između ostalog, pomaže poboljšati upravljanje uslugama i omogućuje da se tradicionalni monolitni programi glatko prepravljaju u skalabilnu distribuiranu arhitekturu.

U ovom ćemo članku predstaviti Dubbo i njegove najvažnije značajke.

2. Arhitektura

Dubbo razlikuje nekoliko uloga:

  1. Pružatelj - tamo gdje je usluga izložena; davatelj će svoju uslugu registrirati u registru
  2. Spremnik - gdje se usluga pokreće, učitava i pokreće
  3. Potrošač - koji se poziva na daljinske usluge; potrošač će se pretplatiti na uslugu potrebnu u registru
  4. Registar - gdje će usluga biti registrirana i otkrivena
  5. Monitor - bilježi statistiku usluga, na primjer, učestalost poziva usluge u određenom vremenskom intervalu

(izvor: //dubbo.io/images/dubbo-architecture.png)

Veze između davatelja usluge, potrošača i registra trajne su, pa kad god davatelj usluga ne radi, registar može otkriti kvar i obavijestiti potrošače.

Registar i monitor nisu obavezni. Potrošači bi se mogli izravno povezati s pružateljima usluga, ali to bi utjecalo na stabilnost cijelog sustava.

3. Ovisnost Mavena

Prije nego što zaronimo, dodajmo sljedeću ovisnost našoj pom.xml:

 com.alibaba dubbo 2.5.7 

Najnoviju verziju možete pronaći ovdje.

4. Bootstrapping

Ajmo sada isprobati osnovne značajke Dubba.

Ovo je minimalno invazivni okvir, a mnoštvo njegovih značajki ovisi o vanjskim konfiguracijama ili napomenama.

Službeno se sugerira da bismo trebali koristiti XML konfiguracijsku datoteku jer to ovisi o Spring spremniku (trenutno Spring 4.3.10).

Većinu njegovih značajki demonstrirat ćemo pomoću XML konfiguracije.

4.1. Multikast registar - davatelj usluga

Kao brzi početak trebat će nam samo davatelj usluga, potrošač i "nevidljivi" registar. Registar je nevidljiv jer koristimo multicast mrežu.

U sljedećem primjeru davatelj usluga samo kaže "zdravo" svojim potrošačima:

javno sučelje GreetingsService {String sayHi (naziv niza); } javna klasa GreetingsServiceImpl implementira GreetingsService {@Override javni niz sayHi (naziv niza) {return "hi," + name; }}

Da bi uputio poziv na daljinu, potrošač mora dijeliti zajedničko sučelje s davateljem usluga, dakle sučelje PozdravService mora se podijeliti s potrošačem.

4.2. Multikast registar - registracija usluge

Registrirajmo se sada PozdravService u registar. Vrlo prikladan način je korištenje multicast registra ako su i davatelji i potrošači na istoj lokalnoj mreži:

S gornjom konfiguracijom graha, upravo smo izložili svoj PozdravService na url ispod dubbo: //127.0.0.1: 20880 i registrirali uslugu na multicast adresu navedenu u .

U konfiguraciji davatelja usluga također smo proglasili metapodatke svoje aplikacije, sučelje za objavljivanje, odnosno do , i .

The dubbo protokol je jedan od mnogih protokola koje okvir podržava. Izgrađen je na vrhu mogućnosti blokiranja Java NIO i to je zadani protokol koji se koristi.

O tome ćemo detaljnije razgovarati kasnije u ovom članku.

4.3. Multikast registar - potrošač usluge

Općenito, potrošač mora navesti sučelje za pozivanje i adresu udaljene usluge, a to je upravo ono što je potrebno za potrošača:

Sad je sve postavljeno, pogledajmo kako oni djeluju na djelu:

javna klasa MulticastRegistryTest {@Before public void initRemote () {ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext ("multicast / provider-app.xml"); remoteContext.start (); } @Test javna praznina givenProvider_whenConsumerSaysHi_thenGotResponse () {ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext ("multicast / consumer-app.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); String hiMessage = greetingsService.sayHi ("baeldung"); assertNotNull (hiMessage); assertEquals ("hi, baeldung", hiMessage); }}

Kad davateljev remoteContext započne, Dubbo će se automatski učitati PozdravService i registrirajte ga u određeni registar. U ovom se slučaju radi o registru za višestruko slanje.

Potrošač se pretplaćuje na registar za višestruko slanje i stvara proxy za PozdravService u kontekstu. Kada se naš lokalni klijent poziva na pozdraviti metoda, to je transparentno pozivanje udaljene usluge.

Spomenuli smo da je registracija neobavezna, što znači da se potrošač mogao izravno povezati s davateljem putem izložene luke:

U osnovi je postupak sličan tradicionalnom web servisu, ali Dubbo ga čini jednostavnim, jednostavnim i laganim.

4.4. Jednostavan registar

Imajte na umu da kada koristite "nevidljivi" multicast registar, usluga registra nije samostalna. Međutim, primjenjivo je samo na ograničenu lokalnu mrežu.

Da bismo izričito postavili upravljivi registar, možemo koristiti SimpleRegistryService.

Nakon učitavanja sljedeće konfiguracije graha u Spring kontekst, pokreće se jednostavna usluga registra:

Imajte na umu da SimpleRegistryService klasa nije sadržana u artefaktu, pa smo kopirali izvorni kod izravno iz spremišta Github.

Zatim ćemo prilagoditi konfiguraciju registra davatelja i potrošača:

SimpleRegistryService može se koristiti kao samostalni registar prilikom testiranja, ali se ne preporučuje koristiti u proizvodnom okruženju.

4.5. Java konfiguracija

Podržana je i konfiguracija putem Java API-ja, datoteke svojstava i bilješki. Međutim, datoteka svojstava i bilješke primjenjive su samo ako naša arhitektura nije vrlo složena.

Pogledajmo kako se naše prethodne XML konfiguracije za multicast registar mogu prevesti u API konfiguraciju. Prvo, davatelj se postavlja na sljedeći način:

ApplicationConfig aplikacija = nova ApplicationConfig (); application.setName ("demo-usluga"); application.setVersion ("1.0"); RegistryConfig registryConfig = novi RegistryConfig (); registryConfig.setAddress ("multicast: //224.1.1.1: 9090"); ServiceConfig usluga = nova ServiceConfig (); service.setApplication (aplikacija); service.setRegistry (registryConfig); service.setInterface (GreetingsService.class); service.setRef (novi GreetingsServiceImpl ()); service.export ();

Sad kad je usluga već izložena putem registra višestrukog slanja, konzumirajmo je u lokalnom klijentu:

ApplicationConfig aplikacija = nova ApplicationConfig (); application.setName ("demo-potrošač"); application.setVersion ("1.0"); RegistryConfig registryConfig = novi RegistryConfig (); registryConfig.setAddress ("multicast: //224.1.1.1: 9090"); ReferenceConfig referenca = nova ReferenceConfig (); reference.setApplication (aplikacija); reference.setRegistry (registryConfig); reference.setInterface (GreetingsService.class); GreetingsService greetingsService = reference.get (); String hiMessage = greetingsService.sayHi ("baeldung");

Iako gornji isječak djeluje poput šarma kao prethodni primjer XML konfiguracije, malo je trivijalniji. Zasad bi XML konfiguracija trebala biti prvi izbor ako namjeravamo u potpunosti iskoristiti Dubbo.

5. Podrška protokola

Okvir podržava više protokola, uključujući dubbo, RMI, najamnik, HTTP, web usluga, štedljivost, memcached i redis. Većina protokola izgleda poznato, osim dubbo. Pogledajmo što je novo u ovom protokolu.

The dubbo protokol održava trajnu vezu između pružatelja i potrošača. Duga veza i NIO neblokirajuća mrežna komunikacija rezultiraju prilično velikim performansama tijekom prijenosa malih paketa podataka (<100K).

Postoji nekoliko konfigurabilnih svojstava, poput priključka, broja veza po potrošaču, maksimalno prihvaćenih veza itd.

Dubbo također podržava izlaganje usluga putem različitih protokola odjednom:

I da, možemo izložiti različite usluge koristeći različite protokole, kao što je prikazano u gornjem isječku. Osnovni transporteri, implementacije serializacije i druga uobičajena svojstva koja se odnose na umrežavanje također se mogu konfigurirati.

6. Keširanje rezultata

Podržano je izvorno predmemoriranje rezultata kako bi se ubrzao pristup vrućim podacima. Jednostavno je kao dodati atribut predmemorije referenci graha:

Ovdje smo konfigurirali najmanje korištenu predmemoriju. Da bismo provjerili ponašanje predmemoriranja, malo ćemo promijeniti u prethodnoj standardnoj implementaciji (nazovimo je "posebna implementacija"):

javna klasa GreetingsServiceSpecialImpl implementira GreetingsService {@Preuzmi javni niz sayHi (naziv niza) {try {SECONDS.sleep (5); } catch (iznimka se zanemaruje) {} return "hi," + ime; }}

Nakon pokretanja davatelja usluge možemo provjeriti na strani potrošača da li se rezultat kešira kod pozivanja više puta:

@Test javna praznina givenProvider_whenConsumerSaysHi_thenGotResponse () {ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext ("multicast / consumer-app.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); puno prije = System.currentTimeMillis (); String hiMessage = greetingsService.sayHi ("baeldung"); long timeElapsed = System.currentTimeMillis () - prije; assertTrue (timeElapsed> 5000); assertNotNull (hiMessage); assertEquals ("hi, baeldung", hiMessage); prije = System.currentTimeMillis (); hiMessage = greetingsService.sayHi ("baeldung"); timeElapsed = System.currentTimeMillis () - prije; assertTrue (timeElapsed <1000); assertNotNull (hiMessage); assertEquals ("hi, baeldung", hiMessage); }

Ovdje se potrošač poziva na implementaciju posebne usluge, pa je trebalo više od 5 sekundi da se poziv prvi put dovrši. Kad se ponovno zazovemo, pozdraviti metoda dovršava se gotovo odmah, jer se rezultat vraća iz predmemorije.

Imajte na umu da su podržani i lokalna predmemorija niti i JCache.

7. Podrška klastera

Dubbo nam pomaže da slobodno povećamo svoje usluge svojom sposobnošću uravnoteženja tereta i nekoliko strategija tolerancije kvarova. Evo, pretpostavimo da imamo Zookeeper kao naš registar za upravljanje uslugama u klasteru. Pružatelji usluga mogu registrirati svoje usluge u Zookeeper-u ovako:

Imajte na umu da su nam ove dodatne ovisnosti potrebne u POM:

 org.apache.zookeeper čuvar zoološkog vrta 3.4.11 com.101tec zkclient 0.10 

Najnovije verzije čuvar zoo vrta ovisnost i zkclient možete pronaći ovdje i ovdje.

7.1. Uravnoteženje opterećenja

Trenutno okvir podržava nekoliko strategija uravnoteženja opterećenja:

  • slučajno
  • kolobarnica
  • najmanje aktivan
  • konzistentno-hash.

U sljedećem primjeru imamo dvije implementacije usluga kao pružatelje usluga u klasteru. Zahtjevi se usmjeravaju koristeći okrugli pristup.

Prvo, postavimo davatelje usluga:

@Before public void initRemote () {ExecutorService executorService = Executors.newFixedThreadPool (2); executorService.submit (() -> {ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext ("cluster / provider-app-default.xml"); remoteContext.start ();}); executorService.submit (() -> {ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext ("cluster / provider-app-special.xml"); backupRemoteContext.start ();}); }

Sada imamo standardnog "brzog davatelja usluga" koji reagira odmah i posebnog "sporog davatelja usluga" koji na svaki zahtjev spava 5 sekundi.

Nakon što smo šest puta trčali sa strategijom zaokruživanja, očekujemo da će prosječno vrijeme odziva biti najmanje 2,5 sekunde:

@Test javna praznina givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced () {ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext ("cluster / consumer-app-lb.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); Popis elapseList = novi ArrayList (6); for (int i = 0; i e) .average (); assertTrue (avgElapse.isPresent ()); assertTrue (avgElapse.getAsDouble ()> 2500,0); }

Štoviše, prihvaćeno je dinamičko uravnoteženje opterećenja. Sljedeći primjer pokazuje da, sa strategijom zaokruživanja, potrošač automatski bira novog davatelja usluga kao kandidata kada novi davatelj stupi na mrežu.

"Spori pružatelj usluga" registriran je dvije sekunde kasnije nakon pokretanja sustava:

@Before public void initRemote () {ExecutorService executorService = Executors.newFixedThreadPool (2); executorService.submit (() -> {ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext ("cluster / provider-app-default.xml"); remoteContext.start ();}); executorService.submit (() -> {SECONDS.sleep (2); ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext ("cluster / provider-app-special.xml"); backupRemoteContext.start (); return null;} }

Potrošač se poziva na daljinsku uslugu jednom u sekundi. Nakon izvođenja 6 puta, očekujemo da će prosječno vrijeme odziva biti veće od 1,6 sekundi:

@Test javna praznina givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced () baca InterruptedException {ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext ("cluster / consumer-app-lb.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); Popis elapseList = novi ArrayList (6); for (int i = 0; i e) .average (); assertTrue (avgElapse.isPresent ()); assertTrue (avgElapse.getAsDouble ()> 1666,0); }

Imajte na umu da se uravnoteživač tereta može konfigurirati i na strani potrošača i na strani davatelja usluge. Evo primjera konfiguracije na strani potrošača:

7.2. Tolerancija kvarova

U Dubbo-u je podržano nekoliko strategija tolerancije kvarova, uključujući:

  • neuspjeh
  • siguran u kvaru
  • neuspješan
  • neuspjeh
  • račvanje.

U slučaju kvara, kada jedan davatelj ne uspije, potrošač može pokušati s nekim drugim davateljima usluga u klasteru.

Strategije tolerancije kvarova konfigurirane su na sljedeći način za davatelje usluga:

Da bismo demonstrirali neuspjeh usluge na djelu, kreirajmo implementaciju neuspjeha PozdravService:

javna klasa GreetingsFailoverServiceImpl implementira GreetingsService {@Preuzmi javni niz sayHi (naziv niza) {return "hi, failover" + name; }}

Možemo se prisjetiti da je naša posebna usluga implementirana GreetingsServiceSpecialImpl spava 5 sekundi za svaki zahtjev.

Kada se bilo koji odgovor koji traje duže od 2 sekunde smatra neuspjehom zahtjeva za potrošača, imamo scenarij prebacivanja:

Nakon pokretanja dva pružatelja usluga, ponašanje sljedećeg isječka možemo provjeriti sljedećim isječkom:

@Test javna praznina whenConsumerSaysHi_thenGotFailoverResponse () {ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext ("cluster / consumer-app-failtest.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); String hiMessage = greetingsService.sayHi ("baeldung"); assertNotNull (hiMessage); assertEquals ("hi, failover baeldung", hiMessage); }

8. Sažetak

U ovom uputstvu zagrizli smo Dubbo. Većinu korisnika privlači jednostavnost te bogate i moćne značajke.

Osim onoga što smo uveli u ovaj članak, okvir ima niz značajki koje tek treba istražiti, kao što su provjera valjanosti parametara, obavijesti i povratni pozivi, generalizirana implementacija i reference, daljinsko grupiranje i spajanje rezultata, nadogradnja usluge i povratna kompatibilnost. nekoliko.

Kao i uvijek, cjelovitu implementaciju možete pronaći na Githubu.


$config[zx-auto] not found$config[zx-overlay] not found