Blog

Wie Sie die PHP-Leistung auf Google Cloud Run optimieren

Luca Cavallin

Aktualisiert Oktober 21, 2025
6 Minuten

Ich musste kürzlich die Leistung einer PHP-basierten API auf Cloud Run optimieren. Nach einem Leistungstest stellten wir fest, dass die API sehr langsam wurde, wenn wir sie stark belasteten (mit Antwortzeiten von über 10 Sekunden). In diesem Beitrag erfahren Sie, welche Änderungen ich vorgenommen habe, um diese Zeit auf stabile 100 ms zu senken.

Die API verwendet PHP 7.4, Laravel 8.0 und MySQL auf Cloud SQL (die verwaltete Datenbank auf Google Cloud). Die API muss mindestens 10.000 gleichzeitige Benutzer verarbeiten können. Das Container-Image, das wir auf Cloud Run bereitstellen, verfügt über nginx und PHP-FPM.

Das habe ich getan, um die Antwortzeiten zu verbessern. (Machen Sie sich keine Sorgen, wenn hier nicht alles Sinn macht, ich werde alles erklären).

  • Anpassung der Anzahl der PHP-FPM-Worker an die Einstellung für die maximale Gleichzeitigkeit in Cloud Run.
  • Konfigurieren von OPcache (kompiliert und cached PHP-Skripte)
  • Verbesserung der Einstellungen für das automatische Laden des Composers
  • Laravel-spezifische Optimierungen, einschließlich Caching von Routen, Ansichten, Ereignissen und der Verwendung von API-Ressourcen

Abgleich von Gleichzeitigkeit und Arbeitern

Die Anwendung verwendet nginx und PHP-FPM, einen Prozessmanager für PHP. PHP ist Single-Thread-fähig, d.h. ein Prozess kann eine (genau eine) Anfrage zur gleichen Zeit bearbeiten. PHP-FPM hält einen Pool von PHP-Workern (ein Worker ist ein Prozess) bereit, um Anfragen zu bedienen, und fügt weitere hinzu, wenn die Nachfrage steigt. Es ist eine gute Praxis, die maximale Größe des PHP-FPM-Worker-Pools zu begrenzen, um sicherzustellen, dass Ihre Ressourcennutzung (CPU und Speicher) vorhersehbar ist.

Um PHP-FPM für maximale Leistung zu konfigurieren, habe ich zunächst den Prozessmanagertyp für PHP-FPM auf statisch gesetzt, so dass die angegebene Anzahl von Workern jederzeit läuft und darauf wartet, Anfragen zu bearbeiten. Dazu habe ich eine benutzerdefinierte Konfigurationsdatei in den Container der Anwendung kopiert und die Umgebung so konfiguriert, dass diese Optionen von PHP-FPM übernommen werden (Sie müssen die Konfiguration dorthin kopieren, wo sie erwartet wird, in meinem Fall nach /usr/local/etc/php-fpm.d/). Die von mir benötigten Einstellungen sind:

pm = static
pm.max_children = 10

Wenn Sie jedoch ein Limit festlegen und mehr Anfragen auf einem Server eingehen, als der Pool bewältigen kann, beginnen die Anfragen sich in der Warteschlange anzustellen, wodurch sich die Antwortzeit dieser Anfragen erhöht:

Nginx und php-fpm Anfragemodell

Begrenzung gleichzeitiger Anfragen bei Cloud Run

Um die Warteschlangenbildung in Nginx zu vermeiden, müssen Sie die Anzahl der Anfragen, die Cloud Run gleichzeitig an Ihren Container sendet, begrenzen.

Cloud Run verwendet anforderungsbasierte Autoskalierung. Das bedeutet, dass es die Anzahl der gleichzeitigen Anfragen an einen Container begrenzt und weitere Container hinzufügt, wenn alle Container ihr Limit erreicht haben. Sie können diese Grenze mit der Einstellung für die Gleichzeitigkeit ändern. Ich habe sie auf 10 gesetzt. Das ist die maximale Anzahl gleichzeitiger Anfragen, die ein Container mit 1 GB Arbeitsspeicher und 1vCPU mit dieser Anwendung bewältigen kann.

Cloud Gleichzeitige Anfragen mit Nginx und php-fpm ausführen

Achten Sie unbedingt darauf, dass die Gleichzeitigkeitseinstellung von Cloud Run mit der maximalen Anzahl von PHP-FPM-Arbeitern übereinstimmt! Wenn Cloud Run beispielsweise 100 gleichzeitige Anfragen an einen Container sendet, bevor Sie weitere Container hinzufügen, und Sie Ihren PHP-FPM so konfiguriert haben, dass er nur 10 Worker startet, werden Sie eine Menge Anfragen in der Warteschlange sehen.

Wenn diese Optimierungen nicht ausreichen, um die gewünschte Leistung zu erreichen, überprüfen Sie die Cloud Run-Metriken, um zu sehen, wie hoch der tatsächliche Nutzungsgrad ist. Möglicherweise müssen Sie die Menge an Arbeitsspeicher und vCPUs ändern, die dem Container zur Verfügung stehen. Der Nachteil dieser Optimierung ist, dass aufgrund der geringeren Gleichzeitigkeit mehr Container ausgeführt werden, was zu höheren Kosten führt. Außerdem habe ich beim Starten neuer Instanzen vorübergehende Verzögerungen festgestellt, die sich jedoch mit der Zeit normalisieren.

OPCache konfigurieren

OPCache ist eine Standard-PHP-Erweiterung, die die kompilierten Skripte im Speicher zwischenspeichert und so die Antwortzeiten erheblich verbessert. Ich habe die OPCache-Einstellungen aktiviert und angepasst, indem ich die Optionen der Erweiterung zu einer benutzerdefinierten php.ini Datei hinzugefügt habe (in meinem Fall habe ich sie in das Verzeichnis /usr/local/etc/php/conf.d/ gelegt). Im Folgenden finden Sie eine allgemeine Konfiguration, die Sie leicht wiederverwenden können. Die Einzelheiten zu den einzelnen Optionen entnehmen Sie bitte der Dokumentation.

opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=32531
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.fast_shutdown=0

Composer optimieren

Composer ist ein Abhängigkeitsmanager für PHP. Mit ihm können Sie die Bibliotheken angeben, die Ihre Anwendung benötigt, und er lädt sie für Sie in ein Verzeichnis herunter. Außerdem generiert er eine Autoload-Konfigurationsdatei, die Importpfade auf Dateien abbildet.Wenn Sie dem Composer das Flag übergeben, wird diese Datei nur einmal generiert und nicht dynamisch aktualisiert, wenn Sie neuen Code hinzufügen. Während dies in der Entwicklung praktisch ist (Ihre Änderungen werden sofort angezeigt), kann es Ihren Code in der Produktion sehr langsam machen.

Sie können den Autoloader von Composer optimieren, indem Sie das Flag --optimize-autoloader wie folgt übergeben:

composer install --optimize-autoloader --no-dev

Laravel-spezifische Optimierungen

Die Anwendung, die ich optimiert habe, wurde mit Laravel erstellt, das eine Reihe von Tools bietet, mit denen die Leistung der API verbessert werden kann. Hier sehen Sie, was ich zusätzlich zu den anderen Optimierungen getan habe, um die Antwortzeiten unter 100 ms zu bringen.

  • Ich habe die in Laravel integrierten Caching-Funktionen während der Builds genutzt, um die Startzeiten zu verkürzen. Diese Änderungen haben keine Nachteile, außer dass Sie keine Closure-definierten Routen verwenden können (sie können nicht gecached werden). Sie können Ansichten, Ereignisse und Routen mit diesen Befehlen zwischenspeichern:

    php artisan view:cache
    php artisan event:cache
    php artisan route:cache

    Vermeiden Sie die Ausführung von php artisan config:cache, da Laravel Umgebungsvariablen ignoriert, wenn Sie die Konfiguration zwischenspeichern.

  • Die Verwendung von Laravel API-Ressourcen verbessert die Antwortzeiten Ihrer Anwendung weiter. Dies hat sich als viel schneller erwiesen, als wenn das Framework einzelne Objekte und Sammlungen automatisch in JSON konvertiert.

Zusammenfassung

In diesem Blog habe ich mit Ihnen geteilt, was ich bei der Optimierung der Leistung einer PHP-basierten API auf Cloud Run gelernt habe. Alle Optimierungen zusammen haben dazu beigetragen, die Antwortzeiten auf ein Zehntel des ursprünglichen Ergebnisses zu reduzieren. Ich denke, dass die größte Wirkung durch die Anpassung der Gleichzeitigkeit und der PHP-FPM-Worker erzielt wurde (wenn Sie es eilig haben, tun Sie nur dies). Die Beobachtung der Anwendungsmetriken war während der gesamten Leistungstestphase von grundlegender Bedeutung, ebenso wie die Prüfung der Cloud Run-Protokolle nach jeder Änderung.

Wenn Ihre Anwendung nach diesen Änderungen immer noch eine schlechte Leistung aufweist, können Sie weitere Optimierungen vornehmen, um die Antwortzeiten zu verbessern, auf die ich hier nicht eingegangen bin.

  • Erhöhen Sie bei Bedarf die PHP-Speichergrenzen
  • Prüfen Sie MySQL auf langsame Abfragen (oft aufgrund fehlender Indizes)
  • Zwischenspeichern der Antworten mit einem CDN
  • Migrieren Sie auf PHP 8.0 (bis zu 3x schneller)

Möchten Sie mehr über Google Cloud Run erfahren? Schauen Sie sich dieses Buch von unserem Mitarbeiter Wietse Venema an.

Credits: Kopfzeilenbild von Serey Kim auf Unsplash

Verfasst von

Luca Cavallin

Luca is a Software Engineer and Trainer with full-stack experience ranging from distributed systems to cross-platform apps. He is currently interested in building modern, serverless solutions on Google Cloud using Golang, Rust and React and leveraging SRE and Agile practices. Luca holds 3 Google Cloud certifications, he is part of the Google Developers Experts community and he is the co-organizer of the Google Cloud User Group that Binx.io holds with Google.

Contact

Let’s discuss how we can support your journey.