Introduksjon til Dubbo

1. Introduksjon

Dubbo er en åpen kildekode RPC og mikroservice ramme fra Alibaba.

Det hjelper blant annet med å forbedre tjenestestyring og gjør det mulig for en tradisjonell monolit-applikasjon å bli omformet jevnt til en skalerbar distribuert arkitektur.

I denne artikkelen vil vi gi en introduksjon til Dubbo og dens viktigste funksjoner.

2. Arkitektur

Dubbo skiller noen få roller:

  1. Leverandør - hvor tjenesten utsettes; en leverandør vil registrere tjenesten sin i registeret
  2. Container - der tjenesten startes, lastes og kjøres
  3. Forbruker - som påkaller fjerntjenester; en forbruker vil abonnere på tjenesten som trengs i registret
  4. Register - hvor tjenesten blir registrert og oppdaget
  5. Monitor - registrer statistikk for tjenester, for eksempel hyppighet av tjenesteanrop i et gitt tidsintervall

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

Forbindelsene mellom en leverandør, en forbruker og et register er vedvarende, så når en tjenesteleverandør er nede, kan registret oppdage feilen og varsle forbrukerne.

Registret og skjermen er valgfritt. Forbrukere kan koble seg direkte til tjenesteleverandører, men stabiliteten til hele systemet vil bli påvirket.

3. Maven avhengighet

Før vi dykker inn, la oss legge til følgende avhengighet til vår pom.xml:

 com.alibaba dubbo 2.5.7 

Den siste versjonen finner du her.

4. Bootstrapping

La oss nå prøve de grunnleggende funksjonene i Dubbo.

Dette er et minimalt invasivt rammeverk, og mange av funksjonene avhenger av eksterne konfigurasjoner eller merknader.

Det foreslås offisielt at vi skal bruke XML-konfigurasjonsfil fordi den avhenger av en Spring-container (for øyeblikket Spring 4.3.10).

Vi vil demonstrere de fleste funksjonene ved hjelp av XML-konfigurasjon.

4.1. Multicast-register - tjenesteleverandør

Som en rask start trenger vi bare en tjenesteleverandør, en forbruker og et "usynlig" register. Registret er usynlig fordi vi bruker et multicast-nettverk.

I det følgende eksemplet sier leverandøren bare “hei” til forbrukerne:

offentlig grensesnitt GreetingsService {String sayHi (Stringnavn); } offentlig klasse GreetingsServiceImpl implementerer GreetingsService {@Override public String sayHi (String name) {return "hei," + name; }}

For å ringe en ekstern prosedyre må forbrukeren dele et felles grensesnitt med tjenesteleverandøren, og dermed grensesnittet HilsenService må deles med forbrukeren.

4.2. Multicast-register - Tjeneregistrering

La oss nå registrere oss HilsenService til registeret. En veldig praktisk måte er å bruke et multicast-register hvis både leverandører og forbrukere er på samme lokale nettverk:

Med bønnekonfigurasjonen ovenfor har vi nettopp avslørt vår HilsenService til en url under dubbo: //127.0.0.1: 20880 og registrerte tjenesten til en multicast-adresse spesifisert i .

I leverandørens konfigurasjon erklærte vi også applikasjonsmetadata, grensesnittet for henholdsvis publisering og implementering av , og .

De dubbo protokoll er en av mange protokoller som rammeverket støtter. Den er bygget på toppen av Java NIO ikke-blokkerende funksjon, og det er standardprotokollen som brukes.

Vi vil diskutere det nærmere senere i denne artikkelen.

4.3. Multicast-register - tjenesteforbruker

Generelt sett må forbrukeren spesifisere grensesnittet som skal påkalles og adressen til ekstern tjeneste, og det er akkurat det som trengs for en forbruker:

Nå er alt satt opp, la oss se hvordan de fungerer i aksjon:

offentlig klasse MulticastRegistryTest {@Before public void initRemote () {ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext ("multicast / provider-app.xml"); remoteContext.start (); } @Test offentlig ugyldig 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 ("hei, baeldung", hiMessage); }}

Når leverandøren er remoteContext starter, lastes Dubbo automatisk HilsenService og registrer det i et gitt register. I dette tilfellet er det et multicast-register.

Forbrukeren abonnerer på multicastregistret og oppretter en fullmakt for HilsenService i konteksten. Når vår lokale klient påkaller si hei metode, er det transparent å påkalle en ekstern tjeneste.

Vi nevnte at registeret er valgfritt, noe som betyr at forbrukeren kan koble seg direkte til leverandøren via den eksponerte porten:

I utgangspunktet ligner prosedyren tradisjonell webtjeneste, men Dubbo gjør den bare enkel, enkel og lett.

4.4. Enkelt register

Merk at når du bruker et "usynlig" multicast-register, er registertjenesten ikke frittstående. Det gjelder imidlertid bare for et begrenset lokalt nettverk.

For å eksplisitt sette opp et håndterbart register, kan vi bruke en SimpleRegistryService.

Etter å ha lastet inn følgende bønnekonfigurasjon i vårkontekst, startes en enkel registertjeneste:

Merk at SimpleRegistryService klasse er ikke inneholdt i artefakten, så vi kopierte kildekoden direkte fra Github-depotet.

Deretter skal vi justere registerkonfigurasjonen til leverandøren og forbrukeren:

SimpleRegistryService kan brukes som et frittstående register ved testing, men det anbefales ikke å brukes i produksjonsmiljø.

4.5. Java-konfigurasjon

Konfigurasjon via Java API, eiendomsfil og merknader støttes også. Egenskapsfiler og merknader gjelder imidlertid bare hvis arkitekturen vår ikke er veldig kompleks.

La oss se hvordan våre tidligere XML-konfigurasjoner for multicast-register kan oversettes til API-konfigurasjon. Først er leverandøren satt opp som følger:

ApplicationConfig-applikasjon = ny ApplicationConfig (); application.setName ("demo-leverandør"); application.setVersion ("1.0"); RegistryConfig registryConfig = ny RegistryConfig (); registryConfig.setAddress ("multicast: //224.1.1.1: 9090"); ServiceConfig service = ny ServiceConfig (); service.setApplication (applikasjon); service.setRegistry (registryConfig); service.setInterface (GreetingsService.class); service.setRef (ny GreetingsServiceImpl ()); service.export ();

Nå som tjenesten allerede er eksponert via multicast-registeret, la oss konsumere den i en lokal klient:

ApplicationConfig-applikasjon = ny ApplicationConfig (); application.setName ("demo-forbruker"); application.setVersion ("1.0"); RegistryConfig registryConfig = ny RegistryConfig (); registryConfig.setAddress ("multicast: //224.1.1.1: 9090"); ReferenceConfig referanse = ny ReferenceConfig (); reference.setApplication (applikasjon); reference.setRegistry (registryConfig); reference.setInterface (GreetingsService.class); GreetingsService greetingsService = reference.get (); String hiMessage = greetingsService.sayHi ("baeldung");

Selv om utdraget ovenfor fungerer som en sjarm som det forrige XML-konfigurasjonseksemplet, er det litt mer trivielt. Foreløpig bør XML-konfigurasjon være førstevalget hvis vi har tenkt å gjøre full bruk av Dubbo.

5. Protokollstøtte

Rammeverket støtter flere protokoller, inkludert dubbo, RMI, hessian, HTTP, nettjeneste, sparsommelighet, memcached og redis. De fleste protokollene ser kjent ut, bortsett fra dubbo. La oss se hva som er nytt i denne protokollen.

De dubbo protokollen holder en vedvarende forbindelse mellom leverandører og forbrukere. Den lange forbindelsen og NIO-ikke-blokkerende nettverkskommunikasjon resulterer i en ganske god ytelse mens du overfører småskala datapakker (<100K).

Det er flere konfigurerbare egenskaper, for eksempel port, antall tilkoblinger per forbruker, maksimalt aksepterte tilkoblinger, etc.

Dubbo støtter også eksponering av tjenester via forskjellige protokoller samtidig:

Og ja, vi kan eksponere forskjellige tjenester ved hjelp av forskjellige protokoller, som vist i utdraget ovenfor. De underliggende transportørene, serialiseringsimplementeringene og andre vanlige egenskaper knyttet til nettverk kan også konfigureres.

6. Resultat caching

Nativt ekstern resultatbufring støttes for å få raskere tilgang til varme data. Det er så enkelt som å legge til et cache-attributt til bønnereferansen:

Her konfigurerte vi en hurtigbuffer som nylig ble brukt. For å bekrefte caching-oppførselen, vil vi endre litt i forrige standardimplementering (la oss kalle det "spesiell implementering"):

offentlig klasse GreetingsServiceSpecialImpl implementerer GreetingsService {@Override public String sayHi (String name) {prøv {SECONDS.sleep (5); } fange (Unntak ignorert) {} returner "hei", + navn; }}

Etter at vi har startet leverandøren, kan vi verifisere på forbrukerens side at resultatet blir hurtigbufret når vi påkaller flere ganger:

@Test offentlig ugyldig givenProvider_whenConsumerSaysHi_thenGotResponse () {ClassPathXmlApplicationContext localContext = ny ClassPathXmlApplicationContext ("multicast / consumer-app.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); lenge før = System.currentTimeMillis (); String hiMessage = greetingsService.sayHi ("baeldung"); long timeElapsed = System.currentTimeMillis () - før; assertTrue (timeElapsed> 5000); assertNotNull (hiMessage); assertEquals ("hei, baeldung", hiMessage); før = System.currentTimeMillis (); hiMessage = greetingsService.sayHi ("baeldung"); timeElapsed = System.currentTimeMillis () - før; assertTrue (timeElapsed <1000); assertNotNull (hiMessage); assertEquals ("hei, baeldung", hiMessage); }

Her påkaller forbrukeren den spesielle tjenesteimplementeringen, så det tok mer enn 5 sekunder for påkallelsen å fullføre første gang. Når vi påkaller igjen, si hei metoden fullføres nesten umiddelbart, ettersom resultatet returneres fra hurtigbufferen.

Merk at tråd-lokal hurtigbuffer og JCache også støttes.

7. Klyngestøtte

Dubbo hjelper oss å oppskalere tjenestene våre fritt med sin evne til lastbalansering og flere feiltoleransestrategier. La oss anta at vi har Zookeeper som register for å administrere tjenester i en klynge. Leverandører kan registrere sine tjenester i Zookeeper slik:

Merk at vi trenger disse ekstra avhengighetene i POM:

 org.apache.zookeeper dyrehage 3.4.11 com.101tec zkclient 0.10 

De siste versjonene av dyrepasser avhengighet og zkclient finner du her og her.

7.1. Lastbalansering

Foreløpig støtter rammeverket noen få balanseringsstrategier:

  • tilfeldig
  • round-robin
  • minst aktiv
  • konsekvent hasj.

I det følgende eksemplet har vi to tjenesteimplementeringer som leverandører i en klynge. Forespørslene rutes ved hjelp av round-robin-tilnærmingen.

La oss først sette opp tjenesteleverandører:

@Før offentlig ugyldig 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 ();}); }

Nå har vi en standard "rask leverandør" som reagerer umiddelbart, og en spesiell "treg leverandør" som sover i 5 sekunder på hver forespørsel.

Etter å ha kjørt 6 ganger med round-robin-strategien, forventer vi at den gjennomsnittlige responstiden er minst 2,5 sekunder:

@Test offentlig ugyldighet gittProviderCluster_whenConsumerSaysHi_thenResponseBalanced () {ClassPathXmlApplicationContext localContext = ny ClassPathXmlApplicationContext ("klynge / forbruker-app-lb.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); List elapseList = new ArrayList (6); for (int i = 0; i e). gjennomsnitt (); assertTrue (avgElapse.isPresent ()); assertTrue (avgElapse.getAsDouble ()> 2500.0); }

Videre er dynamisk lastbalansering vedtatt. Det neste eksemplet viser at forbrukeren automatisk velger den nye tjenesteleverandøren som kandidat når den nye leverandøren kommer online, med rund-robin-strategi.

Den "langsomme leverandøren" blir registrert to sekunder senere etter at systemet starter:

@Før offentlig ugyldig 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;}); }

Forbrukeren påkaller fjerntjenesten en gang i sekundet. Etter å ha kjørt 6 ganger, forventer vi at den gjennomsnittlige responstiden vil være større enn 1,6 sekunder:

@Test offentlig ugyldighet givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced () kaster InterruptedException {ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext ("cluster / consumer-app-lb.xml"); localContext.start (); GreetingsService greetingsService = (GreetingsService) localContext.getBean ("greetingsService"); Liste elapseList = ny ArrayList (6); for (int i = 0; i e). gjennomsnitt (); assertTrue (avgElapse.isPresent ()); assertTrue (avgElapse.getAsDouble ()> 1666.0); }

Legg merke til at lastbalanseren kan konfigureres både på forbrukerens side og på leverandørens side. Her er et eksempel på konfigurasjon på forbrukersiden:

7.2. Feiltoleranse

Flere feiltoleransestrategier støttes i Dubbo, inkludert:

  • fail-over
  • feilsikker
  • mislykkes raskt
  • fail-back
  • gaffel.

I tilfelle fail-over, når en leverandør mislykkes, kan forbrukeren prøve med noen andre tjenesteleverandører i klyngen.

Feiltoleransestrategiene er konfigurert slik for tjenesteleverandører:

For å demonstrere tjenestefeil i aksjon, la oss lage en fail-over-implementering av HilsenService:

offentlig klasse GreetingsFailoverServiceImpl implementerer GreetingsService {@Override public String sayHi (String name) {return "hei, failover" + navn; }}

Vi kan huske at vår spesielle tjenesteimplementering HilsenServiceSpesialImpl sover 5 sekunder for hver forespørsel.

Når ethvert svar som tar mer enn 2 sekunder blir sett på som en forespørselsfeil for forbrukeren, har vi et fail-over-scenario:

Etter å ha startet to leverandører, kan vi bekrefte feilsøkingsatferden med følgende kodebit:

@Test offentlig ugyldig nårConsumerSaysHi_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 ("hei, failover baeldung", hiMessage); }

8. Oppsummering

I denne opplæringen tok vi en liten bit av Dubbo. De fleste brukere tiltrekkes av sin enkelhet og rike og kraftige funksjoner.

Bortsett fra det vi introduserte i denne artikkelen, har rammeverket en rekke funksjoner som ennå ikke skal utforskes, for eksempel parametervalidering, varsling og tilbakeringing, generalisert implementering og referanse, ekstern resultatgruppering og sammenslåing, tjenesteoppgradering og bakoverkompatibilitet, for å bare nevne Noen.

Som alltid kan den fullstendige implementeringen finnes på Github.


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