RPC – Remote Procedure Call (Zdalne Wywołanie Procedury)
Remote Procedure Call (skrót RPC) to model komunikacji w systemach rozproszonych, w którym program wywołuje procedurę lub metodę znajdującą się na innym komputerze tak, jakby była ona wywoływana lokalnie. Dzięki abstrakcji warstwy transportowej i szczegółów sieciowych, programista może skupić się na logice aplikacji, nie martwiąc się o ręczne kodowanie komunikatów sieciowych.
Historia
Pierwsze koncepcje RPC pojawiły się na początku lat 1970 w projektach ARPANET. W 1985 firma Sun Microsystems zaprezentowała protokół SUN‑RPC, który stał się podstawą wielu kolejnych implementacji. W kolejnych dekadach rozwijano różne warianty, m.in. XML‑RPC (1998), JSON‑RPC (2005) oraz bardziej nowoczesny gRPC (od 2015).
Podstawowe założenia
- Ukrycie szczegółów sieciowych – wywołujący nie wie, czy procedura jest lokalna, czy zdalna.
- Proceduralny interfejs – wywołanie przyjmuje argumenty i zwraca wynik, podobnie jak tradycyjna funkcja.
- Transmisja danych – argumenty i wyniki są serializowane (marshalling) i deserializowane (unmarshalling) przed i po przesłaniu.
- Model synchroniczny i asynchroniczny – klasyczne RPC działa synchronicznie (wywołujący czeka), ale istnieją także asynchroniczne warianty.
Architektura RPC
Typowy system RPC składa się z czterech głównych warstw:
- Client Stub (kod po stronie wywołującego) – konwertuje wywołanie procedury na komunikat sieciowy.
- Transport Layer – np. TCP, UDP lub HTTP.
- Server Stub (kod po stronie serwera) – odczytuje komunikat, wywołuje rzeczywistą procedurę i zwraca wynik.
- Procedura docelowa – faktyczna funkcja lub metoda implementowana w aplikacji serwera.
Identyfikatory języków i definicja interfejsu
Wiele implementacji RPC wykorzystuje IDL (Interface Definition Language) do opisania dostępnych metod, ich parametrów oraz typów zwracanych danych. Przykładowe IDL:
interface Kalkulator {
int Dodaj(int a, int b);
double Podziel(double licznik, double mianownik);
}
Popularne protokoły i biblioteki
- XML‑RPC – oparty na XML i HTTP, prosty, lecz dość ciężki pod względem rozmiaru komunikatów.
- JSON‑RPC – lekki, używa JSON jako formatu serializacji.
- gRPC – rozwinięcie RPC oparte na Protocol Buffers, wspiera wiele języków, komunikację strumieniową i TLS.
- Apache Thrift – platforma RPC z własnym IDL, obsługuje różne protokoły transportowe i formaty kodowania.
- WCF (Windows Communication Foundation) – rozwiązanie Microsoftu integrujące RPC z innymi modelami komunikacji.
Zastosowania
RPC jest wykorzystywane w wielu dziedzinach informatyki:
- Usługi sieciowe – mikroserwisy komunikują się ze sobą przy pomocy gRPC lub JSON‑RPC.
- Systemy operacyjne – np. DCE/RPC w systemach Windows i Unix.
- Rozproszone bazy danych – wywołania operacji na węzłach klastra.
- Systemy czasu rzeczywistego – asynchroniczne RPC w aplikacjach IoT.
Zalety i wady
| Zalety | Wady |
|---|---|
|
|
Porównanie z innymi modelami komunikacji
W przeciwieństwie do REST, które operuje na zasobach i wykorzystuje metody HTTP, RPC koncentruje się na wywoływaniu metod. Model ten jest bardziej zbliżony do tradycyjnego wywoływania funkcji, co może upraszczać projektowanie API, ale jednocześnie wprowadza silniejsze powiązanie między klientem a serwerem.
Przyszłość RPC
Obecnie największy rozgłos zdobywa gRPC ze względu na wydajność, wsparcie dla strumieniowania i integrację z ekosystemem Kubernetes. Wraz z rosnącą popularnością mikroserwisów oraz chmur obliczeniowych, model RPC pozostaje kluczowym elementem architektur rozproszonych.
Przykładowe użycie gRPC w języku Python
# plik: kalkulator.proto
syntax = "proto3";
service Kalkulator {
rpc Dodaj (Para) returns (Wynik);
}
message Para {
int32 a = 1;
int32 b = 2;
}
message Wynik {
int32 wynik = 1;
}
Po wygenerowaniu kodu przy pomocy protoc, serwer może wyglądać tak:
import grpc
from concurrent import futures
import kalkulator_pb2
import kalkulator_pb2_grpc
class KalkulatorServicer(kalkulator_pb2_grpc.KalkulatorServicer):
def Dodaj(self, request, context):
return kalkulator_pb2.Wynik(wynik=request.a + request.b)
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
kalkulator_pb2_grpc.add_KalkulatorServicer_to_server(KalkulatorServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
Bibliografia i dalsza lektura
- W. Birrell i B. Nelson, Implementing Remote Procedure Calls, ACM SIGOPS Operating Systems Review, 1984.
- J. Lloyd, gRPC: A High Performance, Open Source Universal RPC Framework, 2015.
- Dokumentacja gRPC oraz Protocol Buffers.