Warum C++-Mikroservices nicht mit dem Netzwerk befreundet sind (und wie Service Mesh das behebt)
\n\nStellen Sie sich vor: Sie haben eine perfekte Pipeline in C++ gebaut. Jeder Mikroservice fliegt, der Speicher wird streng verwaltet und die Geschwindigkeit ist jenseits von Gut und Böse. Aber sobald Sie das Ganze in Kubernetes starten, beginnt die Hölle. Timeouts, Wiederholungen, Verbindungsabbrüche, Paketverluste. Sie kriechen in den Code, fügen curl in jede Ecke ein, schreiben Ihre eigenen Fahrräder für Wiederholungen – und das Projekt verwandelt sich in einen Sumpf.
Kommt Ihnen bekannt vor? Willkommen in der Welt der verteilten Systeme. Die gute Nachricht: Das Problem löst Service Mesh. Die schlechte: Die meisten Tutorials sind für Go oder Java geschrieben. Aber was tun wir, C++-Entwickler, die kein schweres Istio mit Envoy schleppen wollen, wenn wir eine leichte und verständliche Lösung bauen können?
\n\nIn diesem Artikel werden wir besprechen, wie Sie Service Mesh für C++-Mikroservices ohne Schmerzen und überflüssige Abhängigkeiten einführen. Sie erfahren, was ein Sidecar-Proxy ist, wie Sie Lastverteilung und Observability konfigurieren, und erhalten ein reales Codebeispiel in C++ mit gRPC.
\n\nWas ist Service Mesh und warum brauchen es C++-Projekte?
\n\nService Mesh ist eine dedizierte Infrastrukturschicht zur Verwaltung des Netzwerkverkehrs zwischen Mikroservices. Anstatt die Logik für Timeouts, Wiederholungen, Lastverteilung und Verschlüsselung in jeden Dienst einzubetten, lagern Sie sie in einen Proxy-Container (Sidecar) aus, der neben jeder Instanz Ihres Dienstes läuft.
\n\nFür C++ ist das besonders relevant, weil:
\n- \n
- C++-Code wird normalerweise für High-Load-Systeme geschrieben, bei denen jede Mikrosekunde zählt; \n
- Eingebettete Netzwerklogik erschwert die Wartung und das Testen; \n
- Die Standardbibliothek von C++ bietet keine vorgefertigten Mechanismen für Service Mesh (im Gegensatz zu Go mit seinen standardmäßigen HTTP-Clients). \n
Die Hauptkomponenten von Service Mesh:
\n- \n
- Data Plane – Proxy-Server (normalerweise Envoy, aber auch eigene in C++ möglich); \n
- Control Plane – Verwaltungsebene (z. B. Istio, Consul oder selbst geschrieben). \n
Wir konzentrieren uns auf die Data Plane, denn hier zeigt C++ seine Stärke.
\n\nSchreiben eines eigenen Sidecar-Proxys in C++ (minimales Beispiel)
\n\nAngenommen, wir haben zwei Mikroservices: auth_service und user_service. Sie kommunizieren über gRPC. Ohne Service Mesh muss jeder Dienst selbst Wiederherstellungsversuche, Timeouts und Metriken verarbeiten. Mit Proxy nicht.
Hier ist ein minimales Beispiel eines Sidecar-Proxys in C++ unter Verwendung der Bibliotheken libcurl und nlohmann/json. Er nimmt HTTP-Anfragen entgegen, leitet sie an das Backend weiter, fügt Wiederholungen hinzu und protokolliert Verzögerungen.
// proxy.cpp\n#include <httplib.h>\n#include <nlohmann/json.hpp>\n#include <curl/curl.h>\n#include <chrono>\n#include <thread>\n\nusing json = nlohmann::json;\nusing namespace std::chrono_literals;\n\nclass SidecarProxy {\npublic:\n SidecarProxy(const std::string& backend_host, int backend_port, int max_retries = 3)\n : backend_host_(backend_host), backend_port_(backend_port), max_retries_(max_retries) {}\n\n void handle_request(const httplib::Request& req, httplib::Response& res) {\n auto start = std::chrono::high_resolution_clock::now();\n CURL* curl = curl_easy_init();\n std::string url = "http://" + backend_host_ + ":" + std::to_string(backend_port_) + req.path;\n curl_easy_setopt(curl, CURLOPT_URL, url.c_str());\n curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);\n\n std::string response_string;\n curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](void* ptr, size_t size, size_t nmemb, void* stream) {\n ((std::string*)stream)->append((char*)ptr, size * nmemb);\n return size * nmemb;\n });\n curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);\n\n int retries = 0;\n CURLcode code;\n d