Guerra dei Runtimes di Symfony: Un’Odyssey delle prestazioni
9 Febbraio 2024
Nel sempre mutante panorama dello sviluppo di applicazioni web, le complessità sorgono man mano che emergono nuove tecnologie. Questa rapida trasformazione offre agli sviluppatori una vasta gamma di opzioni, ma introduce anche sfide nel fare le scelte giuste. Symfony, essendo un framework PHP flessibile e potente per le applicazioni web, offre agli sviluppatori una vasta gamma di opzioni di runtime. Tuttavia, fare la scelta corretta tra queste opzioni è cruciale per le prestazioni, la scalabilità e la facilità di manutenzione di un’applicazione.
Criteri di Selezione del Runtime
Sicuramente, quando si sceglie un runtime, le prestazioni sono senza dubbio un elemento cruciale, ma non dipendono solo dalle prestazioni. Altri fattori significativi includono:
-
Esperienza dello Sviluppatore: La scelta del runtime influenza l’esperienza dello sviluppatore. Gli sviluppatori possono lavorare in modo più efficace quando utilizzano un runtime che si allinea bene alle loro preferenze. Fattori come strumenti di monitoraggio user-friendly, capacità di debug e documentazione influenzano significativamente l’esperienza dello sviluppatore.
-
Supporto della Comunità ed Ecosistema: La presenza di una forte comunità e di un vasto ecosistema di supporto dietro un runtime fornisce agli sviluppatori un accesso più facile alle risorse e una risoluzione più rapida dei problemi. I runtime supportati dalla comunità possono avere vantaggi in termini di aggiunta di nuove funzionalità e fornire aggiornamenti di sicurezza.
-
Requisiti del Progetto: Le specifiche caratteristiche e i requisiti di un progetto possono essere determinanti nella scelta del runtime appropriato. Ad esempio, determinati runtime potrebbero integrarsi meglio con database specifici o altri sistemi esterni.
-
Scalabilità e Utilizzo delle Risorse: La dimensione e la scala di un progetto possono influenzare la scelta di un runtime appropriato. I runtime leggeri e scalabili potrebbero essere vantaggiosi per progetti più piccoli, mentre runtime più robusti che gestiscono efficacemente l’utilizzo delle risorse possono essere preferiti per applicazioni di grande scala.
-
Compatibilità con l’Infrastruttura Esistente: La compatibilità con altre strumenti, servizi ed elementi di infrastruttura utilizzati nel progetto può influenzare la scelta del runtime. È essenziale che un runtime sia compatibile con l’infrastruttura esistente e faciliti un’integrazione facile.
-
Sicurezza e Politiche di Aggiornamento: Il runtime deve aderire agli standard di sicurezza e ricevere regolari aggiornamenti per garantire la sicurezza a lungo termine del progetto.
Questi fattori, oltre alle prestazioni, svolgono un ruolo cruciale nell’orientare la scelta di un runtime ideale. Valutare queste considerazioni in modo equilibrato può migliorare il successo complessivo e la sostenibilità di un progetto.
Ora che abbiamo considerato criteri essenziali come l’esperienza dello sviluppatore, il supporto della comunità, la documentazione, la sicurezza e la compatibilità, è fondamentale approfondire gli aspetti delle prestazioni dei runtime di Symfony identificati. Condurre un’analisi approfondita delle prestazioni comporta l’esame di metriche chiave come le Richieste per Secondo (RPS), i valori di latenza e le velocità di trasferimento in diversi scenari. Esaminando attentamente come ciascun runtime gestisce questi indicatori di prestazione, possiamo ottenere informazioni sulla loro efficienza in diverse condizioni di carico di lavoro. Questa valutazione approfondita delle prestazioni ci guiderà nella presa di decisioni informate, garantendo che i runtime scelti soddisfino non solo i requisiti non funzionali del progetto, ma offrano anche velocità e reattività ottimali, fondamentali per un’applicazione Symfony di successo.
Endpoint di Test
Questi endpoint rappresentano tre diverse rotte API nella tua applicazione Symfony, ognuna con uno scopo diverso:
-
Endpoint di Controllo dello Stato di Salute (
**/health-check**
): Questo endpoint viene utilizzato per valutare lo stato generale dell’applicazione. Quando viene chiamato, esegue un controllo di integrità, valutando lo stato dei servizi mirati, e restituisce una risposta HTTP 204 No Content. Ciò indica che la funzionalità principale dell’applicazione è attiva e lo stato di salute è positivo. -
Endpoint di Informazioni Statiche (
**/static**
): Questo endpoint fornisce informazioni statiche sull’applicazione restituendo una semplice risposta JSON. La risposta JSON include tipicamente valori costanti, versioni o altri dettagli statici sull’applicazione. Questo endpoint offre un accesso rapido e facile per i client per raccogliere informazioni di base sull’applicazione. -
Endpoint di Richieste HTTP (
**/http-request**
): Questo endpoint utilizza il servizioHttp
di Symfony per inviare una richiesta HTTP GET a un’altra API. La risposta ricevuta dimostra la capacità dell’applicazione Symfony di interagire con risorse esterne. Questa funzionalità può essere utilizzata in scenari come il recupero di dati da API esterne o l’accesso a risorse.
La traefik/whoami è un’applicazione di esempio semplice che, al ricevimento di una richiesta HTTP, fornisce informazioni dettagliate sulla fonte della richiesta. Questa applicazione restituisce una risposta informativa contenente intestazioni HTTP, indirizzo IP del client, timestamp della richiesta e altri dettagli pertinenti.
Questi tre endpoint rappresentano diversi scenari d’uso, consentendo di effettuare diversi test per valutare le prestazioni complessive dell’applicazione.
json([
'status' => true,
]);
#[Route('/http-request', name: 'http_request')]
public function httpRequest(HttpService $httpService): JsonResponse
{
return $this->json(json_decode($httpService->get('http://whoami/api')));
}
}
Immagini Docker
Open Swoole
FROM php:8.3-alpine
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
RUN install-php-extensions pcntl sockets openswoole
COPY . /var/www
WORKDIR /var/www
RUN composer install --no-dev
ENV APP_RUNTIME="Runtime\\\Swoole\\\Runtime"
ENTRYPOINT ["php", "public/index.php"]
Swoole
FROM php:8.3-alpine
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
RUN install-php-extensions pcntl sockets swoole
COPY . /var/www
WORKDIR /var/www
RUN composer install --no-dev
ENV APP_RUNTIME="Runtime\\\Swoole\\\Runtime"
ENTRYPOINT ["php", "public/index.php"]
RoadRunner
FROM php:8.3-alpine
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPY --from=ghcr.io/roadrunner-server/roadrunner:latest /usr/bin/rr /usr/local/bin/rr
RUN install-php-extensions pcntl sockets
COPY . /var/www
WORKDIR /var/www
RUN composer install --no-dev
ENV APP_RUNTIME="Runtime\\\RoadRunnerSymfonyNyholm\\\Runtime"
ENTRYPOINT ["rr", "serve"]
FrankenPHP
FROM php:8.3-alpine
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
RUN install-php-extensions pcntl sockets
COPY . /var/www
WORKDIR /var/www
RUN apk add jq
RUN wget -O/usr/local/bin/frankenphp $(wget -O- https://api.github.com/repos/dunglas/frankenphp/releases/latest | jq '.assets[] | select(.name=="frankenphp-linux-x86_64") | .browser_download_url' -r) && chmod +x /usr/local/bin/frankenphp
RUN composer install --no-dev
ENV APP_RUNTIME="Runtime\\\FrankenPhpSymfony\\\Runtime"
ENV APP_PUBLIC_PATH="/var/www/public"
ENV MAX_REQUESTS="500"
ENV REQUEST_MAX_EXECUTION_TIME="500"
ENV CADDY_SERVER_ADMIN_PORT="3823"
ENV CADDY_SERVER_LOG_LEVEL="WARN"
ENV CADDY_SERVER_LOGGER="json"
ENV CADDY_SERVER_SERVER_NAME="http://:9804"
ENV CADDY_SERVER_WORKER_COUNT="16"
ENV CADDY_SERVER_EXTRA_DIRECTIVES=""
ENTRYPOINT ["frankenphp","run", "-cCaddyfile"]
Docker Compose
version: "3.9"
services:
whoami:
container_name: "whoami"
image: "containous/whoami"
openswoole:
container_name: "openswoole"
image: "ghcr.io/thecaliskan/symfony-benchmark:openswoole"
ports:
- "9801:9801"
swoole:
container_name: "swoole"
image: "ghcr.io/thecaliskan/symfony-benchmark:swoole"
ports:
- "9802:9802"
roadrunner:
container_name: "roadrunner"
image: "ghcr.io/thecaliskan/symfony-benchmark:roadrunner"
ports:
- "9803:9803"
frankenphp:
container_name: "frankenphp"
image: "ghcr.io/thecaliskan/symfony-benchmark:frankenphp"
ports:
- "9804:9804"
GitHub – thecaliskan/symfony-benchmark: Symfony Benchmark Example Project
for Symfony Runtime…
Symfony Benchmark Example Project for Symfony Runtime Servers – GitHub – thecaliskan/symfony-benchmark: Symfony…
Installazione
Per eseguire test di benchmark sul tuo server, segui questi passaggi per configurare l’applicazione:
wget https://raw.githubusercontent.com/thecaliskan/symfony-benchmark/master/docker-compose.yml
docker compose up -d
Benchmark
Ora che la tua applicazione Symfony è in esecuzione, puoi effettuare test di benchmark per diverse opzioni di server. Utilizza i seguenti comandi per ciascun server:
OpenSwoole
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9801/api/health-check
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9801/api/static
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9801/api/http-request
Swoole
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9802/api/health-check
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9802/api/static
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9802/api/http-request
RoadRunner
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9803/api/health-check
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9803/api/static
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9803/api/http-request
FrankenPHP
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9804/api/health-check
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9804/api/static
wrk -t16 -c100 -d30s --latency http://127.0.0.1:9804/api/http-request
Stack
Software
-
PHP: v8.3.1
-
Symfony: v7.0.2
-
Open Swoole: v22.1.2
-
Swoole: v5.1.1
-
RoadRunner: v2023.3.8
-
FrankenPHP: v1.0.3
-
Docker Engine: v24.0.7
-
Sistema Operativo: Fedora Linux 39 (Edizione Workstation)
-
Versione del Kernel: Linux 6.6.8–200.fc39.x86_64
Hardware
-
Intel i9 9900K (8 Core/16 Thread, 3.6 Ghz, Turbo 5.0 Ghz)
-
32 GB DDR4 3200 Mhz
-
Samsung 970 EvoPlus SSD (3.500w/3.300r MB/s)
Risultati dei Test
Conclusioni
I test di benchmark che valutano le prestazioni del Framework Symfony rivelano un netto vantaggio dei runtime OpenSwoole e Swoole rispetto agli altri. Questo è particolarmente evidente negli scenari “Health Check”, “Static” e “Http Request”, in cui sono evidenti valori di latenza bassi e alti tassi di Richieste per Secondo (RPS).
La superiorità di OpenSwoole e Swoole in questi aspetti è un vantaggio significativo per garantire che le applicazioni vengano eseguite in modo rapido ed efficiente. Questi runtime rispondono efficacemente alle richieste degli utenti con valori di latenza ridotti e gestiscono con successo elevate richieste con i loro elevati tassi di RPS.
Gli sviluppatori dovrebbero concentrarsi sull’ottimizzazione di RoadRunner e FrankenPHP in base a questi risultati dei benchmark. Ciò contribuirà a migliorare le prestazioni dei progetti Symfony nel complesso, avendo un impatto positivo sull’esperienza dell’utente e favorire un processo di sviluppo delle applicazioni più efficiente.
Quando si tratta di selezionare l’ambiente di runtime per i progetti Symfony, quali sono i fattori chiave che influenzano la tua decisione? Quale runtime preferisci per i tuoi progetti e quali considerazioni come prestazioni, esperienza dello sviluppatore o requisiti specifici del progetto giocano un ruolo nella tua scelta? Condividi le tue preferenze personali e le ragioni che prendi in considerazione quando prendi queste decisioni.
Crediti e fonte dell’articolo qui.