Bramy API i wykrywanie usług
Dynamicznie kieruj żądania, agreguj dane i lokalizuj usługi
Bramy API i wykrywanie usług to bezpłatna lekcja PHP Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej PHP Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs PHP Academy zawiera 4 lekcji w sumie.
Bramy i wykrywanie usług
Gdy mają już Państwo kilkanaście usług, pojawiają się dwa problemy. Klienci nie powinni znać adresu każdej usługi ani wywoływać pięciu z nich, aby wyrenderować jeden ekran — tym zajmuje się brama API. Z kolei usługi, które skalują się w górę i w dół oraz zmieniają adresy IP, potrzebują sposobu na wzajemne odnajdywanie się — to właśnie wykrywanie usług.
W tej lekcji omówimy oba zagadnienia, używając PHP na warstwie bramy.
Co robi brama API
Brama API to pojedynczy punkt wejścia znajdujący się przed Państwa usługami. Typowe zadania:
- Routing żądań do właściwego backendu.
- Przekrojowe zagadnienia: uwierzytelnianie, ograniczanie częstotliwości żądań, CORS, terminowanie TLS.
- Agregacja: połączenie kilku wywołań backendu w jedną odpowiedź dla klienta.
- Translacja protokołów: zewnętrzny REST na wejściu, wewnętrzne gRPC na wyjściu.
Dzięki temu klienci pozostają prości, a zasady, które w przeciwnym razie trzeba byłoby powielać w każdej usłudze, są scentralizowane.
Routing na brzegu sieci
W swojej istocie brama mapuje przychodzącą ścieżkę na usługę upstream. Bramy używane w produkcji (Kong, Traefik, Nginx, AWS API Gateway) robią to deklaratywnie, ale logika jest na tyle prosta, że można ją zilustrować w PHP.
<?php
$routes = [
'#^/api/orders#' => 'http://orders-svc',
'#^/api/customers#' => 'http://customers-svc',
'#^/api/catalog#' => 'http://catalog-svc',
];
function resolveUpstream(string $path, array $routes): ?string {
foreach ($routes as $pattern => $upstream) {
if (preg_match($pattern, $path)) {
return $upstream . $path;
}
}
return null; // 404 at the gateway
}
echo resolveUpstream('/api/orders/42', $routes), "\n";Centralizacja uwierzytelniania
Zweryfikujcie wywołującego raz, na bramie, a następnie przekażcie do dalszych usług zaufaną tożsamość, aby każda z nich nie musiała ponownie weryfikować surowego tokenu. Brama sprawdza podpis i ważność JWT, a następnie wstrzykuje do wewnętrznego żądania nagłówki takie jak X-User-Id (w zaufanej sieci).
<?php
function authenticate(string $authHeader): ?array {
if (!str_starts_with($authHeader, 'Bearer ')) return null;
$jwt = substr($authHeader, 7);
$claims = verifyJwt($jwt); // signature + exp check
if ($claims === null) return null;
// Forward minimal trusted identity to internal services
return ['X-User-Id' => $claims['sub'], 'X-Scopes' => implode(',', $claims['scopes'])];
}
function verifyJwt(string $j): ?array { return ['sub' => 'u-7', 'scopes' => ['orders:read']]; }
print_r(authenticate('Bearer abc.def.ghi'));Agregowanie odpowiedzi
Ekran mobilny może potrzebować danych dotyczących zamówienia, klienta i katalogu. Zamiast zmuszać klienta do wykonania trzech wywołań, brama rozsyła żądania do wielu usług, czeka na odpowiedzi i je scala. Aby zachować wysoką szybkość działania, należy wykonywać wywołania usług upstream równolegle (obietnice Guzzle / curl_multi), a nie sekwencyjnie.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Promise\Utils;
$http = new Client(['timeout' => 2.0]);
$promises = [
'order' => $http->getAsync('http://orders-svc/orders/42'),
'customer' => $http->getAsync('http://customers-svc/customers/7'),
'catalog' => $http->getAsync('http://catalog-svc/items?order=42'),
];
$results = Utils::settle($promises)->wait(); // run in parallel
// merge the fulfilled bodies into one response for the clientBackendy dla frontendów
Jedna ogólna brama często nie jest w stanie równie dobrze obsłużyć aplikacji webowej, mobilnej i partnerów — każdy z tych klientów potrzebuje innych agregacji oraz struktur danych. Wzorzec Backend for Frontend (BFF) zapewnia każdemu typowi klienta własną, cienką bramę dopasowaną do jego potrzeb, podczas gdy współdzielone usługi pozostają ogólne.
Pozwala to uniknąć nadmiernie rozbudowanej bramy centralnej i umożliwia niezależną pracę poszczególnych zespołów klienckich.
Problem wykrywania usług
W dynamicznym środowisku instancje pojawiają się i znikają, a ich adresy IP się zmieniają. Wpisanie na stałe adresu http://10.0.3.14:8080 jest rozwiązaniem kruchym. Wykrywanie usług utrzymuje aktualny rejestr odpowiedzi na pytanie: "które zdrowe instancje usługi X są obecnie dostępne?", dzięki czemu wywołujący może w chwili wywołania przekształcić nazwę logiczną w rzeczywisty adres.
Wykrywanie po stronie klienta a po stronie serwera
Istnieją dwa modele:
- Po stronie klienta — wywołujący odpyta rejestr (Consul, etcd), sam wybierze instancję i zajmie się równoważeniem obciążenia.
- Po stronie serwera — wywołujący korzysta ze stabilnego adresu wirtualnego (modułu równoważenia obciążenia / Kubernetes Service), który rozwiązuje adres i równoważy obciążenie w jego imieniu.
W Kubernetes zwykle otrzymują Państwo wykrywanie po stronie serwera bez dodatkowej konfiguracji: wystarczy wywołać http://customers-svc, a DNS klastra i Service zajmą się resztą. Poza Kubernetesem często stosuje się rejestry w stylu Consula.
Odpytywanie rejestru
W przypadku wykrywania po stronie klienta wywołujący napisany w PHP pyta rejestr o zdrowe instancje i wybiera jedną z nich. Rejestr zwraca wyłącznie instancje, które przechodzą kontrole stanu zdrowia, więc niedziałające węzły są automatycznie wykluczane.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
function discover(Client $http, string $service): string {
// Consul: only passing-health instances
$res = $http->get("http://consul:8500/v1/health/service/$service?passing=true");
$nodes = json_decode((string) $res->getBody(), true);
if (!$nodes) throw new \RuntimeException("No healthy $service");
$pick = $nodes[array_rand($nodes)]['Service']; // simple LB
return "http://{$pick['Address']}:{$pick['Port']}";
}Kontrole stanu zdrowia i rejestracja
Skuteczność wykrywania usług zależy od jakości danych o ich stanie. Każda usługa udostępnia punkt końcowy /health, który sprawdza jej rzeczywiste zależności (bazę danych, pamięć podręczną), a następnie rejestruje się przy uruchomieniu (lub jest rejestrowana przez platformę). Rejestr odpytuje ten punkt końcowy i usuwa niesprawne instancje.
Kontrola stanu zdrowia musi mieć praktyczne znaczenie: zwracanie 200, gdy baza danych nie działa, jest gorsze niż bezużyteczne — kieruje ruch do uszkodzonego węzła.
<?php
// GET /health
function health(PDO $db, Redis $cache): array {
$checks = [
'db' => safe(fn() => $db->query('SELECT 1') !== false),
'cache' => safe(fn() => $cache->ping() === '+PONG'),
];
$ok = !in_array(false, $checks, true);
http_response_code($ok ? 200 : 503);
return ['status' => $ok ? 'pass' : 'fail', 'checks' => $checks];
}
function safe(callable $c): bool { try { return (bool) $c(); } catch (\Throwable) { return false; } }Liveness a readiness
Jeden punkt końcowy kontroli stanu zdrowia nie wystarczy — należy rozróżnić dwa pytania:
- Liveness: "czy proces działa?" Jeśli kontrola się nie powiedzie, orkiestrator restartuje kontener. Kontrola powinna być tania i niezależna od zależności, ponieważ niestabilna baza danych mogłaby wywoływać niepotrzebne restarty.
- Readiness: "czy proces może w tej chwili obsługiwać ruch?" Jeśli kontrola się nie powiedzie, ruch jest wstrzymywany, ale proces nadal działa (na przykład podczas rozgrzewania pamięci podręcznej lub tymczasowej niedostępności bazy danych).
Mylenie tych pojęć prowadzi do pętli restartów albo kierowania ruchu do węzłów, które nie są jeszcze gotowe.
<?php
// GET /livez - is the process itself healthy? (no external deps)
function livez(): void { http_response_code(200); echo 'alive'; }
// GET /readyz - should we receive traffic? (checks dependencies)
function readyz(PDO $db): void {
try { $db->query('SELECT 1'); http_response_code(200); echo 'ready'; }
catch (\Throwable) { http_response_code(503); echo 'not ready'; }
}Szybkie sprawdzenie
Ograniczanie liczby żądań wysyłanych przez klienta.
Podsumowanie
Routing i lokalizowanie usług:
- Brama API centralizuje routing, uwierzytelnianie, ograniczanie częstotliwości żądań, TLS i agregację.
- Agregujcie współbieżnie; używajcie BFF-ów, gdy potrzeby klientów się różnią.
- Wykrywanie usług przekształca nazwy logiczne w działające, zdrowe instancje.
- Wykrywanie po stronie klienta (odpytywanie rejestru) a po stronie serwera (stabilny moduł równoważenia obciążenia / Service Kubernetes).
- Praktyczne kontrole stanu zdrowia nie pozwalają kierować ruchu do uszkodzonych węzłów.
Następnie: zapewnienie odporności wszystkich tych wywołań na nieuniknione awarie poszczególnych elementów.
Często zadawane pytania
Czy lekcja „Bramy API i wykrywanie usług” jest bezpłatna?
Tak — pełny tekst „Bramy API i wykrywanie usług” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu PHP Academy, przejdź na CoddyKit PRO. Kurs PHP Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Bramy API i wykrywanie usług”?
Dynamicznie kieruj żądania, agreguj dane i lokalizuj usługi Ćwiczysz PHP Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć PHP Academy?
Nie wymagamy żadnego doświadczenia. PHP Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Bramy API i wykrywanie usług”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji PHP Academy?
Tak. Każda lekcja PHP Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Od monolitu do mikroserwisów
- Komunikacja usług: REST i gRPC
- Bramy API i wykrywanie usług
- Odporność: circuit breakery i ponowienia