Heim >Backend-Entwicklung >PHP-Tutorial >Praxis zur Optimierung der PHP-Parallelitätsleistung (Leistung um 104 % gesteigert)

Praxis zur Optimierung der PHP-Parallelitätsleistung (Leistung um 104 % gesteigert)

步履不停
步履不停Original
2019-06-10 10:29:598644Durchsuche

Praxis zur Optimierung der PHP-Parallelitätsleistung (Leistung um 104 % gesteigert)

Betriebswirtschaftlicher Hintergrund

Rahmen und entsprechendes Umgebung

  1. laravel5.7, mysql5.7, redis5, nginx1.15

  2. Centos 7.5 bbr

  3. Docker, Docker-Compose

  4. Alibaba Cloud 4C und 8G

Problemhintergrund

PHP hat Opcache aktiviert, Laravel hat auch den Optimierungsbefehl zur Optimierung ausgeführt und Composer hat auch den Dump-Autoload-Befehl ausgeführt.

Als erstes muss erklärt werden, dass es kleinere Probleme im geben muss Systemumgebung (Es ist unmöglich, eine so große Leistung ohne Probleme zu verbessern), aber diese Probleme werden möglicherweise nicht in Ihrem Leben entdeckt, wenn Sie keine geeigneten Tools verwenden.

Dieser Artikel konzentriert sich darauf, wie man sie entdeckt Probleme und wie man sie findet Die Idee.

Wir finden zunächst eine geeignete API oder Funktion im System, um das Problem zu verstärken.

Diese API wurde ursprünglich entwickelt, um Gesundheitsprüfungen für die Nginx-Last durchzuführen ausgleichend. Verwenden Sie ab -n 100000 -c 1000 für Stresstests und stellen Sie fest, dass die QPS nur 140 Mal pro Sekunde erreichen können.

Wir wissen, dass die Leistung von Laravel notorisch schlecht ist, aber nicht in diesem Ausmaß Die API sollte nicht so niedrig sein, also habe ich beschlossen, es herauszufinden.

 public function getActivateStatus()
    {
        try {
            $result = \DB::select('select 1');
            $key = 1;
            if ($result[0]->$key !== 1) {
                throw new \Exception("mysql 检查失败");
            }
        } catch (\Exception $exception) {
            \Log::critical("数据库连接失败: {$exception->getMessage()}", $exception->getTrace());
            return \response(null, 500);
        }
        try {
            Cache::getRedis()->connection()->exists("1");
        } catch (\Exception $exception) {
            \Log::critical("缓存连接失败: {$exception->getMessage()}", $exception->getTrace());
            return \response(null, 500);
        }
        return \response(null, 204);
    }

Problemmanifestationen und Ideen zur Fehlerbehebung

top

Top-Befehl hat festgestellt, dass die System-CPU zu 100 % ausgelastet ist Davon entfallen 80 % auf den Benutzermodus und 20 % auf den Kernelmodus. Es scheint, dass es kein großes Problem gibt. Das Ergebnis der Ausführung des oberen Befehls

下载 (2).jpg

ist, dass sich einige PHP-FPM-Prozesse im Ruhezustand befinden, die CPU-Auslastung jedoch immer noch fast 30 % erreicht. Wenn sich ein Prozess im Ruhezustand befindet, belegt er immer noch viel CPU. Schauen wir uns die Manpage des Ttop-Befehls an Dies bedeutet ungefähr, dass diese Belegung das letzte Mal ist, dass der Prozess die CPU-Belegung aktualisiert, da Linux möglicherweise die Planung des Prozesses erzwungen hat (z. B. wird er zum Sammeln von Prozessinformationen mit top verwendet). ), also befinden sich in diesem Moment (in dem Moment, in dem der Bildschirm aktualisiert wird) einige PHP-FPM-Prozesse im Ruhezustand, was verständlich ist, daher sollte es bei PHP-FPM kein Problem sein >pidstat

Wählen Sie zuerst einen PHP-FPM-Prozess aus und verwenden Sie dann pidstat, um den detaillierten Ausführungsstatus des Prozesses anzuzeigen

Während des Prozesses wurde nichts Ungewöhnliches gefunden Die Ausführungsergebnisse des oberen Befehls sind im Grunde die gleichen.

vmstat

下载 (3).jpg

Messen Sie weiterhin den Druck und führen Sie vmstate zur Überprüfung aus, mit Ausnahme des Kontextwechsels (Kontextwechsel). Das ist etwas hoch, ich sehe nicht viele Auffälligkeiten. Da Docker, Redis und MySQL alle auf demselben Computer ausgeführt werden, ist CS von etwa 7.000 immer noch ein angemessener Bereich, aber der IN (Unterbrechung) ist etwas zu hoch und erreicht etwa 14.000. Es muss etwas geben, das es auslöst

Wir wissen, dass Interrupts harte Interrupts und weiche Interrupts umfassen, die von Hardware wie Netzwerkkarten und Mäusen gesendet werden und die CPU sofort stoppt, was sie gerade tut . Soft-Interrupts werden vom Betriebssystem ausgegeben und werden häufig zur erzwungenen Planung von Prozessen verwendet.

Sowohl vmstat als auch pidstat sind nur neue Erkennungstools. Wir lesen die Interrupt-Informationen des Systems aus der schreibgeschützten Datei /proc/interrupts, um herauszufinden, was genau den Anstieg der Interrupts verursacht hat. Verwenden Sie den Befehl watch -d, um die sich am häufigsten ändernden Interrupts zu ermitteln.下载 (4).jpg

%CPU -- CPU usage

The task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.

Wir haben festgestellt, dass sich Rescheduling-Interrupts am schnellsten ändern. Dies ist der Rescheduling-Interrupt (RES). Dieser Interrupt-Typ bedeutet, die inaktive CPU aufzuwecken, um die Ausführung neuer Aufgaben zu planen. Dies ist der Mechanismus, den der Scheduler verwendet, um Aufgaben auf verschiedene CPUs in Multiprozessorsystemen (SMP) zu verteilen. Er wird auch allgemein als Inter-Processor Interrupts (IPI) bezeichnet. Durch die Kombination der Befehle in vmstat können wir feststellen, dass einer der Gründe für niedrige QPS darin liegt, dass zu viele Prozesse um die CPU konkurrieren. Wir sind uns noch nicht sicher, was es ist, daher sind weitere Untersuchungen erforderlich

下载 (5).jpgstrace

strace kann Systemaufrufe anzeigen. Wir wissen, dass das System bei der Verwendung von Systemaufrufen in den Kernelmodus wechselt. Überprüfen Sie dies durch Anzeigen des PHP-FPM-Systems unsere Vermutung

下载 (6).jpg果然, 发现大量的stat系统调用, 我们猜想, 是opcache在检查文件是否过期导致的. 我们通过修改opcache的配置, 让opcache更少的检查文件timestamp, 减少这种系统调用

 opcache.validate_timestamps="60"
    opcache.revalidate_freq="0"

再次执行ab命令进行压测

下载 (7).jpg果然qps直接涨到了205, 提升非常明显, 有接近 46% 的提升

perf

现在任然不满足这个性能, 希望在更多地方找到突破口. 通过

perf record -g
perf report -g

看到系统的分析报告

下载 (8).jpg

我们看到, 好像这里面有太多tcp建立相关的系统调用(具体是不是我还不清楚, 请大神指正, 但是看到send, ip, tcp啥的我就怀疑可能是tcp/ip相关的问题).

我们怀疑两种情况

  1. 与mysql, redis重复大量的建立TCP连接, 消耗资源

  2. 大量请求带来的tcp连接

先说第一个, 经过检查, 发现数据库连接使用了php-fpm的连接池, 但是redis连接没有, redis用的predis, 这个是一个纯PHP实现, 性能不高, 换成了phpredis:

打开laravel的config/database.php文件, 修改redis的driver为phpredis, 确保本机已安装php的redis扩展. 另外由于Laravel自己封装了一个Redis门面, 而恰好redis扩展带来的对象名也叫Redis. 所以需要修改Laravel的Redis门面为其他名字, 如RedisL5.

再次进行压测

下载 (9).jpg

达到了喜人的286qps, 虽然和其他主打高性能的框架或者原生php比, 还有很高的提升空间(比如Swoole), 但是最终达到了104%的提升, 还是很有意义的

总结

  1. 我们通过top, 发现系统CPU占用高, 且发现确实是php-fpm进程占用了CPU资源, 判断系统瓶颈来自于PHP.

  2. 接着我们通过pidstat, vmstat发现压测过程中, 出现了大量的系统中断, 并通过 watch -d cat /proc/interrupts 发现主要的中断来自于重调度中断(RES)

  3. 通过strace查看具体的系统调用, 发现大量的系统调用来自于stat, 猜测可能是opcache频繁的检查时间戳, 判断文件修改. 通过修改配置项, 达到了46%的性能提升

  4. 最后再通过perf, 查看函数调用栈, 分析得到, 可能是大量的与redis的TCP连接带来不必要的资源消耗. 通过安装redis扩展, 以及使用phpredis来驱动Laravel的redis缓存, 提升性能, 达到了又一次近50%的性能提升.

  5. 最终我们完成了我们的性能提升104%的目标

推荐教程:网站高并发架设基础教程

Das obige ist der detaillierte Inhalt vonPraxis zur Optimierung der PHP-Parallelitätsleistung (Leistung um 104 % gesteigert). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn