Sofortantwort
gRPC einfach erklärt
Hochperformantes RPC-Framework für Microservices-Kommunikation.
- Kurz gesagt
- Binäres Protokoll (Protocol Buffers) statt JSON – oft kompakter und effizienter
- Typischer Einsatz
- Microservices-Kommunikation, Mobile Backends, Real-Time Streaming
- Wichtig zu wissen
- Bidirektionales Streaming für Echtzeit-Kommunikation
gRPC im Überblick
gRPC ist ein Framework für Remote Procedure Calls – du rufst Funktionen auf einem anderen Server auf, als wären sie lokal. Es kann effizienter als JSON-basierte REST-Kommunikation sein, weil es Protocol Buffers und HTTP/2 nutzt.
REST vs. gRPC:
| Aspekt | REST | gRPC |
|---|---|---|
| Format | JSON (Text) | Protocol Buffers (Binär) |
| Protokoll | HTTP/1.1 oder 2 | HTTP/2 |
| Typisierung | Optional (OpenAPI) | Pflicht (.proto) |
| Streaming | je nach Technik zusätzlicher Aufwand | native Unterstützung |
| Performance | gut, setupabhängig | oft sehr gut, setupabhängig |
| Browser-Support | Ja | Eingeschränkt |
Beispiel – User-Service:
// user.proto
syntax = "proto3";
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (stream User);
}
message GetUserRequest {
int32 id = 1;
}
message User {
int32 id = 1;
string name = 2;
string email = 3;
}
Aufruf (Python):
response = stub.GetUser(GetUserRequest(id=user_id))
print(response.name)
Technisch betrachtet
Protocol Buffers
Schema definieren:
syntax = "proto3";
package myapp;
message Product {
int32 id = 1;
string name = 2;
double price = 3;
repeated string tags = 4; // Array
optional string description = 5;
enum Status {
UNKNOWN = 0;
ACTIVE = 1;
DISCONTINUED = 2;
}
Status status = 6;
}
Code generieren:
protoc --python_out=. --grpc_python_out=. product.proto
Generiert typsichere Klassen für unterstützte Programmiersprachen.
Streaming-Patterns
1. Unary (Standard):
rpc GetUser(Request) returns (Response);
Ein Request → Eine Response
2. Server Streaming:
rpc ListUsers(Request) returns (stream User);
Ein Request → Viele Responses
3. Client Streaming:
rpc UploadChunks(stream Chunk) returns (Response);
Viele Requests → Eine Response
4. Bidirectional Streaming:
rpc Chat(stream Message) returns (stream Message);
Viele Requests ↔ Viele Responses (gleichzeitig)
Server-Implementierung (Python)
import grpc
from concurrent import futures
import user_pb2
import user_pb2_grpc
class UserServicer(user_pb2_grpc.UserServiceServicer):
def GetUser(self, request, context):
user = db.get_user(request.id)
if not user:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details('User not found')
return user_pb2.User()
return user_pb2.User(
id=user.id,
name=user.name,
email=user.email
)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=max_workers))
user_pb2_grpc.add_UserServiceServicer_to_server(UserServicer(), server)
server.add_insecure_port(server_address)
server.start()
server.wait_for_termination()
Client-Implementierung
import grpc
import user_pb2
import user_pb2_grpc
channel = grpc.insecure_channel(server_address)
stub = user_pb2_grpc.UserServiceStub(channel)
# Unary Call
response = stub.GetUser(user_pb2.GetUserRequest(id=user_id))
# Server Streaming
for user in stub.ListUsers(user_pb2.ListUsersRequest()):
print(user.name)
Error Handling
try:
response = stub.GetUser(request)
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND:
print("User not found")
elif e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
print("Timeout")
else:
print(f"Error: {e.details()}")
gRPC vs. REST – Wann was?
| Szenario | Empfehlung |
|---|---|
| Öffentliche API | häufig REST oder GraphQL |
| Browser-Client | häufig REST / GraphQL oder gRPC-Web |
| Interne Microservices | häufig gRPC |
| Mobile mit begrenztem Netz | gRPC kann sinnvoll sein |
| Real-Time Streaming | gRPC kann sinnvoll sein |
| Einfaches CRUD | häufig REST |
| Polyglotte Services | gRPC kann sinnvoll sein |