Hva er ekstern prosedyrekall rpc. Ringer eksterne prosedyrer

Remote Procedure Call (RPC) Remote Procedure Call Consept

Ideen med en Remote Procedure Call (RPC) er å utvide den velkjente og forståtte mekanismen for overføring av kontroll og data i et program som kjører på én maskin for å overføre kontroll og data over et nettverk. Verktøy for ekstern prosedyreanrop er designet for å lette organiseringen av distribuert databehandling. Den største effektiviteten ved bruk av RPC oppnås i de applikasjonene der det er interaktiv kommunikasjon mellom eksterne komponenter med raske responstider og en relativt liten mengde data som overføres. Slike applikasjoner kalles RPC-orienterte.

De karakteristiske trekk ved å ringe lokale prosedyrer er:

Asymmetri, det vil si at en av de samhandlende partene er initiativtakeren; Synkronisitet, det vil si at utføringen av anropsprosedyren stopper fra det øyeblikket forespørselen er utstedt og gjenopptas først etter at den anropte prosedyren kommer tilbake.

Implementering av eksterne anrop er mye mer komplisert enn å implementere lokale prosedyreanrop. Til å begynne med, siden anrops- og anropsprosedyrene utføres på forskjellige maskiner, har de forskjellige adresserom, og dette skaper problemer ved overføring av parametere og resultater, spesielt hvis maskinene ikke er identiske. Siden RPC ikke kan stole på delt minne, betyr dette at RPC-parametere ikke må inneholde pekere til ikke-stablede minneplasseringer og at parameterverdier må kopieres fra en datamaskin til en annen. Den neste forskjellen mellom RPC og en lokal samtale er at den nødvendigvis bruker det underliggende kommunikasjonssystemet, men dette skal ikke være eksplisitt synlig verken i definisjonen av prosedyrene eller i selve prosedyrene. Fjernhet introduserer ytterligere problemer. Utførelsen av det anropende programmet og den kalte lokale prosedyren på samme maskin implementeres i en enkelt prosess. Men implementeringen av RPC involverer minst to prosesser - en på hver maskin. Hvis en av dem krasjer, kan følgende situasjoner oppstå: hvis anropsprosedyren krasjer, vil de eksternt kalte prosedyrene bli "foreldreløse", og hvis fjernprosedyrene krasjer, vil anropsprosedyrene bli "foreldreløse foreldre", og venter forgjeves på en respons fra fjernprosedyrene.

I tillegg er det en rekke problemer knyttet til heterogeniteten til programmeringsspråk og driftsmiljøer: datastrukturene og prosedyrekallstrukturene som støttes på et hvilket som helst programmeringsspråk, støttes ikke på samme måte på alle andre språk.

Disse og noen andre problemer løses av den utbredte RPC-teknologien, som ligger til grunn for mange distribuerte operativsystemer.

Grunnleggende RPC-operasjoner

For å forstå hvordan RPC fungerer, la oss først vurdere å foreta et lokalt prosedyrekall på en typisk maskin som kjører offline. La dette for eksempel være et systemanrop

Count=read(fd,buf,nbytes);

der fd er et heltall,
buf - rekke karakterer,
nbytes er et heltall.

For å foreta anropet, skyver anropsprosedyren parametrene inn på stabelen i omvendt rekkefølge (Figur 3.1). Etter at leseanropet er utført, plasserer den returverdien i et register, flytter returadressen og returnerer kontrollen til anropsprosedyren, som henter parametere fra stabelen og returnerer den til sin opprinnelige tilstand. Merk at på C-språket kan parametere kalles enten ved referanse (etter navn) eller etter verdi (etter verdi). I forhold til den kalte prosedyren er verdiparametere initialiserte lokale variabler. Den kalte prosedyren kan endre dem uten å påvirke de opprinnelige verdiene til disse variablene i anropsprosedyren.

Hvis en peker til en variabel sendes til den kalte prosedyren, innebærer endring av verdien av denne variabelen ved den kalte prosedyren å endre verdien av denne variabelen for den anropende prosedyren. Dette faktum er veldig viktig for RPC.

Det er også en annen parameteroverføringsmekanisme som ikke brukes i C. Den kalles call-by-copy/restore, som krever at den som ringer kopierer variabler til stabelen som verdier, og deretter kopierer dem tilbake etter at samtalen er utført over opprinnelige verdier for anropsprosedyren.

Beslutningen om hvilken parameteroverføringsmekanisme som skal brukes, tas av språkutviklerne. Noen ganger avhenger det av typen data som overføres. I C, for eksempel, sendes heltall og andre skalardata alltid med verdi, og matriser sendes alltid ved referanse.

Ris. 3.1. a) Stabelen før leseanropet utføres;
b) Stable under prosedyreutførelse;
c) Stable etter retur til oppringingsprogrammet

Ideen bak RPC er å få et eksternt prosedyrekall til å se så likt ut som et lokalt prosedyrekall som mulig. Med andre ord, gjør RPC transparent: anropsprosedyren trenger ikke å vite at den anropte prosedyren er på en annen maskin, og omvendt.

RPC oppnår åpenhet på følgende måte. Når den kalte prosedyren faktisk er ekstern, blir en annen versjon av prosedyren, kalt en klientstubb, plassert i biblioteket i stedet for den lokale prosedyren. I likhet med den opprinnelige prosedyren kalles stubben ved å bruke en kallesekvens (som i figur 3.1), og et avbrudd oppstår når du får tilgang til kjernen. Bare, i motsetning til den opprinnelige prosedyren, plasserer den ikke parametere i registre og ber ikke om data fra kjernen; i stedet genererer den en melding som skal sendes til kjernen til den eksterne maskinen.

RPC-utførelsesstadier

Samspillet mellom programvarekomponenter når du utfører et eksternt prosedyrekall er illustrert i figur 3.2. Etter at klientstubben har blitt kalt opp av klientprogrammet, er dens første oppgave å fylle bufferen med meldingen som sendes. I noen systemer har klientstubben en enkelt buffer med fast lengde som fylles helt fra begynnelsen med hver ny forespørsel. I andre systemer er meldingsbufferen en pool av buffere for individuelle meldingsfelt, hvorav noen allerede er fulle. Denne metoden er spesielt egnet for tilfeller der pakken har et format som består av et stort antall felt, men verdiene til mange av disse feltene endres ikke fra anrop til anrop.

Parametrene må deretter konverteres til riktig format og settes inn i meldingsbufferen. På dette tidspunktet er meldingen klar til å sendes, så kjerneanropsavbruddet utføres.

Ris. 3.2. Anrop for ekstern prosedyre

Når kjernen får kontroll, bytter den kontekst, lagrer prosessorregistre og minnekart (sidehåndtak), og installerer et nytt minnekart som skal brukes til å kjøre i kjernemodus. Fordi kjerne- og brukerkontekstene er forskjellige, må kjernen kopiere meldingen nøyaktig til sitt eget adresserom slik at den kan få tilgang til den, huske destinasjonsadressen (og muligens andre overskriftsfelt), og den må sende den til nettverksgrensesnittet. Dette fullfører arbeidet på byggherresiden. Overføringstidtakeren er slått på, og kjernen kan enten syklisk spørre etter et svar eller sende kontrollen til planleggeren, som vil velge en annen prosess som skal kjøres. I det første tilfellet blir kjøringen av spørringen akselerert, men multiprogrammering er fraværende.

På serversiden plasseres innkommende biter av den mottakende maskinvaren enten i en buffer på brikken eller i RAM. Når all informasjon er mottatt, genereres et avbrudd. Avbruddsbehandleren sjekker riktigheten av pakkedataene og bestemmer hvilken stubb den skal sendes til. Hvis ingen av stubbene forventer denne pakken, må behandleren enten buffere den eller forkaste den helt. Hvis det er en ventestubb, blir meldingen kopiert til den. Til slutt utføres en kontekstsvitsj, som et resultat av at registrene og minnekartet gjenopprettes, og tar verdiene som de hadde i øyeblikket da stubben foretok mottaksanropet.

Nå begynner serverstubben å fungere. Den pakker ut parameterne og skyver dem på riktig måte på stabelen. Når alt er klart, ringes det til serveren. Etter å ha utført prosedyren, sender serveren resultatene til klienten. For å gjøre dette, utfør alle trinnene beskrevet ovenfor, bare i omvendt rekkefølge.

Figur 3.3 viser rekkefølgen av kommandoer som må utføres for hvert RPC-kall, og Figur 3.4 viser hvor stor andel av den totale RPC-utførelsestiden som brukes på hvert av de 14 trinnene som er beskrevet. Testene ble utført på en DEC Firefly multi-prosessor arbeidsstasjon, og mens tilstedeværelsen av fem prosessorer nødvendigvis påvirket resultatene av målingene, gir histogrammet vist i figuren en generell ide om RPC-utførelsesprosessen.

Ris. 3.3. Trinn for å utføre en RPC-prosedyre

Ris. 3.4. Tidsfordeling mellom 14 stadier av RPC-utførelse

1. Ringe en stubb

2. Forbered en buffer

3. Pakk parametere

4. Fyll ut tittelfeltet

5. Beregn kontrollsummen i meldingen

6. Avbryt til kjernen

7. Pakkekø for utførelse

8. Sende en melding til kontrolleren via QBUS-bussen

9. Ethernet-overføringstid

10. Motta pakke fra kontrolleren

11. Avbryt håndteringsprosedyre

12. Kontrollsumberegning

13. Kontekstbytte til brukerplass

14. Utføre en serverstubb

Dynamisk kobling

La oss vurdere hvordan klienten spesifiserer plasseringen av serveren. En metode for å løse dette problemet er å bruke serverens nettverksadresse direkte i klientprogrammet. Ulempen med denne tilnærmingen er dens ekstreme ufleksibilitet: når du flytter en server, eller øker antall servere, eller endrer grensesnittet i alle disse og mange andre tilfeller, er det nødvendig å rekompilere alle programmer som brukte en hardkodet serveradresse. For å unngå alle disse problemene bruker noen distribuerte systemer det som kalles dynamisk kobling.

Utgangspunktet for dynamisk binding er den formelle definisjonen (spesifikasjonen) av serveren. Spesifikasjonen inneholder filservernavnet, versjonsnummeret og en liste over tjenesteprosedyrer gitt av denne serveren til klienter (Figur 3.5). For hver prosedyre er det gitt en beskrivelse av parameterne, som indikerer om denne parameteren er inn- eller utdata i forhold til serveren. Noen parametere kan være både input og output - for eksempel en matrise som sendes av klienten til serveren, modifiseres der og deretter returneres tilbake til klienten (kopierings-/gjenopprettingsoperasjon).

Ris. 3.5. RPC-serverspesifikasjon

Den formelle serverspesifikasjonen brukes som input til stubgeneratorprogrammet, som lager både klient- og serverstubber. De blir deretter plassert i de aktuelle bibliotekene. Når et bruker (klient) program kaller en hvilken som helst prosedyre definert i serverspesifikasjonen, er den tilsvarende stubbprosedyren assosiert med programmets binære kode. På samme måte, når en server er kompilert, er serverstubber knyttet til den.

Når en server starter opp, er det aller første den gjør å sende servergrensesnittet til et spesielt program kalt en binder. Denne prosessen, kjent som serverregistreringsprosessen, innebærer at serveren sender navn, versjonsnummer, unike identifikator og en håndtere til plasseringen av serveren. Håndtaket er systemuavhengig og kan være en IP-, Ethernet-, X.500- eller en annen adresse, og kan også inneholde annen informasjon, for eksempel autentiseringsrelatert informasjon.

Når en klient ringer en av fjernprosedyrene for første gang, for eksempel les, ser klientstubben at den ennå ikke er koblet til serveren og sender en melding til binderprogrammet med en forespørsel om å importere grensesnittet til ønsket versjon av ønsket server. Hvis en slik server eksisterer, sender binder beskrivelsen og den unike identifikatoren til klientstubben.

Når du sender en melding med en forespørsel, bruker klientstubben en deskriptor som adresse. Meldingen inneholder parametere og en unik identifikator som serverkjernen bruker for å rute den innkommende meldingen til ønsket server hvis det er flere av dem på denne maskinen.

Denne metoden for å importere/eksportere grensesnitt er svært fleksibel. For eksempel kan det være flere servere som støtter samme grensesnitt, og klienter er tilfeldig fordelt på tvers av serverne. Innenfor rammen av denne metoden blir det mulig å periodisk polle servere, analysere ytelsen deres og, i tilfelle feil, automatisk slå av, noe som øker den generelle feiltoleransen til systemet. Denne metoden kan også støtte klientautentisering. For eksempel kan serveren bestemme at den bare kan brukes av klienter fra en bestemt liste.

Dynamisk binding har imidlertid ulemper, for eksempel ekstra overhead (tid) for eksport og import av grensesnitt. Størrelsen på disse kostnadene kan være betydelig, siden mange klientprosesser eksisterer i kort tid, og hver gang prosessen starter, må grensesnittimportprosedyren utføres på nytt. I tillegg, i store distribuerte systemer, kan bindeprogrammet bli en flaskehals, og å lage flere programmer med lignende formål øker også overheaden med å opprette og synkronisere prosesser.

RPC-semantikk ved feil

Ideelt sett bør RPC fungere riktig selv ved feil. Vurder følgende feilklasser:

Klienten kan ikke finne serveren, for eksempel hvis ønsket server feiler, eller fordi klientprogrammet ble kompilert for lenge siden og brukte en gammel versjon av servergrensesnittet. I dette tilfellet, som svar på klientens forespørsel, mottas en melding som inneholder en feilkode. Forespørselen fra klienten til serveren gikk tapt. Den enkleste løsningen er å gjenta forespørselen etter en viss tid. Svarmeldingen fra serveren til klienten gikk tapt. Dette alternativet er mer komplisert enn det forrige, siden noen prosedyrer ikke er idempotente. En idempotent prosedyre er en prosedyre hvis utførelsesforespørsel kan gjentas flere ganger uten å endre resultatet. Et eksempel på en slik prosedyre vil være å lese en fil. Men prosedyren for å ta ut et visst beløp fra en bankkonto er ikke idempotent, og hvis svaret går tapt, kan en gjentatt forespørsel endre tilstanden til kundens konto betydelig. En mulig løsning er å gjøre alle prosedyrer idempotente. I praksis er dette imidlertid ikke alltid mulig, så en annen metode kan brukes - sekvensiell nummerering av alle forespørsler fra klientkjernen. Serverkjernen husker nummeret på den siste forespørselen fra hver klient, og ved mottak av hver forespørsel analyserer den om denne forespørselen er en primær eller en gjentatt forespørsel. Serveren krasjet etter å ha mottatt forespørselen. Egenskapen til idempotens er også viktig her, men tilnærmingen med spørringsnummerering kan dessverre ikke brukes. I dette tilfellet er det viktig når feilen oppstod - før eller etter operasjonen. Men klientkjernen kan ikke gjenkjenne disse situasjonene, den vet bare at responstiden er utløpt. Det er tre tilnærminger til dette problemet: Vent til serveren starter på nytt og prøv operasjonen på nytt. Denne tilnærmingen sikrer at RPC fullfører minst én gang, og muligens flere. Meld feilen umiddelbart til applikasjonen. Denne tilnærmingen sikrer at RPC-en utføres maksimalt én gang. Den tredje tilnærmingen garanterer ingenting. Når serveren svikter, gis ingen støtte til klienten. RPC kan enten ikke bli utført i det hele tatt, eller det kan bli utført mange ganger. I alle fall er denne metoden veldig enkel å implementere.

Ingen av disse tilnærmingene er veldig attraktive. Og det ideelle alternativet, som vil garantere nøyaktig én RPC-utførelse, kan i det generelle tilfellet ikke implementeres av grunnleggende årsaker. La for eksempel en ekstern operasjon være å skrive ut noe tekst, som inkluderer lasting av skriverbufferen og innstilling av én bit i et skriverkontrollregister, som et resultat av at skriveren starter. En serverkrasj kan oppstå enten et mikrosekund før eller et mikrosekund etter at kontrollbiten er satt. Feiløyeblikket bestemmer helt gjenopprettingsprosedyren, men klienten kan ikke finne ut om feiløyeblikket. Kort sagt, muligheten for et serverkrasj endrer radikalt karakteren til RPC og gjenspeiler tydelig forskjellen mellom et sentralisert og et distribuert system. I det første tilfellet fører et serverkrasj til et klientkrasj, og gjenoppretting er umulig. I det andre tilfellet er det både mulig og nødvendig å utføre systemgjenopprettingshandlinger.

Klienten krasjet etter å ha sendt en forespørsel. I dette tilfellet blir det utført beregninger på resultater som ingen forventer. Slike beregninger kalles «foreldreløse». Tilstedeværelsen av foreldreløse barn kan forårsake ulike problemer: bortkastet CPU-tid, blokkering av ressurser, erstatning av et svar på en gjeldende forespørsel med et svar på en forespørsel som ble utstedt av klientmaskinen før systemet ble startet på nytt.

Hvordan håndtere foreldreløse barn? La oss se på 4 mulige løsninger.

Ødeleggelse. Før klientstubben sender en RPC-melding, noterer den seg i loggen som indikerer hva den vil gjøre nå. Loggen lagres på disk eller annen feiltolerant lagring. Etter ulykken startes systemet på nytt, loggen analyseres og foreldreløse barn elimineres. Ulempene med denne tilnærmingen inkluderer for det første den økte overheaden forbundet med å skrive hver RPC til disk, og for det andre mulig ineffektivitet på grunn av utseendet til andregenerasjons foreldreløse barn generert av RPC-anrop utstedt av førstegenerasjons foreldreløse barn. Reinkarnasjon. I dette tilfellet løses alle problemer uten å bruke diskopptak. Metoden består i å dele opp tid i sekvensielt nummererte perioder. Når klienten starter på nytt, sender den en melding til alle maskiner for å kunngjøre starten på en ny periode. Etter å ha mottatt denne meldingen, elimineres alle eksterne beregninger. Selvfølgelig, hvis nettverket er segmentert, kan noen foreldreløse overleve. Myk re-inkarnasjon ligner på det forrige tilfellet, bortsett fra at ikke alle slettede beregninger blir funnet og ødelagt, men bare beregningene til den omstartende klienten. Utløpsdato. Hver forespørsel får en standard tidsperiode T hvor den må fullføres. Hvis forespørselen ikke fullføres innen den tildelte tiden, tildeles et ekstra kvante. Selv om dette krever ekstra arbeid, hvis serveren etter en klientkrasj venter på et intervall T før den starter klienten på nytt, blir alle foreldreløse barn nødvendigvis ødelagt.

I praksis er ingen av disse tilnærmingene ønskelig, og faktisk kan det å drepe foreldreløse barn gjøre situasjonen verre. Anta for eksempel at en foreldreløs har låst én eller flere databasefiler. Hvis det foreldreløse barnet plutselig blir ødelagt, vil disse låsene forbli, i tillegg kan de ødelagte foreldreløse barna bli stående i forskjellige systemkøer, i fremtiden kan de føre til utførelse av nye prosesser, etc.

Ideen om å ringe eksterne prosedyrer (Remote Procedure Call - RPC) består i å utvide den velkjente og forståtte mekanismen for overføring av kontroll og data innenfor et program som kjører på én maskin til å overføre kontroll og data over et nettverk. Verktøy for ekstern prosedyreanrop er designet for å lette organiseringen av distribuert databehandling.

Den største effektiviteten ved å bruke RPC oppnås i de applikasjonene der det er interaktiv kommunikasjon mellom eksterne komponenter Med kort responstid Og relativt liten mengde overførte data.Slike applikasjoner kalles RPC-orienterte.

De karakteristiske trekk ved å ringe lokale prosedyrer er:

    asymmetri, det vil si at en av de samhandlende partene er initiativtaker;

    Synkronisitet, det vil si at utførelsen av anropsprosedyren suspenderes fra det øyeblikket forespørselen er utstedt og gjenopptas først når den anropte prosedyren kommer tilbake.

Implementering av eksterne anrop er mye mer komplisert enn å implementere lokale prosedyreanrop.

1. La oss starte med det faktum at siden anrops- og anropsprosedyrene utføres på forskjellige maskiner, har forskjellige adresseområder, og dette skaper problemer ved overføring av parametere og resultater, spesielt hvis maskinene ikke er identiske.

Siden RPC ikke kan stole på delt minne, betyr dette det RPC-parametere må ikke inneholde pekere til ikke-stablede minneplasseringer Hva så parameterverdier må kopieres fra en datamaskin til en annen.

2. Den neste forskjellen mellom RPC og en lokal samtale er at den bruker nødvendigvis det underliggende kommunikasjonssystemet, men dette bør ikke være tydelig synlig verken i definisjonen av prosedyrer eller i selve prosedyrene .

Fjernhet introduserer ytterligere problemer. Kjøre oppringingsprogrammet og den oppkalte lokale prosedyren på samme maskin implementert innenforenkelt prosess. Men involvert i implementeringen av RPCminst to prosesser - en i hver bil. Hvis en av dem mislykkes, kan følgende situasjoner oppstå:

    Hvis anropsprosedyren krasjer, vil de eksternt kalte prosedyrene bli "foreldreløse" og

    Hvis fjernprosedyrene avsluttes unormalt, vil anropsprosedyrene bli "fattige foreldre" og vente på svar fra fjernprosedyrene til ingen nytte.

I tillegg er det en rekke problemer knyttet til heterogeniteten til programmeringsspråk og driftsmiljøer : Datastrukturer og prosedyrekallstrukturer som støttes i et programmeringsspråk, støttes ikke på samme måte på alle andre språk.

Disse og noen andre problemer løses av den utbredte RPC-teknologien, som ligger til grunn for mange distribuerte operativsystemer.

Ideen bak RPC er å få et eksternt prosedyrekall til å se så likt ut som et lokalt prosedyrekall som mulig. Med andre ord, gjør RPC transparent: anropsprosedyren trenger ikke å vite at den anropte prosedyren er på en annen maskin, og omvendt.

RPC oppnår åpenhet på følgende måte. Når den kalte prosedyren faktisk er ekstern, blir en annen versjon av prosedyren, kalt en klientstubb, plassert i biblioteket i stedet for den lokale prosedyren. I likhet med den opprinnelige prosedyren kalles stubben ved å bruke en kallesekvens (som i figur 3.1), og et avbrudd oppstår når du får tilgang til kjernen. Bare, i motsetning til den opprinnelige prosedyren, plasserer den ikke parametere i registre og ber ikke om data fra kjernen; i stedet genererer den en melding som skal sendes til kjernen til den eksterne maskinen.

Ris. 3.2. Anrop for ekstern prosedyre

Ekstern prosedyrekall(eller Ringer eksterne prosedyrer) (fra engelsk. Remote Procedure Call (RPC)) - en klasse med teknologier som lar dataprogrammer kalle opp funksjoner eller prosedyrer i et annet adresseområde (vanligvis på eksterne datamaskiner). Vanligvis inkluderer en implementering av RPC-teknologi to komponenter: en nettverksprotokoll for klient-server-kommunikasjon og et objektserialiseringsspråk (eller strukturer, for ikke-objekt-RPC). Ulike RPC-implementeringer har svært forskjellige arkitekturer og varierer i deres evner: noen implementerer SOA-arkitekturen, andre CORBA eller DCOM. På transportlaget bruker RPC-er primært TCP- og UDP-protokoller, men noen er bygget på toppen av HTTP (som bryter med ISO/OSI-arkitekturen, siden HTTP ikke er en innfødt transportprotokoll).

Implementeringer

Det er mange teknologier som gir RPC:

  • Sun RPC (binær protokoll basert på TCP og UDP og XDR) RFC-1831 andre navn ONC RPC RFC-1833
  • .Net Remoting (binær protokoll basert på TCP, UDP, HTTP)
  • SOAP - Simple Object Access Protocol (HTTP-basert tekstprotokoll) se spesifikasjon: RFC-4227
  • XML RPC (HTTP-basert tekstprotokoll) se spesifikasjon: RFC-3529
  • Java RMI - Java Remote Method Invocation - se spesifikasjon: http://java.sun.com/j2se/1.5.0/docs/guide/rmi/index.html
  • JSON-RPC JavaScript Object Notation Remote Procedure Calls (HTTP-basert tekstprotokoll) se spesifikasjon: RFC-4627
  • DCE/RPC - Distribuert datamiljø / Remote Procedure Calls (binær protokoll basert på ulike transportprotokoller, inkludert TCP/IP og Named Pipes fra SMB/CIFS-protokollen)
  • DCOM - Distributed Component Object Model kjent som MSRPC Microsoft Remote Procedure Call eller "Network OLE" (en objektorientert utvidelse til DCE RPC som lar deg sende referanser til objekter og kalle objektmetoder gjennom slike referanser)

Prinsipp

Ideen med en Remote Procedure Call (RPC) er å utvide den velkjente og forståtte mekanismen for overføring av kontroll og data i et program som kjører på én maskin for å overføre kontroll og data over et nettverk. Verktøy for ekstern prosedyreanrop er designet for å lette organiseringen av distribuert databehandling og opprettelsen av distribuerte klient-server informasjonssystemer. Den største effektiviteten ved bruk av RPC oppnås i de applikasjonene der det er interaktiv kommunikasjon mellom eksterne komponenter med raske responstider og en relativt liten mengde data som overføres. Slike applikasjoner kalles RPC-orienterte.

Implementering av eksterne anrop er mye mer komplisert enn å implementere lokale prosedyreanrop. Vi kan identifisere følgende problemer og oppgaver som må løses ved implementering av RPC:

  • Fordi anrops- og anropsprosedyrene kjører på forskjellige maskiner, har de forskjellige adresseområder, og dette skaper problemer ved overføring av parametere og resultater, spesielt hvis maskinene kjører forskjellige operativsystemer eller har forskjellige arkitekturer (for eksempel little-endian eller big- endian). ). Siden RPC ikke kan stole på delt minne, betyr dette at RPC-parametere ikke må inneholde pekere til ikke-stablede minneplasseringer og at parameterverdier må kopieres fra en datamaskin til en annen. For å kopiere prosedyreparametere og utførelsesresultater over nettverket, blir de serialisert.
  • I motsetning til et lokalt anrop, bruker et eksternt prosedyrekall nødvendigvis transportlaget til nettverksarkitekturen (for eksempel TCP), men dette forblir skjult for utvikleren.
  • Utførelsen av det anropende programmet og den kalte lokale prosedyren på samme maskin implementeres i en enkelt prosess. Men implementeringen av RPC involverer minst to prosesser - en på hver maskin. Hvis en av dem krasjer, kan følgende situasjoner oppstå: hvis anropsprosedyren krasjer, vil de eksternt kalte prosedyrene bli "foreldreløse", og hvis fjernprosedyrene krasjer, vil anropsprosedyrene bli "fattige foreldre", som vil vente forgjeves for svar fra fjernprosedyrene.
  • Det er en rekke problemer knyttet til heterogeniteten til programmeringsspråk og driftsmiljøer: datastrukturene og prosedyrekallstrukturene som støttes i et hvilket som helst programmeringsspråk, støttes ikke på samme måte på alle andre språk. Det er altså et kompatibilitetsproblem som ennå ikke er løst enten ved innføring av én allment akseptert standard, eller ved implementering av flere konkurrerende standarder på alle arkitekturer og på alle språk.

Delsystemer

  • Transportdelsystem

Administrer utgående og innkommende forbindelser. - støtte for konseptet "meldingsgrense" for transportprotokoller som ikke direkte støtter det (TCP). - støtte for garantert levering for transportprotokoller som ikke direkte støtter det (UDP).

  • Trådbasseng (kun callee). Gir en utførelseskontekst for kode som påkalles over nettverket.
  • Marshalling (også kalt "serialisering"). Pakke anropsparametere inn i en bytestrøm på en standard måte, uavhengig av arkitekturen (spesielt rekkefølgen på byte i et ord). Spesielt kan det påvirke matriser, strenger og strukturer som pekes på av pekerparametere.
  • Kryptere pakker og bruke en digital signatur på dem.
  • Autentisering og autorisasjon. Overføring over nettverket av informasjon som identifiserer personen som ringer.

I noen RPC (.NET Remoting)-implementeringer er delsystemgrenser åpne polymorfe grensesnitt, og det er mulig å skrive din egen implementering av nesten alle de listede undersystemene. I andre implementeringer (DCE RPC på Windows) er dette ikke tilfelle.

se også

Remote Procedure Call (RPC) Remote Procedure Call Consept

Ideen med en Remote Procedure Call (RPC) er å utvide den velkjente og forståtte mekanismen for overføring av kontroll og data i et program som kjører på én maskin for å overføre kontroll og data over et nettverk. Verktøy for ekstern prosedyreanrop er designet for å lette organiseringen av distribuert databehandling. Den største effektiviteten ved bruk av RPC oppnås i de applikasjonene der det er interaktiv kommunikasjon mellom eksterne komponenter med raske responstider og en relativt liten mengde data som overføres. Slike applikasjoner kalles RPC-orienterte.

De karakteristiske trekk ved å ringe lokale prosedyrer er:

  • Asymmetri, det vil si at en av de samhandlende partene er initiativtakeren;
  • Synkronisitet, det vil si at utførelsen av anropsprosedyren suspenderes fra det øyeblikket forespørselen er utstedt og gjenopptas først etter at den anropte prosedyren kommer tilbake.

Implementering av eksterne anrop er mye mer komplisert enn å implementere lokale prosedyreanrop. Til å begynne med, siden anrops- og anropsprosedyrene utføres på forskjellige maskiner, har de forskjellige adresserom, og dette skaper problemer ved overføring av parametere og resultater, spesielt hvis maskinene ikke er identiske. Siden RPC ikke kan stole på delt minne, betyr dette at RPC-parametere ikke må inneholde pekere til ikke-stablede minneplasseringer og at parameterverdier må kopieres fra en datamaskin til en annen. Den neste forskjellen mellom RPC og en lokal samtale er at den nødvendigvis bruker det underliggende kommunikasjonssystemet, men dette skal ikke være eksplisitt synlig verken i definisjonen av prosedyrene eller i selve prosedyrene. Fjernhet introduserer ytterligere problemer. Utførelsen av det anropende programmet og den kalte lokale prosedyren på samme maskin implementeres i en enkelt prosess. Men implementeringen av RPC involverer minst to prosesser - en på hver maskin. Hvis en av dem krasjer, kan følgende situasjoner oppstå: hvis anropsprosedyren krasjer, vil de eksternt kalte prosedyrene bli "foreldreløse", og hvis fjernprosedyrene krasjer, vil anropsprosedyrene bli "foreldreløse foreldre", og venter forgjeves på en respons fra fjernprosedyrene.

I tillegg er det en rekke problemer knyttet til heterogeniteten til programmeringsspråk og driftsmiljøer: datastrukturene og prosedyrekallstrukturene som støttes på et hvilket som helst programmeringsspråk, støttes ikke på samme måte på alle andre språk.

Disse og noen andre problemer løses av den utbredte RPC-teknologien, som ligger til grunn for mange distribuerte operativsystemer. Grunnleggende RPC-operasjoner

For å forstå hvordan RPC fungerer, la oss først vurdere å foreta et lokalt prosedyrekall på en typisk maskin som kjører offline. La dette for eksempel være et systemanrop

count=read(fd, buf, nbytes);

der fd er et heltall, buf er en rekke tegn, nbytes er et heltall.

For å foreta anropet, skyver anropsprosedyren parametrene inn på stabelen i omvendt rekkefølge (Figur 3.1). Etter at leseanropet er utført, plasserer den returverdien i et register, flytter returadressen og returnerer kontrollen til anropsprosedyren, som henter parametere fra stabelen og returnerer den til sin opprinnelige tilstand. Merk at på C-språket kan parametere kalles enten ved referanse (etter navn) eller etter verdi (etter verdi). I forhold til den kalte prosedyren er verdiparametere initialiserte lokale variabler. Den kalte prosedyren kan endre dem uten å påvirke de opprinnelige verdiene til disse variablene i anropsprosedyren.

Hvis en peker til en variabel sendes til den kalte prosedyren, innebærer endring av verdien av denne variabelen ved den kalte prosedyren å endre verdien av denne variabelen for den anropende prosedyren. Dette faktum er veldig viktig for RPC.

Det er også en annen parameteroverføringsmekanisme som ikke brukes i C. Den kalles call-by-copy/restore, som krever at den som ringer kopierer variabler til stabelen som verdier, og deretter kopierer dem tilbake etter at samtalen er utført over opprinnelige verdier for anropsprosedyren.

Beslutningen om hvilken parameteroverføringsmekanisme som skal brukes, tas av språkutviklerne. Noen ganger avhenger det av typen data som overføres. I C, for eksempel, sendes heltall og andre skalardata alltid med verdi, og matriser sendes alltid ved referanse.

applikasjon

En betydelig del av fjernadministrasjonsverktøyene i Windows-operativsystemet (Event Viewer, Server Manager, utskriftsadministrasjon, brukerlisteadministrasjon) bruker DCE RPC som et middel for nettverkskommunikasjon mellom den administrerte tjenesten ogapplikasjonen. DCE RPC-støtte har vært til stede i Windows NT siden den aller første versjonen 3.1. DCE RPC-klienter ble også støttet i den lette serien med Windows 3.x/95/98/Me-operativsystemer.

Windows-systembibliotekene som gir slike kontrollfunksjoner og fungerer som basislaget for bruker(netapi32.dll og delvis advapi32.dll) inneholder faktisk klientkode for DCE RPC-grensesnittene som utfører denne kontrollen.

Denne arkitektoniske beslutningen ble gjenstand for aktiv kritikk mot Microsoft. De generiske rangeringsprosedyrene som finnes i DCE RPC er svært komplekse og har et stort potensial for å utnytte defekter i nettverket ved å sende en bevisst misformet DCE RPC-pakke. En betydelig del av Windows-sikkerhetsfeil oppdaget fra slutten av 90-tallet til midten av 2000-tallet var feil i DCE RPC-rangeringskoden.

I tillegg til DCE RPC, bruker Windows aktivt DCOM-teknologi. For eksempel brukes det som et kommunikasjonsmiddel mellom IIS-nettserveradministrasjonsverktøy og selve serveren som administreres. Et fullt funksjonelt grensesnitt for kommunikasjon med MS Exchange Server-postsystemet - MAPI - er også basert på DCOM.

Remote Procedure Call RPC Konseptet med Remote Procedure Call Ideen bak Remote Procedure Call (RPC) er å utvide den velkjente og forståtte mekanismen for overføring av kontroll og data i et program som kjører på én maskin for å overføre kontroll og data over et nettverk. Verktøy for ekstern prosedyreanrop er designet for å lette organiseringen av distribuert databehandling. Den største effektiviteten ved bruk av RPC oppnås i de applikasjonene der det er interaktiv kommunikasjon mellom eksterne komponenter med korte responstider og en relativt liten mengde overførte data.

Slike applikasjoner kalles RPC-orienterte. De karakteristiske egenskapene til å ringe lokale prosedyrer er asymmetri, det vil si at en av de samhandlende partene er initiatoren Synchronicity, det vil si at utførelsen av anropsprosedyren stopper fra det øyeblikket forespørselen er utstedt og gjenopptas først etter retur fra den anropte prosedyren. Implementeringen av eksterne samtaler er mye mer komplisert enn implementeringen av samtaler til lokale prosedyrer.

Til å begynne med, siden anrops- og anropsprosedyrene utføres på forskjellige maskiner, har de forskjellige adresserom, og dette skaper problemer ved overføring av parametere og resultater, spesielt hvis maskinene ikke er identiske. Siden RPC ikke kan stole på delt minne, betyr dette at RPC-parametere ikke skal inneholde pekere til ikke-stablede minneplasseringer og at parameterverdier skal kopieres fra en datamaskin til en annen.

Den neste forskjellen mellom RPC og en lokal samtale er at den nødvendigvis bruker det underliggende kommunikasjonssystemet, men dette skal ikke være eksplisitt synlig verken i definisjonen av prosedyrene eller i selve prosedyrene. Fjernhet introduserer ytterligere problemer. Utførelsen av det anropende programmet og den kalte lokale prosedyren på samme maskin implementeres i en enkelt prosess, men implementeringen av RPC involverer minst to prosesser - en i hver maskin.

I tilfelle en av dem krasjer, kan følgende situasjoner oppstå: hvis anropsprosedyren krasjer, vil de eksternt kalte prosedyrene bli foreldreløse, og hvis fjernprosedyrene krasjer, vil anropsprosedyrene bli foreldreløse foreldre, som vil vente forgjeves på svar fra fjernprosedyrene. I tillegg er det en rekke problemer knyttet til heterogeniteten til programmeringsspråk og driftsmiljøer, datastrukturene og prosedyrekallstrukturene som støttes i et hvilket som helst programmeringsspråk, støttes ikke på samme måte i alle andre språk.

Disse og noen andre problemer løses av den utbredte RPC-teknologien, som ligger til grunn for mange distribuerte operativsystemer. Grunnleggende RPC-operasjoner For å forstå hvordan RPC fungerer, la oss først vurdere å foreta et lokalt prosedyrekall på en vanlig maskin som kjører autonomt. La det for eksempel være systemanropstallene lese fd,buf,nbytes der fd er et heltall, buf er en matrise av tegn er nbytes et heltall .

For å foreta anropet, skyver anropsprosedyren parametrene inn på stabelen i omvendt rekkefølge av figur 3.1. Etter at leseanropet er utført, plasserer den returverdien i et register, flytter returadressen og returnerer kontrollen til anropsprosedyren, som henter parametrene fra stabelen og returnerer den til sin opprinnelige tilstand. Merk at i C, parametere kan kalles ved referanse eller ved navn eller etter verdi. I forhold til den kalte prosedyren er verdiparametere initialiserte lokale variabler.

Den kalte prosedyren kan endre dem uten å påvirke de opprinnelige verdiene til disse variablene i anropsprosedyren. Hvis en peker til en variabel sendes til den kalte prosedyren, innebærer endring av verdien av denne variabelen ved den kalte prosedyren å endre verdien av denne variabelen for den kallende prosedyren. Dette faktum er veldig viktig for RPC. Det er også en annen mekanisme for å sende parametere som ikke brukes i C. Det kalles call-by-copy restore og innebærer at det kallende programmet kopierer variabler til stabelen som verdier, og deretter kopierer dem tilbake etter at kallet er gjort over originalen. verdiene for anropsprosedyren.

Beslutningen om hvilken parameteroverføringsmekanisme som skal brukes, tas av språkutviklerne. Noen ganger avhenger dette av typen data som sendes. I C, for eksempel, sendes heltall og andre skalardata alltid etter verdi, og matriser sendes alltid ved referanse.

Ris. 3.1. a Stabelen før leseanropet utføres b Stabelen under utførelsen av prosedyren c Stabelen etter retur til anropsprogrammet Ideen bak RPC er å få et kall til en ekstern prosedyre til å se så likt ut som mulig som et anrop til en lokal prosedyre. Med andre ord, for å gjøre RPC transparent, trenger ikke anropsprosedyren å vite at den anropte prosedyren er på en annen maskin, og omvendt RPC oppnår åpenhet på følgende måte.

Når den kalte prosedyren faktisk er ekstern, i stedet for den lokale prosedyren, plasseres en annen versjon av prosedyren, kalt klientstubben, i biblioteket. I likhet med den opprinnelige prosedyren kalles stubben ved å bruke anropssekvensen som i figur 3.1, og et avbrudd oppstår når du får tilgang til kjernen. Bare, i motsetning til den opprinnelige prosedyren, plasserer den ikke parametere i registre og ber ikke om data fra kjernen; i stedet genererer den en melding som skal sendes til kjernen til den eksterne maskinen. Stadier av RPC-utførelse Samspillet mellom programvarekomponenter når du utfører et eksternt prosedyrekall er illustrert i figur 3.2. Etter at klientstubben har blitt kalt opp av klientprogrammet, er dens første oppgave å fylle bufferen med meldingen som sendes.

I noen systemer har klientstubben en enkelt buffer med fast lengde som fylles helt fra begynnelsen med hver ny forespørsel. I andre systemer er meldingsbufferen en pool av buffere for individuelle meldingsfelt, hvorav noen allerede er fulle.

Denne metoden er spesielt egnet for tilfeller der pakken har et format som består av et stort antall felt, men verdiene til mange av disse feltene endres ikke fra anrop til anrop. Parametrene må deretter konverteres til riktig format og settes inn i meldingsbufferen. På dette tidspunktet er meldingen klar til å sendes, så kjerneanropsavbruddet utføres. Ris. 3.2. Ekstern prosedyrekall Når kjernen får kontroll, bytter den kontekst, lagrer prosessorregistre og minnekartsidehåndtak, og installerer et nytt minnekart som skal brukes til å kjøre i kjernemodus. Fordi kjerne- og brukerkontekstene er forskjellige, må kjernen kopiere meldingen nøyaktig til sitt eget adresserom slik at den kan få tilgang til den, huske destinasjonsadressen og muligens andre overskriftsfelt, og den må sende den til nettverksgrensesnittet.

Dette fullfører arbeidet på byggherresiden.

Overføringstidtakeren er slått på, og kjernen kan enten syklisk spørre etter et svar eller sende kontrollen til planleggeren, som vil velge en annen prosess som skal kjøres. I det første tilfellet blir kjøringen av spørringen akselerert, men multiprogrammering er fraværende. På serversiden plasseres innkommende biter av mottaksmaskinvaren enten i den innebygde bufferen eller i RAM Når all informasjonen er mottatt genereres et avbrudd.

Avbruddsbehandleren sjekker pakkens data for gyldighet og bestemmer hvilken stubb den skal sendes til. Hvis ingen stubb venter på pakken, må avbruddsbehandleren enten buffere den eller forkaste den helt. Hvis det er en ventestubb, blir meldingen kopiert til den. Til slutt utføres en kontekstsvitsj, som et resultat av at registrene og minnekartet gjenopprettes, og tar verdiene som de hadde i øyeblikket da stubben foretok mottaksanropet.

Nå begynner serverstubben å fungere. Den pakker ut parameterne og skyver dem på riktig måte på stabelen. Når alt er klart, ringes det til serveren. Etter å ha fullført prosedyren, sender serveren resultatene til klienten. For å gjøre dette utføres alle trinnene beskrevet ovenfor, kun i omvendt rekkefølge. Figur 3.3 viser rekkefølgen av kommandoer som må utføres for hvert RPC-kall, og Figur 3.4 viser hvor stor andel av den totale RPC-utførelsestiden som brukes på hvert av de 14 trinnene som er beskrevet.

Testene ble utført på en DEC Firefly multi-prosessor arbeidsstasjon, og mens tilstedeværelsen av fem prosessorer nødvendigvis påvirket resultatene av målingene, gir histogrammet vist i figuren en generell ide om RPC-utførelsesprosessen. Ris. 3.3. Stadier av RPC-prosedyren Fig. 3.4. Tidsfordeling mellom 14 stadier av RPC-utførelse 1. Kalle en stub 2. Forbered en buffer 3. Pakkeparametre 4. Fyll ut overskriftsfeltet 5. Beregn kontrollsummen i meldingen 6. Avbryt til kjernen 7. Sett pakken i kø for utførelse 8. Overfør meldingen til kontrolleren via QBUS-bussen 9. Overfør tid over Ethernet-nettverket 10. Motta en pakke fra kontrolleren 11. Avbruddshåndteringsprosedyre 12. Kontrollsumberegning 13. Kontekstbytte til brukerplass 14. Utføre en serverstubb Dynamisk binding La oss vurdere spørsmålet om hvordan klienten spesifiserer plasseringen av serveren.

En metode for å løse dette problemet er å bruke serverens nettverksadresse direkte i klientprogrammet.

Ulempen med denne tilnærmingen er at den er ekstremt lite fleksibel når du flytter serveren, eller øker antall servere eller endrer grensesnittet; i alle disse og mange andre tilfeller er det nødvendig å rekompilere alle programmer som brukte hard innstilling av serveren For å unngå alle disse problemene bruker noen distribuerte systemer det som kalles dynamisk kobling.

Utgangspunktet for dynamisk binding er å formelt definere serverspesifikasjonen. Spesifikasjonen inneholder filservernavnet, versjonsnummeret og en liste over tjenesteprosedyrer gitt av denne serveren til klienter (Figur 3.5). For hver prosedyre er det gitt en beskrivelse av parameterne, som indikerer om denne parameteren er input eller output i forhold til serveren. Noen parametere kan være både input og output - for eksempel endres en array som sendes av klienten til serveren. der, og returnerte deretter tilbake til klientoperasjonen kopigjenoppretting . Ris. 3.5. RPC-serverspesifikasjon Den formelle serverspesifikasjonen brukes som input til stubbgeneratorprogrammet, som lager både klient- og serverstubber.

De blir deretter plassert i de aktuelle bibliotekene. Når et brukerklientprogram kaller en hvilken som helst prosedyre definert i serverspesifikasjonen, er den tilsvarende stubbprosedyren assosiert med programmets binære kode.

På samme måte, når en server er kompilert, er serverstubber knyttet til den. Når serveren starter, er den aller første handlingen å overføre servergrensesnittet til et spesielt program kalt binder. Denne prosessen, kjent som serverregistreringsprosessen, innebærer at serveren sender navn, versjonsnummer, unike identifikator og en beskrivelse av serverens plassering. Deskriptoren er systemuavhengig og kan være en IP, Ethernet, X.500 eller noe annet. annen adresse.

I tillegg kan den inneholde annen informasjon, for eksempel relatert til autentisering. Når en klient kaller en av fjernprosedyrene for første gang, for eksempel les, ser klientstubben at den ennå ikke er koblet til serveren, og sender en melding til binderprogrammet med en forespørsel om å importere grensesnittet til ønsket versjon av ønsket server. Hvis en slik server eksisterer, sender binder deskriptor og unik identifikator for klientstubben.

Når du sender en melding med en forespørsel, bruker klientstubben en deskriptor som adresse. Meldingen inneholder parametere og en unik identifikator som serverkjernen bruker for å rute den innkommende meldingen til ønsket server hvis det er flere av dem på denne maskinen. Denne metoden for å importere og eksportere grensesnitt er svært fleksibel, for eksempel kan det være flere servere som støtter samme grensesnitt, og klienter er tilfeldig fordelt mellom serverne.

Innenfor rammen av denne metoden blir det mulig å periodisk polle servere, analysere ytelsen deres og, i tilfelle feil, automatisk slå av, noe som øker den generelle feiltoleransen til systemet. Denne metoden kan også støtte klientautentisering. For eksempel kan serveren bestemme at den bare kan brukes av klienter fra en spesifikk liste.Dynamisk binding har imidlertid ulemper, for eksempel ekstra overhead og tid brukt på eksport og import av grensesnitt.

Størrelsen på disse kostnadene kan være betydelig, siden mange klientprosesser eksisterer i kort tid, og hver gang prosessen starter, må grensesnittimportprosedyren utføres på nytt. I tillegg kan bindeprogrammet i store distribuerte systemer bli en flaskehals, og å lage flere programmer med samme formål øker også overheaden med å lage og synkronisere prosesser RPC-semantikk ved feil Ideelt sett bør RPC fungere korrekt i tilfelle av feil.

Tenk på følgende feilklasser: 1. Klienten kan ikke finne serveren, for eksempel hvis ønsket server feiler, eller fordi klientprogrammet ble kompilert for lenge siden og brukte en gammel versjon av servergrensesnittet. I dette tilfellet, som svar på klientens forespørsel, mottas en melding som inneholder en feilkode. 2. Forespørselen fra klienten til serveren gikk tapt Den enkleste løsningen er å gjenta forespørselen etter en viss tid. 3. Svarmeldingen fra serveren til klienten går tapt.

Dette alternativet er mer komplisert enn det forrige, siden noen prosedyrer ikke er idempotente. En idempotent prosedyre er en prosedyre hvis utførelsesforespørsel kan gjentas flere ganger uten å endre resultatet. Et eksempel på en slik prosedyre er å lese en fil. Men prosedyren for å ta ut et visst beløp fra en bankkonto er ikke idempotent, og hvis svaret går tapt, kan en gjentatt forespørsel endre tilstanden til kundens konto betydelig.

En mulig løsning er å gjøre alle prosedyrer idempotente. I praksis er dette imidlertid ikke alltid mulig, så en annen metode kan brukes - sekvensiell nummerering av alle forespørsler fra klientkjernen. Serverkjernen husker nummeret på den siste forespørselen fra hver klient, og ved mottak av hver forespørsel analyserer den om denne forespørselen er en primær eller en gjentatt forespørsel. 4. Serveren krasjet etter å ha mottatt forespørselen Idempotency-egenskapen er også viktig her, men tilnærmingen med forespørselsnummerering kan dessverre ikke brukes.

I dette tilfellet er det viktig når feilen oppstod - før eller etter operasjonen. Men klientkjernen kan ikke gjenkjenne disse situasjonene, den vet bare at responstiden er utløpt. Det er tre tilnærminger til dette problemet: Vent til serveren starter på nytt og prøv operasjonen på nytt Denne tilnærmingen sikrer at RPC fullføres minst én gang, og muligens flere. Meld feilen umiddelbart til applikasjonen.

Denne tilnærmingen sikrer at RPC-en utføres maksimalt én gang. Den tredje tilnærmingen garanterer ingenting. Når serveren svikter, gis ingen støtte til klienten. RPC kan enten ikke bli utført i det hele tatt, eller det kan bli utført mange ganger. I alle fall er denne metoden veldig enkel å implementere. Ingen av disse tilnærmingene er særlig attraktive, og det ideelle alternativet, som vil garantere nøyaktig én RPC-utførelse, kan i det generelle tilfellet ikke implementeres av prinsipielle årsaker.

La for eksempel en ekstern operasjon være å skrive ut noe tekst, som inkluderer lasting av skriverbufferen og innstilling av én bit i et skriverkontrollregister, som et resultat av at skriveren starter. Et serverkrasj kan oppstå enten et mikrosekund før eller et mikrosekund etter at kontrollbiten er satt. Feiløyeblikket bestemmer helt gjenopprettingsprosedyren, men klienten kan ikke finne ut om feiløyeblikket.

Kort sagt, muligheten for et serverkrasj endrer radikalt karakteren til RPC og gjenspeiler tydelig forskjellen mellom et sentralisert og et distribuert system. I det første tilfellet fører et serverkrasj til et klientkrasj, og gjenoppretting er umulig. I det andre tilfellet er det både mulig og nødvendig å utføre systemgjenopprettingshandlinger. 1. Klienten krasjet etter å ha sendt forespørselen. I dette tilfellet utføres beregninger på resultater som ingen forventer.Slike beregninger kalles foreldreløse beregninger. Tilstedeværelsen av foreldreløse barn kan forårsake ulike problemer: overhead av CPU-tid, blokkering av ressurser, erstatning av svaret på gjeldende forespørsel med et svar på en forespørsel som ble utstedt av klientmaskinen før systemet ble startet på nytt.

Hvordan håndtere foreldreløse barn? La oss se på 4 mulige løsninger. Ødeleggelse. Før klientstubben sender en RPC-melding, noterer den seg i loggen som angir hva den skal gjøre videre Loggen lagres på disk eller annet feiltolerant minne.

Etter ulykken startes systemet på nytt, loggen analyseres og foreldreløse barn elimineres. Ulempene med denne tilnærmingen inkluderer for det første den økte overheaden forbundet med å skrive hver RPC til disk, og for det andre mulig ineffektivitet på grunn av utseendet til andregenerasjons foreldreløse barn generert av RPC-anrop utstedt av førstegenerasjons foreldreløse barn. Reinkarnasjon I dette tilfellet løses alle problemer uten bruk av diskopptak. Metoden består i å dele opp tid i sekvensielt nummererte perioder. Når klienten starter på nytt, sender den en melding til alle maskiner for å kunngjøre starten på en ny periode.

Etter å ha mottatt denne meldingen, elimineres alle eksterne beregninger. Selvfølgelig, hvis nettverket er segmentert, kan noen foreldreløse overleve. Myk re-inkarnasjon ligner på det forrige tilfellet, bortsett fra at ikke alle slettede beregninger blir funnet og ødelagt, men bare beregningene til den omstartende klienten. Utløp. Hver forespørsel får en standard tidsperiode T som den må fullføres.

Hvis forespørselen ikke fullføres innen den tildelte tiden, tildeles et ekstra kvante. Selv om dette krever ekstra arbeid, hvis serveren etter et klientkrasj venter på et intervall T før den starter opp klienten på nytt, blir nødvendigvis alle foreldreløse barn ødelagt. I praksis er ingen av disse tilnærmingene ønskelig; faktisk kan ødeleggelse av foreldreløse barn gjøre situasjonen verre . Anta for eksempel at en foreldreløs har låst én eller flere databasefiler.

Hvis det foreldreløse barnet plutselig blir ødelagt, vil disse låsene forbli, i tillegg kan de ødelagte foreldreløse barna bli stående i forskjellige systemkøer, i fremtiden kan de føre til utførelse av nye prosesser, etc.

Hva skal vi gjøre med det mottatte materialet:

Hvis dette materialet var nyttig for deg, kan du lagre det på siden din på sosiale nettverk:

Programmer som kommuniserer over et nettverk trenger en kommunikasjonsmekanisme. På det lavere nivået, ved ankomst av pakker, sendes og behandles et signal av etm. På toppnivået fungerer møtemekanismen, tatt i bruk på Ada-språket. NFS bruker en RPC-mekanisme (Remote Procedure Call) der klienten kommuniserer med serveren (se figur 1). I henhold til denne prosessen kaller klienten først en prosedyre som sender en forespørsel til serveren. Ved ankomst av en forespørselspakke kaller serveren pakkeåpningsprosedyren, utfører den forespurte tjenesten, sender et svar og kontrollen returnerer til klienten.

RPC-grensesnittet kan tenkes å bestå av tre lag:

Toppnivået er helt gjennomsiktig. Et program på dette nivået kan for eksempel inneholde et kall til rnusers()-prosedyren, som returnerer antall brukere på den eksterne maskinen. Du trenger ikke vite om bruk av RPC-mekanismen siden du ringer i programmet.

Mellomlaget er beregnet for de vanligste bruksområdene. RPC-anrop på dette nivået håndteres av subrutinene registerrpc() og callrpc(): registerrpc() mottar kode for hele systemet, og callrpc() utfører et eksternt prosedyrekall. Anropet rnusers() implementeres ved å bruke disse to rutinene.

Det lavere nivået brukes til mer komplekse oppgaver som endrer standardverdiene for prosedyreparametere. På dette nivået kan du eksplisitt manipulere kontaktene som brukes til å overføre RPC-meldinger.

Som en generell regel bør du bruke det øverste nivået og unngå å bruke de lavere nivåene med mindre det er absolutt nødvendig.

Selv om vi i denne opplæringen kun tar for oss C-grensesnittet, kan anrop til eksterne prosedyrer gjøres fra alle språk. Driften av RPC-mekanismen for å organisere kommunikasjon mellom prosesser på forskjellige maskiner er ikke forskjellig fra driften på én maskin.

RPC (Remote Procedure Call) er et grensesnitt mellom eksterne brukere og visse vertsprogrammer som startes på forespørsel fra disse brukerne. RPC-tjenesten til enhver vert gir som regel klienter et sett med programmer. Hvert av disse programmene består i sin tur av en eller flere fjernprosedyrer. For eksempel kan en ekstern NFS-filsystemtjeneste som er bygget på RPC-anrop bestå av bare to programmer: for eksempel samhandler det ene programmet med brukergrensesnitt på høyt nivå og det andre med I/O-funksjoner på lavt nivå.

Hvert eksternt prosedyrekall involverer to parter: den aktive klienten, som sender prosedyreanropsforespørselen til serveren, og serveren, som sender svaret til klienten.

Merk. Det bør huskes på at begrepene "klient" og "server" i dette tilfellet refererer til en spesifikk transaksjon.En bestemt vert eller programvare (prosess eller program) kan fungere som både klient og server. For eksempel kan et program som gir en ekstern prosedyretjeneste samtidig være en klient for arbeid med et nettverksfilsystem.

RPC-protokollen er bygget på en ekstern prosedyreanropsmodell, lik den lokale prosedyreanropsmekanismen. Når du kaller en lokal prosedyre, plasserer du argumenter på et bestemt sted i minnet, stabelen eller miljøvariabler, og overfører kontrollen over prosessen til en bestemt adresse. Når jobben er fullført, leser du resultatene på en bestemt adresse og fortsetter med prosessen.

Når du arbeider med en ekstern prosedyre, er hovedforskjellen at fjernfunksjonskallet håndteres av to prosesser: en klientprosess og en serverprosess.

Klientprosessen sender en melding til serveren, som inkluderer parametrene til den kalte prosedyren, og venter på en svarmelding med resultatene av arbeidet. Når et svar mottas, leses resultatet og prosessen fortsetter. På serversiden er samtalebehandlingsprosessen i en ventetilstand, og når en melding kommer, leser den parametrene for prosedyren, utfører den, sender et svar og blir i ventetilstand for neste samtale.

RPC-protokollen stiller ingen krav til ytterligere kommunikasjon mellom prosesser og krever ikke synkronisering av funksjonene som utføres, det vil si at anrop kan være asynkrone og gjensidig uavhengige, slik at klienten kan utføre andre prosedyrer mens de venter på svar. RPC-serveren kan tildele en separat prosess eller virtuell maskin for hver funksjon, derfor kan den, uten å vente på at tidligere forespørsler skal fullføres, umiddelbart godta de neste.

Det er imidlertid flere viktige forskjeller mellom lokale og eksterne prosedyreanrop:

1. Feil under behandling. I alle fall bør klienten motta varsling om feil som oppstår ved oppringing av eksterne prosedyrer på serveren eller nettverket.

2. Globale variabler. Fordi serveren ikke har tilgang til klientens adresserom, kan ikke eksterne prosedyrekall bruke skjulte parametere i form av globale variabler.

3. Opptreden. Hastigheten for å utføre eksterne prosedyrer er vanligvis en eller to størrelsesordener lavere enn hastigheten for å utføre lignende lokale prosedyrer.

4. Autentisering. Fordi eksterne prosedyrekall skjer over nettverket, må klientautentiseringsmekanismer brukes.

Prinsipper for protokollkonstruksjon.

RPC-protokollen kan bruke flere forskjellige transportprotokoller. Ansvaret til RPC-protokollen er kun å gi standarder og tolke overføringen av meldinger. Påliteligheten og påliteligheten til meldingsoverføring er helt og holdent sikret av transportlaget.

Imidlertid kan RPC kontrollere valget og noen funksjoner i transportprotokollen. Som et eksempel på interaksjonen mellom RPC og transportprotokollen, vurder prosedyren for å tilordne en RPC-port for en applikasjonsprosess som skal kjøres via RPC - Portmapper.

Denne funksjonen tilordner dynamisk (på forespørsel) en RPC-tilkobling til en spesifikk port. Funksjon Portmapper brukes ganske ofte fordi settet med transportporter reservert for RPC er begrenset, og antallet prosesser som potensielt kan kjøre samtidig er svært høyt. Portmapper kalles for eksempel når du velger porter for interaksjon mellom klienten og NFS-systemserveren.

Service Portmapper bruker en mekanisme for å kringkaste RPC-meldinger til en bestemt port - III. Klienten sender en kringkastingsmelding for portforespørsel for en spesifikk RPC-tjeneste til denne porten. Service Portmapper behandler skattemeldingen, bestemmer adressen til den lokale RPC-tjenesten og sender et svar til klienten. RPC-tjeneste Portmapper kan fungere med både TCP- og UDP-protokoller.

RPC kan fungere med ulike transportprotokoller, men dupliserer aldri funksjonene deres, det vil si at hvis RPC kjører på toppen av TCP, blir alle bekymringer om påliteligheten og gyldigheten til RPC-forbindelsen tildelt TCP. Men hvis RPC-protokollen er installert på toppen av UDP, kan den gi sine egne tilleggsfunksjoner for å sikre at meldingslevering er garantert.

Merk. Applikasjonsoppgaver kan vurdere RPC-protokollen som en spesifikk prosedyre for å kalle en funksjon over JSR-nettverket (Jump Subroutine Instruction).

For at RPC-protokollen skal fungere, må følgende betingelser være oppfylt:

1. Unik identifikasjon av alle eksternt kalte prosedyrer på en gitt vert. RPC-forespørsler inneholder tre identifikasjonsfelt - nummeret til det eksterne programmet (tjenesten), versjonsnummeret til det eksterne programmet og nummeret til fjernprosedyren til det spesifiserte programmet. Programnummeret er tildelt av serviceprodusenten, prosedyrenummeret indikerer den spesifikke funksjonen til denne tjenesten

2. Identifikasjon av RPC-protokollversjonen. RPC-meldinger inneholder et RPC-protokollversjonsfelt. Den brukes til å koordinere formatene til beståtte parametere når klienten jobber med forskjellige versjoner av RPC.

3. Tilbyr mekanismer for klientautentisering på serveren. RPC-protokollen gir en prosedyre for autentisering av klienten til tjenesten, og, om nødvendig, hver gang en forespørsel sendes eller et svar sendes til klienten. I tillegg tillater RPC bruk av ulike tilleggssikkerhetsmekanismer.

RPC kan bruke fire typer autentiseringsmekanismer:

AUTH_NULL - ingen autentisering kreves

AUTH_UNIX - autentisering i henhold til UNIX-standarden

AUTH_SHORT - UNIX standard autentisering med sin egen kodingsstruktur

AUTH_DES - autentisering i henhold til DES-standarden

4. Identifikasjon av svarmeldinger på tilsvarende forespørsler. RPC-svarmeldinger inneholder identifikatoren for forespørselen som de ble konstruert fra. Denne identifikatoren kan kalles RPC-anropstransaksjonsidentifikatoren. Denne mekanismen er spesielt nødvendig når du arbeider i asynkron modus og når du utfører en sekvens med flere RPC-anrop.

5. Identifikasjon av protokollfeil. Alle nettverks- eller serverfeil har unike identifikatorer, som hver av tilkoblingsdeltakerne kan finne årsaken til feilen med.

Protokollmeldingsstrukturer

Når du sender RPC-meldinger over en transportprotokoll, kan flere RPC-meldinger lokaliseres i en enkelt transportpakke. For å skille en melding fra en annen, brukes en rekordmarkør (RM - Record Marker). Hver RPC-melding er "merket" med nøyaktig én RM.

En RPC-melding kan bestå av flere fragmenter. Hvert fragment består av fire byte med header og (0 til 2**31-1) data. Den første biten i overskriften indikerer om fragmentet er det siste, og de resterende 31 bitene indikerer lengden på datapakken.

RPC-strukturen er formelt beskrevet på språket for å beskrive og representere dataformater - XDR med tillegg angående beskrivelse av prosedyrer. Du kan til og med si at RPC-beskrivelsesspråket er en utvidelse av XDR, supplert med arbeid med prosedyrer.

Strukturen til RPC-pakken ser slik ut:

struct rpc_msg (

usignert int xid;

union switch (msg_type mtype) (

call_body cbody;

svar kroppen rbody;

der xid er identifikatoren for gjeldende transaksjon, call_body er forespørselspakken, reply_body er svarpakken. Forespørselsstrukturen ser omtrent slik ut:

struct call body (

usignerte int rpcvers;

usignert int prog;

usignert int vers;

usignert int proc;

opaque_auth cred;

opaque_auth verf;

/* prosedyreparametere */

Svarstrukturen (reply_body) kan inneholde enten en feilstruktur (i så fall inneholder den feilkoden) eller en vellykket forespørselsbehandlingsstruktur (i så fall inneholder den returdataene).

Høynivå programvaregrensesnitt.

Å bruke subrutiner i et program er en tradisjonell måte å strukturere en oppgave og gjøre den klarere. De mest brukte rutinene er samlet i biblioteker hvor de kan brukes av ulike programmer. I dette tilfellet snakker vi om et lokalt (lokalt) anrop, det vil si at både det anropende og det anropte objektet fungerer innenfor samme program på samme datamaskin.

I tilfelle av et eksternt anrop, starter en prosess som kjører på én datamaskin en prosess på den eksterne datamaskinen (det vil si at den faktisk kjører prosedyrekode på den eksterne datamaskinen). Det er klart at et eksternt prosedyrekall skiller seg betydelig fra et tradisjonelt lokalt, men fra programmererens synspunkt er slike forskjeller praktisk talt fraværende, det vil si at arkitekturen til et eksternt prosedyrekall lar deg simulere et lokalt prosedyrekall.

Imidlertid, hvis programmet i tilfelle en lokal samtale sender parametere til den kalte prosedyren og mottar resultatet av arbeidet gjennom stabelen eller delte minneområder, blir overføringen av parametere i tilfelle av en ekstern samtale til overføring av en forespørsel over nettverket, og resultatet av arbeidet ligger i det mottatte svaret.

Denne tilnærmingen er et mulig grunnlag for å lage distribuerte applikasjoner, og selv om mange moderne systemer ikke bruker denne mekanismen, beholdes de grunnleggende konseptene og begrepene i mange tilfeller. Når vi beskriver RPC-mekanismen, vil vi tradisjonelt kalle anropsprosessen en klient, og den eksterne prosessen som implementerer prosedyren en server.

Et eksternt prosedyrekall innebærer følgende trinn:

1. Klientprogrammet foretar et lokalt anrop til en prosedyre som kalles en stubb. I dette tilfellet ser det ut til at klienten ved å ringe stubben faktisk kaller serverprosedyren. Faktisk sender klienten de nødvendige parameterne til stubben, og den returnerer resultatet. Men ting er ikke helt som klienten forestiller seg. Stubbens jobb er å akseptere argumentene som er beregnet på fjernprosedyren, eventuelt konvertere dem til et standardformat og formulere en nettverksforespørsel. Å pakke argumentene og lage nettverksforespørselen kalles rangering.

2. Nettverksforespørselen videresendes over nettverket til det eksterne systemet. For å gjøre dette bruker stubben passende anrop, for eksempel de som er diskutert i de forrige avsnittene. Merk at ulike transportprotokoller kan brukes, og ikke bare TCP/IP-familien.

3. På den eksterne verten skjer alt i omvendt rekkefølge. Serverstubben lytter etter en forespørsel og henter parametrene - argumentene til prosedyrekallet ved mottak. Unmarshalling kan innebære nødvendige transformasjoner (for eksempel byte-rekkefølgeendringer).

4. Stubben ringer til den virkelige serverprosedyren som klientens forespørsel er adressert til, og sender argumentene mottatt over nettverket.

5. Etter å ha fullført prosedyren, går kontrollen tilbake til serverstubben og gir den de nødvendige parameterne. Som klientstubben; Serverstubben konverterer verdiene som returneres av prosedyren, og genererer en nettverkssvarmelding som sendes over nettverket til systemet som forespørselen kom fra.

6. Operativsystemet sender den mottatte meldingen til klientstubben, som etter den nødvendige transformasjonen sender verdiene (som er verdiene som returneres av fjernprosedyren) til klienten, som oppfatter dette som en normal retur fra prosedyren.

Dermed, fra klientens synspunkt, ringer den til en ekstern prosedyre som den ville gjort for en lokal. Det samme kan sies om serveren: en prosedyre kalles på en standard måte, et bestemt objekt (serverstub) kaller en lokal prosedyre og mottar verdiene som returneres av den. Klienten behandler stubben som en anropbar serverprosedyre, og serveren behandler sin egen stubb som en klient.

Dermed utgjør stubber kjernen i RPC-systemet, ansvarlig for alle aspekter av meldingsgenerering og overføring mellom klienten og den eksterne serveren (prosedyre), selv om både klient og server tror at anropene skjer lokalt. Dette er det grunnleggende konseptet til RPC - å fullstendig skjule den distribuerte (nettverks) naturen til interaksjonen i stubbkoden. Fordelene med denne tilnærmingen er åpenbare: både klienten og serveren er uavhengig av nettverksimplementeringen, de opererer begge innenfor en distribuert virtuell maskin, og prosedyrekall har et standardgrensesnitt.

Passerer parametere

Passering av verdiparametere forårsaker ingen spesielle vanskeligheter. I dette tilfellet plasserer klientstubben parameterverdien i nettverksforespørselen, og utfører muligens konverteringer til standardformen (for eksempel reversering av byte-rekkefølgen). Situasjonen er mye mer komplisert med overføring av pekere, når parameteren representerer adressen til dataene, og ikke verdien. Å sende adressen i forespørselen er meningsløst, siden fjernprosedyren utføres i et helt annet adresserom. Den enkleste løsningen som brukes i RPC er å forby klienter å sende andre parametere enn etter verdi, selv om dette selvfølgelig medfører alvorlige begrensninger.

Binding

Før en klient kan kalle en ekstern prosedyre, må den være tilknyttet et eksternt system som er vert for den nødvendige serveren. Dermed deles den bindende oppgaven inn i to:

Finne en ekstern vert med den nødvendige serveren

Finne den nødvendige serverprosessen på en gitt vert

Ulike tilnærminger kan brukes for å finne verten. Et mulig alternativ er å lage en slags sentralisert katalog der verter annonserer sine servere, og hvor klienten, om ønskelig, kan velge verts- og prosedyreadressen som passer for ham.

Hver RPC-prosedyre er unikt identifisert av et program- og prosedyrenummer. Programnummeret identifiserer en gruppe eksterne prosedyrer, som hver har sitt eget nummer. Hvert program er også tildelt et versjonsnummer, slik at hvis du gjør mindre endringer i programmet (for eksempel legger til en prosedyre), er det ikke nødvendig å endre nummeret. Vanligvis implementeres flere funksjonelt like prosedyrer i én programvaremodul, som, når den startes, blir serveren for disse prosedyrene, og som identifiseres av programnummeret.

Derfor, når en klient ønsker å ringe en ekstern prosedyre, må den vite programmet, versjonen og prosedyrenumrene som gir den nødvendige tjenesten.

For å overføre en forespørsel, må klienten også kjenne vertsnettverksadressen og portnummeret som er knyttet til serverprogrammet som gir de nødvendige prosedyrene. Portmap(IM)-demonen brukes til dette (kalt rpcbind(IM) på noen systemer). Daemonen kjører på verten som tilbyr den eksterne prosedyretjenesten og bruker et velkjent portnummer. Når en serverprosess initialiseres, registrerer den sine prosedyrer og portnumre i portmap(IM). Nå, når en klient trenger å vite portnummeret for å ringe en spesifikk prosedyre, sender den en forespørsel til portmap(IM)-serveren, som i sin tur enten returnerer portnummeret eller videresender forespørselen direkte til den eksterne prosedyreserveren og, etter utfører det, returnerer et svar til klienten. I alle fall, hvis den nødvendige prosedyren eksisterer, mottar klienten prosedyreportnummeret fra portmap(IM)-serveren, og ytterligere forespørsler kan sendes direkte til denne porten.

Håndtering av spesielle situasjoner (unntak)

Å håndtere unntak ved tilkalling til lokale prosedyrer er ikke spesielt problematisk. UNIX gir behandling for prosessfeil som divisjon med null, tilgang til et ugyldig minneområde osv. Ved et eksternt prosedyrekall øker sannsynligheten for feilsituasjoner. I tillegg til server- og stubbfeil legges det til feil knyttet til for eksempel mottak av en feilaktig nettverksmelding.

For eksempel, når du bruker UDP som en transportprotokoll, sendes meldinger på nytt etter en viss tidsavbrudd. En feil returneres til klienten hvis det etter et visst antall forsøk ikke er mottatt svar fra serveren. I tilfellet der TCP-protokollen brukes, returneres en feil til klienten hvis serveren har lukket TCP-forbindelsen.

Ring semantikk

Å kalle en lokal prosedyre fører utvetydig til utførelse av den, hvoretter kontrollen går tilbake til hovedprogrammet. Situasjonen er annerledes når du ringer en ekstern prosedyre. Det er umulig å fastslå nøyaktig når prosedyren skal utføres, om den i det hele tatt skal utføres, og i så fall hvor mange ganger? For eksempel, hvis forespørselen mottas av det eksterne systemet etter at serverprogrammet har krasjet, vil ikke prosedyren bli utført i det hele tatt. Hvis klienten, når den ikke mottar et svar etter en viss tidsperiode (tidsavbrudd), sender forespørselen på nytt, kan det oppstå en situasjon når svaret allerede er overført over nettverket, og den gjentatte forespørselen blir igjen akseptert for behandling av fjernkontrollen fremgangsmåte. I dette tilfellet vil prosedyren utføres flere ganger.

Dermed kan utførelsen av en ekstern prosedyre karakteriseres av følgende semantikk:

- En gang og bare en gang. Denne oppførselen (i noen tilfeller den mest ønskelige) er vanskelig å kreve på grunn av mulige serverkrasj.

- Maksimal tid. Dette betyr at prosedyren enten ikke ble utført i det hele tatt eller bare ble utført én gang. En lignende uttalelse kan gjøres når du mottar en feil i stedet for et normalt svar.

- I hvert fall en gang. Prosedyren ble sannsynligvis utført en gang, men det er mulig flere. For å fungere normalt i en slik situasjon, må fjernprosedyren ha egenskapen idempotency (fra den engelske idemponent). Denne egenskapen besittes av en prosedyre hvis gjentatte utførelse ikke forårsaker kumulative endringer. For eksempel er det idempotent å lese en fil, men å legge til tekst i en fil er det ikke.

Datapresentasjon

Når klienten og serveren kjører på samme system på samme datamaskin, er det ingen datainkompatibilitetsproblemer. For både klienten og serveren er data i binær form representert på samme måte. Når det gjelder et eksternt anrop, kompliseres saken av det faktum at klienten og serveren kan kjøre på systemer med forskjellige arkitekturer, ha forskjellige datarepresentasjoner (for eksempel flytende kommarepresentasjon, byte-rekkefølge, etc.)

De fleste RPC-systemimplementeringer definerer en standard datarepresentasjon som alle verdier som sendes i forespørsler og svar må konverteres til.

For eksempel er formatet for å presentere data i RPC fra Sun Microsystems som følger:

Byte-rekkefølge - Mest betydningsfull - sist

Floating Point Representation - IEEE

Tegnrepresentasjon - ASCII

Når det gjelder funksjonalitet, inntar RPC-systemet en mellomplass mellom applikasjonslaget og transportlaget. I følge OSI-modellen tilsvarer denne posisjonen presentasjon og sesjonslag. Dermed er RPC teoretisk uavhengig av nettverksimplementeringen, spesielt av transportlagets nettverksprotokoller.

Programvareimplementeringer av systemet støtter som regel en eller to protokoller. For eksempel støtter RPC-systemet utviklet av Sun Microsystems meldingsoverføring ved hjelp av TCP- og UDP-protokollene. Valget av en eller annen protokoll avhenger av applikasjonskravene. Valget av UDP-protokollen er begrunnet for applikasjoner som har følgende egenskaper:

Kalte prosedyrer er idempotente

Størrelsen på de overførte argumentene og det returnerte resultatet er mindre enn størrelsen på UDP-pakken - 8 KB.

Serveren gir arbeid med flere hundre klienter. Siden serveren blir tvunget til å opprettholde en forbindelse med hver av de aktive klientene når man jobber med TCP-protokoller, tar dette opp en betydelig del av ressursene. UDP-protokollen er mindre ressurskrevende i denne forbindelse

På den annen side gir TCP effektiv drift av applikasjoner med følgende egenskaper:

Applikasjonen krever en pålitelig overføringsprotokoll

Kalte prosedyrer er ikke-identiske

Størrelsen på argumentene eller returresultatet overstiger 8 KB

Valget av protokoll overlates vanligvis til klienten, og systemet organiserer generering og overføring av meldinger på ulike måter. Når du bruker TCP-protokollen, for hvilken de overførte dataene er en strøm av byte, er det derfor nødvendig å skille meldinger fra hverandre. For dette formålet brukes for eksempel rekordmarkeringsprotokollen beskrevet i RFC1057 "RPC: Remote Procedure Call Protocol specification version 2", der et 32-bits heltall er plassert i begynnelsen av hver melding, som definerer størrelsen på meldingen i byte.

Situasjonen er annerledes med semantikken i samtalen. For eksempel, hvis RPC utføres ved hjelp av en upålitelig transportprotokoll (UDP), sender systemet meldingen på nytt med korte intervaller (timeouts). Hvis klientapplikasjonen ikke mottar svar, er det trygt å si at prosedyren har blitt utført null eller flere ganger. Dersom det mottas svar, kan søknaden konkludere med at prosedyren ble utført minst én gang. Ved bruk av en pålitelig transportprotokoll (TCP), hvis et svar mottas, kan prosedyren sies å ha blitt utført én gang. Hvis det ikke mottas svar, er det umulig å definitivt si at prosedyren ikke ble fullført3.

Hvordan det fungerer?

I hovedsak er selve RPC-systemet innebygd i klientprogrammet og serverprogrammet. Det er fint at når du utvikler distribuerte applikasjoner, trenger du ikke å fordype deg i detaljene i RPC-protokollen eller programmeldingsbehandling. Systemet forutsetter at det finnes et passende utviklingsmiljø, noe som i stor grad forenkler livet til applikasjonsprogramvareskapere. Et av nøkkelpunktene i RPC er at utviklingen av en distribuert applikasjon begynner med definisjonen av et objektgrensesnitt - en formell beskrivelse av serverens funksjoner, skrevet på et spesielt språk. Basert på dette grensesnittet genereres deretter klient- og serverstubber automatisk. Det eneste du trenger å gjøre etter dette er å skrive selve koden for prosedyren.

Som et eksempel kan du vurdere RPC fra Sun Microsystems. Systemet består av tre hoveddeler:

Rpcgen(1) er en RPC-kompilator som, basert på beskrivelsen av det eksterne prosedyregrensesnittet, genererer klient- og serverstubber i form av C-programmer.

XDR-biblioteket (eXternal Data Representation), som inneholder funksjoner for å konvertere ulike datatyper til en maskinuavhengig form som tillater informasjonsutveksling mellom heterogene systemer.

Et bibliotek med moduler som sikrer driften av systemet som helhet.

La oss se på et eksempel på en enkel distribuert hendelseslogging-applikasjon. Når klienten starter, kaller den en ekstern prosedyre for å skrive en melding til loggfilen til den eksterne datamaskinen.

For å gjøre dette må du opprette minst tre filer: spesifikasjonen av grensesnittene til den eksterne prosedyren log.x (i grensesnittbeskrivelsesspråket), den faktiske teksten til den eksterne prosedyren log.c og teksten til hovedprosedyren. klientprogram hoved () - klient.c (på C-språk).

rpcgen(l)-kompilatoren oppretter tre filer basert på log.x-spesifikasjonen: teksten til klient- og serverstubbene i C (log clnt.c og log svc.c) og beskrivelsesfilen log.h, brukt av begge stubbene .

Så la oss se på kildekodene til programmene.

Denne filen spesifiserer registreringsparametrene for den eksterne prosedyren - program-, versjons- og prosedyrenumre, og definerer også anropsgrensesnittet - input-argumenter og returverdier. Dermed er en RLOG-prosedyre definert som tar en streng som et argument (som vil bli skrevet til loggen), og returverdien indikerer standard suksess eller fiasko for den bestilte operasjonen.

program LOG_PROG (

versjon LOG_VER (

int RLOG(streng) = 1;

) = 0x31234567;

rpcgen(l)-kompilatoren oppretter en overskriftsfil log.h, hvor spesielt prosedyrene er definert:

log.h

* Vennligst ikke rediger denne filen.

* Den ble generert ved hjelp av rpcgen.

#ifndef _LOG_H_RPCGEN

#define_LOG_H_RPCGEN

#inkludere

/* Programnummer*/

#define LOG_PROG ((lang uten fortegn) (0x31234567))

#define LOG_VER ((usignert lang) (1)) /*Versjonsnummer*/

#define RLOG ((usignert lang) (1)) /*Prosedyrenummer*/

ekstern int *rlog_l ();

/*Intern prosedyre - vi trenger ikke å bruke den*/ extern int log_prog_l_freeresult();

#endif /* !_LOG_H_RPCGEN */

La oss se nøye på denne filen. Kompilatoren oversetter RLOG-navnet definert i grensesnittbeskrivelsesfilen til rlog_1, erstatter store bokstaver med små bokstaver og legger til programversjonsnummeret med en understreking. Returtypen har endret seg fra int til int*. Dette er regelen - RPC lar deg overføre og motta bare adressene til parameterne som er deklarert når du beskriver grensesnittet. Den samme regelen gjelder for strengen som sendes som et argument. Selv om det ikke vises fra print.h, sender funksjonen rlog_l() faktisk adressen til strengen som et argument.

I tillegg til header-filen, produserer rpcgen(l)-kompilatoren klientstub- og serverstubmoduler. Teksten til disse filene inneholder i hovedsak all koden for fjernsamtalen.

Serverstubben er hovedprogrammet som håndterer alle nettverksinteraksjoner med klienten (mer presist, med stubben). For å utføre operasjonen foretar serverstubben et lokalt funksjonsanrop, hvis tekst må skrives:

log.c

#inkludere

#inkludere

#inkludere

#include "log.h"

int *rlog_1 (char **arg)

/*Returverdi må defineres som statisk*/

statisk int resultat;

int fd; /*Loggfilbeskrivelse*/

/*0åpne loggfilen (opprett den hvis den ikke eksisterer), hvis den ikke lykkes, returner feilkoderesultatet == 1.*/

if ((fd=open("./server .log",

O_CREAT | O_RDWR | O_APPEND))< 0) return (&result);

len = strlen(*arg);

if (skriv(fd, *arg, strlen(*arg)) != len)

return(&result); /*Returner resultatet - adresseresultat*/

Klientstubben godtar argumentet som sendes til den eksterne prosedyren, utfører de nødvendige konverteringene, sender en forespørsel til portmap(1M)-serveren, kommuniserer med den eksterne prosedyreserveren og sender til slutt returverdien til klienten. For klienten reduseres et anrop til en ekstern prosedyre til et anrop til en stubb og er ikke forskjellig fra en vanlig lokal samtale.

klient.c

#inkludere

#include "log.h"

main(int argc, char *argv)

char *server, *mystring, *clnttime;

if (argc != 2) (

fprintf(stderr, "Anropsformat: %s vertsadresse\n",

/*Få klientbeskrivelsen. Ved svikt vil vi informere deg om

umulig å etablere en forbindelse med serveren */

if ((c1 = clnt_create(server,

LOG_PROG, LOG_VER, "udp")) == NULL) (

clnt_pcreateerror(server);

/*Tildel en buffer for linjen*/

mystring = (char *)malloc(100);

/* Bestem tidspunktet for hendelsen*/

bintime = tid ((tid_t *) NULL);

clnttime = ctime(&bintime);

sprintf (mystring, "%s - Klient startet", clnttime);

/*Send en melding for loggen - tidspunktet klienten begynte å jobbe. Hvis det ikke lykkes, vil vi rapportere en feil*/

if ((resultat = rlog_l(&mystring, cl)) == NULL) (

fprintf(stderr, "feil2\n");

clnt_perror(cl, server);

/*I tilfelle feil på den eksterne datamaskinen, vil vi rapportere en feil*/

hvis (*resultat !=0)

fprintf(stderr, "Loggingsfeil\n");

/*0frigjør håndtaket*/

cint ødelegge(cl);

Klientstubben log_clnt.c er kompilert med client.c-modulen for å produsere et kjørbart klientprogram.

cc -o rlog client.c log_clnt.c -Insl

Serverstubben log_svc.c og prosedyre log.c er kompilert for å produsere et kjørbart serverprogram.

cc -o logger log_svc.c log.c -Insl

Nå på en eller annen vert server.nowhere.ru må du starte en serverprosess:

Deretter, når du kjører rlog-klienten på en annen maskin, vil serveren legge til en tilsvarende oppføring i loggfilen.

RPC-operasjonsdiagrammet i dette tilfellet er vist i fig. 1. Moduler samhandler som følger:

1. Når serverprosessen starter, oppretter den en UDP-socket og binder enhver lokal port til den kontakten. Deretter kaller serveren bibliotekfunksjonen svc_register(3N) for å registrere programnummer og versjoner. For å gjøre dette kaller funksjonen portmap(IM)-prosessen og sender de nødvendige verdiene. Portmap(IM)-serveren startes vanligvis når systemet initialiseres og binder seg til en velkjent port. Nå vet portmap(3N) portnummeret for vårt program og versjon. Serveren venter på å motta forespørselen. Legg merke til at alle de beskrevne handlingene utføres av en serverstub opprettet av rpcgen(IM)-kompilatoren.

2. Når rlog-programmet starter, er det første det gjør å kalle bibliotekfunksjonen clnt_create(3N), og gi den den eksterne systemadressen, program- og versjonsnumrene og transportprotokollen. Funksjonen sender en forespørsel til portmap(IM)-serveren til det eksterne systemet server.nowhere.m og henter det eksterne portnummeret for loggserveren.

3. Klienten kaller rlog_1()-prosedyren definert i klientstubben og overfører kontrollen til stubben. Det genererer i sin tur en forespørsel (konverterer argumentene til XDR-format) i form av en UDP-pakke og sender den til den eksterne porten mottatt fra portmap-serveren (IM). Den venter deretter på svar en stund, og hvis den ikke mottas, sender den forespørselen på nytt. Under gunstige omstendigheter aksepteres forespørselen av loggerserveren (serverstubmodul). Stubben bestemmer hvilken funksjon som ble kalt (ved prosedyrenummer) og kaller opp rlog_1()-funksjonen til log.c-modulen. Etter at kontroll returnerer til stubben, konverterer sistnevnte verdien returnert av rlog_1()-funksjonen til XDR-format, og genererer et svar også i form av en UDP-pakke. Etter å ha mottatt svaret, trekker klientstubben ut den returnerte verdien, transformerer den og returnerer den til klientens vertsprogram.