Programmering

Skriv din egen MOM!

MAMMA blir misforstått, og MAMMA får ingen kreditt. Du har kanskje hørt denne før, men i arenaen for distribuerte systemer er det faktisk sant! Dette er fordi meldingsorientert mellomvare (MOM) tradisjonelt ikke har hatt samme raffinement og støtte som andre teknologier som brukes i distribuerte kommunikasjonsrammer.

Men tidene endrer seg. Med introduksjonen av sofistikerte, robuste leverandørtilbud, øker interessen for MOM-systemer raskt. Gode ​​MOM-implementeringer gir et applikasjonsgrensesnitt på høyt nivå, servicekvalitetsgarantier og en rekke tjenester som sikkerhet, meldingskø og katalogstøtte som er nødvendig for "industriell styrke" distribuert kommunikasjon.

Distribuerte kommunikasjonsrammer

Hensikten med et distribuert kommunikasjonsrammeverk er å gi en god måte for delene av et distribuert system å kommunisere på. Objektorienterte rammer utfører denne oppgaven ved å gi distribuerte objekter en måte å sende meldinger til hverandre.

De distribuerte objektorienterte rammene som får mest oppmerksomhet er de som modellerer meldinger som metodekaller. CORBA og RMI er to gode eksempler på denne typen rammeverk (se Ressurser). Disse systemene kalles ofte RPC-systemer (Remote Procedure Call). Magien til disse systemene er at de gjør at anrop for eksterne prosedyrer (eller metode) ser ut til å være lokale prosedyreanrop (LPC).

RPC er arkivert på klient / server mønster. For eksempel kalles CORBA-objekter som eksponerer metoder som skal kalles av eksterne objekter (og er) servere.

Vi presenterer MOM

I motsetning til RPC-er, modellerer MOM-er ikke meldinger som metodeanrop; i stedet modellerer de dem som hendelser i et system for levering av hendelser. Klienter sender og mottar hendelser eller "meldinger" via API-er som MOM gir. MOM kan presentere katalogtjenester som lar klienter slå opp et annet program som fungerer som en server, eller det kan presentere allsidige "kanaler" som lar en gruppe klienter kommunisere som jevnaldrende, eller det kan presentere begge alternativene.

Alle applikasjoner kommuniserer direkte med hverandre ved hjelp av MOM. Meldinger generert av applikasjoner er meningsfylte bare for andre klienter fordi MOM i seg selv bare er en meldingsruter (og i noen tilfeller også et meldings-køsystem).

MOMS kommer i alle fasonger og størrelser

Alle MOM-er deler to grunnleggende egenskaper: de muliggjør overføring av meldinger og overføring av meldinger er ikke-blokkerende. Utover disse grunnleggende kan leverandører implementere et hvilket som helst antall forskjellige grensesnitt og tjenester.

Mange MOM-er tilbyr et publiser-og-abonner-grensesnitt som gjør det mulig for applikasjoner å publisere og motta meldinger de er interessert i. Dette grensesnittet kan ha form av et kanalbasert system eller et enklere system der en klient registrerer typer meldinger den er interessert i å motta.

Grunnleggende MOMS gir bare direkte meldinger, ingen tilleggstjenester. Avanserte MOMS gir meldingskø og garantert levering, sammen med sikkerhet, dataovervåking på tvers av plattformer, skalerbarhet og andre fordeler.

MOMS på et øyeblikk

Her er en rask referanse for å hjelpe deg med å håndtere hva MOMS handler om.

MOM fordeler

  • Enkel: Kunder publiserer og abonnerer

    publiser og abonner er en nyttig abstraksjon på høyt nivå for hva apper trenger å gjøre for å kommunisere.

  • Lett: Ingen kompliserte oppsett kreves

    MOM er enkle å installere og bruke, i motsetning til komplekse RPC-baserte systemer som CORBA.

  • Generisk: Den samme MOM kan brukes til flere apper

    Fordi ethvert gitt MOM-system egentlig bare er en generisk meldingstransport, kan det brukes på nytt i forskjellige applikasjoner uten noe ekstra arbeid.

  • Fleksibel: Alle slags meldinger kan sendes

    Enhver melding kan sendes av MAMMA. Fordi MOM ikke forstår meldingene, spiller det ingen rolle hva de er.

MAMMA ulemper

  • Generisk: Programmer må forstå meldinger

    Å få applikasjoner til å bruke meldinger i stedet for metodesamtaler kan være vanskelig, spesielt hvis applikasjonen er avhengig av det faktum at metoden anrop blokkerer.

  • Ukjent: Modellerer ikke metodeanrop

    Utviklere som ikke er kjent med meldinger, kan ha problemer med å finne ut hvordan de kan brukes effektivt.

  • Asynkron: Meldinger blokkeres ikke

    Meldinger blokkeres naturlig. Dette gjør det vanskeligere å skrive apper som trenger blokkering av samtaler.

  • For lett: Ingen dataovervåking

    Selv enkle RPC-systemer samler data riktig. Enkle MOMS kan bare sende meldinger der byte er ute av drift fra mottakerens synspunkt.

  • Ikke-standard: Leverandører er over hele linja

    Leverandør MOM-implementeringer gjør alt ... og ingenting.

    Advarsel Tom

    er uttrykket du må huske på når du vurderer de ulike leverandørtilbudene.

Når er mammaer passende?

  • Når du kommuniserer, må apper bruke meldinger
  • Når programmeringspersonale ikke er koblet til klient / server og RPC-systemer
  • Når CORBA / RMI og relaterte systemer er for kompliserte
  • Når enkle RPC-systemer er for rudimentære

Designhensyn for mammaen vår

Nå som bakgrunnen er ute av veien, la oss begynne å sette sammen mammaen vår Meldingsbuss. Vi bruker MOM for å muliggjøre kommunikasjon mellom distribuerte tavleklienter. (Se Ressurser for lenker til informasjon om tavleprogrammet vi har jobbet med de siste delene.)

Det drivende hensynet til Message Bus er at det gir et praktisk høyt nivå kommunikasjonsgrensesnitt til applikasjonsobjektene som skal bruke det.

Fordi en kanal er fornuftig som den sentrale tjenesten som Message Bus skal tilby, er grensesnittet til Message Bus den Kanal klasse. Klienten bruker Kanal klasse for å få tilgang til alle høynivåfunksjoner i meldingsbussen, fra abonnement og publisering til oppføring av tilgjengelige kanaler i systemet.

De Kanal klasse avslører klassemetoder som påvirker Message Bus som helhet, eller som gjelder alle kanaler. Hver kanalforekomst representerer en enkelt kanal i systemet og avslører kanalspesifikke metoder.

To grensesnitt, ChannelListener og ChannelsUpdateListener, tilveiebringes for å abonnere på mottak av meldinger på en kanal og motta varsel om henholdsvis kanaltilsetning.

Bildet nedenfor illustrerer Message Bus-systemarkitekturen.

Under panseret

Under panseret bruker Message Bus-applikasjonen klassemetoder og datastrukturer av

Kanal

for å holde oversikt over kanaler. Lyttere til en kanal implementerer

ChannelListener

grensesnitt, og objekter som ønsker å motta oppdateringer om kanal legger til implementerer

ChannelsUpdateListener

grensesnitt. Registrerte lytterobjekter blir ringt tilbake av

Kanal

når det skjer noe interessant. All kommunikasjon med omverdenen skjer med en transportspesifikk implementering av

MessageBus

grensesnitt, for eksempel

MessageBusSocketImpl

.

Hver MessageBus implementering sender meldinger ved å snakke med en tilsvarende server for sending av meldinger, kalt megler, over en delt nettverkstransport som stikkontakter eller URL / servlets. Megleren ruter meldinger blant MessageBus tilfeller, som hver tilsvarer a Kanal klasse.

Fordi disse transportspesifikke implementeringene alle implementerer MessageBus grensesnitt, er de utskiftbare. For eksempel en servletbasert MessageBus og megler kan brukes av Kanal i stedet for stikkontakter MessageBus og megler.

Vår Message Bus er et enkelt peer-to-peer-system basert på kanaler, noe som gjør det egnet for bruk i et peer-to-peer-program, for eksempel et samarbeidssystem.

Bruke Message Bus i et klientprogram

Disse trinnene lar en klient bruke meldingsbussen:

  1. Sett opp en forekomst av MessageBus.

     Channel.setMessageBus (ny MessageBusSocketImpl (BROKER_NAME, BROKER_PORT)); 

    I denne samtalen, en ny MessageBus implementering opprettes, med megleren identifisert av argumentene til konstruktøranropet.

  2. Abonner på en kanal.

     Channel textChannel = Channel.subscribe ("text_channel", dette); 

    Denne samtalen returnerer en forekomst av kanalen som tilsvarer kanalnavnargumentet. Hvis kanalen ikke eksisterer, opprettes den i systemet.

    Passering dette som argument betyr at den innringeren selv er a ChannelListener. Innringeren kan abonnere ikke bare seg selv, men hvilken som helst ChannelListener til kanalen, eller et hvilket som helst antall lyttere til en enkelt kanal.

  3. Publiser en melding til kanalen.

     textChannel.publish (ny streng (myID + "sier hei!")); 

    Å publisere en melding er enkelt og innebærer ingenting mer enn å ringe publisere() på den valgte kanalinstansen. Merk at meldingen kan være hvilken som helst type objekt, så lenge andre klienter på kanalen kan forstå den, og serveren har tilgang til meldingsklassefilen (e) (som beskrevet i avsnittet Bruke meldingsbussen)

Ytterligere valgfrie trinn inkluderer:

  • Avmeld en lytter fra en kanal.

     textChannel.unsubscribe (ChannelListener); 

    Denne metoden avslutter abonnementet ChannelListener fra kanalen, noe som betyr at lytteren ikke mottar noen nye meldinger. Lyttere bør avslutte abonnementet på denne måten når de ikke lenger er nødvendige.

  • Få en oversikt over kanalnavn.

     Enumeration Channel.getChannelNames (); 

    Denne metoden returnerer navnene på alle kanalene som er tilgjengelige i meldingsbussen.

  • Abonner for å motta nylig lagt til kanaler.

     Channel.subscribeChannelsUpdate (ChannelsUpdateListener); 

    EN ChannelsUpdateListener kan abonnere for å få oppdateringer når kanaler legges til Message Bus.

  • Slutt å motta nylig lagt til kanaler.

     Channel.unsubscribeChannelsUpdate (ChannelsUpdateListener); 

    EN ChannelsUpdateListener kan avmeldes for oppdateringer av kanaltillegg. Lyttere bør avslutte abonnementet på denne måten når de ikke lenger er nødvendige.

  • Legg til flere lyttere til en kanal.

     textChannel.subscribe (ChannelListener); 

    Denne metoden lar den som ringer abonnere på flere lyttere til en kanal.

     String textChannel.getName (); 

    Denne metoden returnerer navnet på denne kanalforekomsten.

Grensesnitt ChannelListener

De ChannelListener grensesnittet må implementeres av ethvert objekt som ønsker å bli oppdatert når en melding kommer inn på en bestemt kanal.

offentlig grensesnitt ChannelListener {public void messageReceived (Channel channel, Object message); } 

I de fleste tilfeller kan en klient som ber om en Kanal instans vil abonnere på kanalen og implementere dette grensesnittet selv, men det er ikke nødvendig. I samsvar med JDK 1.1 hendelsesadaptere, kan en klient abonnere på et annet objekt på en kanal slik at den vil konsumere meldinger generert av kanalen.

Faktisk kan et enkelt lytterobjekt abonnere på flere kanaler, som vil ringe lytteren beskjed mottatt() hver gang en melding kommer inn på noen av kanalene. De beskjed mottatt () metodeanrop gir tilgang til kanalen der meldingen dukket opp, slik at beskjed mottatt () for å skille meldinger med opprinnelig kanal.

Grensesnitt ChannelsUpdateListener

ChannelsUpdateListener må implementeres av ethvert objekt som ønsker å bli oppdatert når en kanal er lagt til.

offentlig grensesnitt ChannelsUpdateListener {public void channelAdded (String name); } 

Klasse Kanal

De Kanal klassen tjener to formål:

  • Det gir en enkel abstraksjon som et grensesnitt til klienten ved hjelp av Message Bus
  • Det opprettholder global tilstand om tilgjengelige kanaler og overfører meldinger fra kanaler til MessageBus implementering og mottar oppdateringer fra MessageBus gjennomføring

Kanal forekomster blir opprettet og lagret av Kanalstatisk kode. Henvisninger til dem sendes ut av Channel.subscribe () som forespurt av klienten. Hver Kanal forekomst er unik i JVM-prosessen.

offentlig klassekanal {

beskyttet statisk boolsk busSet = false; beskyttet statisk MessageBus-buss; beskyttede statiske Hashtable-kanaler = nye Hashtable (); beskyttede statiske vektorkanalerUpdateListeners = ny vektor ();

offentlig statisk synkronisert ugyldig setMessageBus (MessageBus mb) kaster IOException {if (! busSet) {bus = mb; buss.initBroker (); busSet = true; } annet System.out.println ("Kan ikke angi MessageBus mer enn en gang per kjøretid!"); }

offentlig statisk streng getBrokerName () {retur buss.getBrokerName (); }

public static Enumeration getChannelNames () {return channels.keys (); }

Disse klassemetodene tillater MessageBus forekomst som skal settes en gang for hver kjøretid, og returnere informasjon om henholdsvis buss- og kanalnavn.

 offentlig statisk synkronisert kanalabonnement (strengnavn, ChannelListener cl) kaster IOException {Channel ch; hvis (channel.containsKey (navn)) ch = (Channel) kanaler.get (navn); annet {bus.addChannel (navn); ch = ny kanal (navn); channel.put (navn, ch); } ch.subscribe (cl); retur ch; } 

Denne klassemetoden returnerer kanalforekomsten som tilsvarer kanalnavnet. Det skaper kanalen og samtalene MessageBus for å legge det til systemet hvis det ikke allerede eksisterer. Så snart kanalen er opprettet, er den første lytteren registrert hos den.

// kalt av klienter til å registrere ChannelsUpdateListener offentlig statisk ugyldig subscribeChannelsUpdates (ChannelsUpdateListener cul) {kanalerUpdateListeners.addElement (cul); }

// kalt av klienter til å avregistrere ChannelsUpdateListener public static void unsubscribeChannelsUpdates (ChannelsUpdateListener cul) {channelUpdateListeners.removeElement (cul); }

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