---
title: "`systemtap-toolkit` und `stapxx`: Wie man Daten nutzt, um schwierige Probleme zu lösen? - API7.ai"
description: "Die auf Systemtap basierenden Werkzeugsätze: systemtap-toolkit und stapxx können zur Lösung von Problemen bei der Echtzeitanalyse und Diagnose von NGINX und OpenResty verwendet werden."
url: "https://api7.ai/de/learning-center/openresty/systemtap-toolkit-and-stapxx"
---

# \`systemtap-toolkit\` und \`stapxx\`: Wie man Daten nutzt, um schwierige Probleme zu lösen?

API7.ai

December 22, 2022

[OpenResty (NGINX + Lua)](https://api7.ai/learning-center/openresty)

Wie im vorherigen Artikel vorgestellt, vertiefen wir uns als Server-seitige Entwicklungsingenieure nicht in dynamische Debugging-Toolsets, sondern bleiben meist auf der Nutzungsebene und schreiben höchstens einige einfache Standard-Skripte. Die tieferen Ebenen, wie CPU-Cache, Architektur, Compiler usw., sind das Gebiet von Performance-Ingenieuren.

Es gibt zwei Open-Source-Projekte in OpenResty: `openresty-systemtap-toolkit` und `stapxx`. Es handelt sich um systemtap-basierte, verpackte Toolsets zur Echtzeitanalyse und Diagnose von NGINX und OpenResty. Sie decken on-CPU, off-CPU, Shared Dictionary, Garbage Collection, Request-Latenz, Memory-Pooling, Connection-Pooling, Dateizugriff und andere gängige Funktionen und Debugging-Szenarien ab.

In diesem Artikel werden wir diese Tools und ihre entsprechenden Anwendungen durchgehen, um uns zu helfen, schnell Werkzeuge zur Problembehebung zu finden, wenn wir auf Fehlerbehebungsprobleme mit NGINX und OpenResty stoßen. In der Welt von OpenResty ist das Erlernen der Verwendung dieser Tools ein sicherer Weg, um voranzukommen, und eine sehr effektive Möglichkeit, mit anderen Entwicklern zu kommunizieren – schließlich sind die von den Tools generierten Daten genauer und detaillierter, als wir sie in Worten beschreiben könnten.

Es ist jedoch wichtig zu beachten, dass der LuaJIT GC64-Modus standardmäßig in OpenResty Version `1.15.8` aktiviert ist, aber `openresty-systemtap-toolkit` und `stapxx` die entsprechenden Änderungen nicht nachvollziehen, was dazu führt, dass die Tools darin nicht korrekt funktionieren. Daher sollten wir diese Tools besser in der alten `1.13` Version von OpenResty verwenden.

Die meisten Open-Source-Projektmitwirkenden sind Teilzeitkräfte und nicht verpflichtet, die Tools funktionsfähig zu halten, was wir bei der Verwendung von Open-Source-Projekten beachten müssen.

## Beispiel: `shared dict`

Beginnen wir mit einem Tool, das wir wahrscheinlich am besten kennen und am einfachsten verwenden können, `ngx-lua-shdict`, als Beispiel, um den heutigen Beitrag zu starten.

`ngx-lua-shdict` ist ein Tool, das die `shared dict`s von NGINX analysiert und ihre Operationen verfolgt. Sie können die `-f`-Option verwenden, um das `dict` und den `key` anzugeben, um die Daten im `shared dict` zu erhalten. Die `--raw`-Option ermöglicht es Ihnen, den Rohwert des angegebenen `key` zu exportieren.

Das Folgende ist ein Befehlszeilenbeispiel, um Daten aus einem `shared dict` zu erhalten.

```
# Angenommen, die NGINX Worker PID ist 5050
$ ./ngx-lua-shdict -p 5050 -f --dict dogs --key Jim --luajit20
Tracing 5050 (/opt/nginx/sbin/nginx)...

type: LUA_TBOOLEAN
value: true
expires: 1372719243270
flags: 0xa
```

Ebenso können wir die `-w`-Option verwenden, um die Schreibvorgänge im dict für einen bestimmten `key` zu verfolgen:

```
$./ngx-lua-shdict -p 5050 -w --key Jim --luajit20
Tracing 5050 (/opt/nginx/sbin/nginx)...

Hit Ctrl-C to end

set Jim exptime=4626322717216342016
replace Jim exptime=4626322717216342016
^C
```

Sehen wir uns an, wie dieses Tool implementiert ist. `ngx-lua-shdict` ist ein Perl-Skript, aber die Implementierung hat nichts mit Perl zu tun, das nur verwendet wird, um das `stap`-Skript zu generieren und auszuführen.

```
open my $in, "|stap $stap_args -x $pid -" or die "Cannot run stap: $!\n";
```

Wir könnten es in Python, PHP, Go oder jeder anderen Sprache schreiben, die wir mögen. Der entscheidende Punkt im `stap`-Skript ist die folgende Codezeile:

```
probe process("$nginx_path").function("ngx_http_lua_shdict_set_helper")
```

Dies ist die `probe`, die wir zuvor erwähnt haben, die die Funktion `ngx_http_lua_shdict_set_helper` abtastet. Die Aufrufe dieser Funktion befinden sich alle in der Datei `lua-nginx-module/src/ngx_http_lua_shdict.c` des `lua-nginx-module`-Moduls.

```
static int
ngx_http_lua_shdict_add(lua_State *L)
{
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_ADD);
}

static int
ngx_http_lua_shdict_safe_add(lua_State *L)
{
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_ADD
|NGX_HTTP_LUA_SHDICT_SAFE_STORE);
}

static int
ngx_http_lua_shdict_replace(lua_State *L)
{
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_REPLACE);
}
```

Auf diese Weise können wir alle Operationen des Shared Dict verfolgen, indem wir einfach diese Funktion abtasten.

## on-CPU, off-CPU

Bei der Verwendung von OpenResty ist das häufigste Problem, auf das wir stoßen, die Leistung. Es gibt zwei Haupttypen von schlechter Leistung, d.h. niedrige QPS: zu hohe CPU-Auslastung und zu niedrige CPU-Auslastung. Der erstgenannte Engpass kann darauf zurückzuführen sein, dass wir die zuvor vorgestellten Leistungsoptimierungsmethoden nicht verwenden, während der letztgenannte auf blockierende Funktionen zurückzuführen sein kann. Die entsprechenden on-CPU- und off-CPU-Flame-Graphs können uns helfen, die ultimative Ursache zu identifizieren.

Um C-Level on-CPU-Flame-Graphs zu generieren, müssen Sie `sample-bt` in `systemtap-toolkit` verwenden; während Lua-Level on-CPU-Flame-Graphs von `lj-lua-stacks` in `stapxx` generiert werden.

Nehmen wir `sample-bt` als Beispiel, wie man es verwendet. `sample-bt` ist ein Skript, das den Aufrufstapel eines beliebigen Benutzerprozesses, den wir angeben (nicht nur NGINX- und OpenResty-Prozesse), abtastet.

Zum Beispiel können wir einen laufenden NGINX Worker-Prozess (mit einer PID von `8736`) für 5 Sekunden mit dem folgenden Code abtasten:

```
$ ./sample-bt -p 8736 -t 5 -u > a.bt
WARNING: Tracing 8736 (/opt/nginx/sbin/nginx) in user-space only...
WARNING: Missing unwind data for module, rerun with 'stap -d stap_df60590ce8827444bfebaf5ea938b5a_11577'
WARNING: Time's up. Quitting now...(it may take a while)
WARNING: Number of errors: 0, skipped probes: 24
```

Es gibt die Ergebnisdatei `a.bt` aus, die verwendet werden kann, um mit dem FlameGraph-Toolset einen Flame-Graph zu generieren:

```
stackcollapse-stap.pl a.bt > a.cbt
flamegraph.pl a.cbt > a.svg
```

Die `a.svg` ist der generierte Flame-Graph, den wir im Browser öffnen können, um ihn anzuzeigen. Während des Abtastzeitraums müssen wir jedoch eine bestimmte Anzahl von Anfragen aufrechterhalten. Andernfalls gibt es keine Möglichkeit, den Flame-Graph zu generieren, wenn die Stichprobenanzahl `0` ist.

Als nächstes schauen wir uns an, wie man off-CPU abtastet, indem wir das Skript `sample-bt-off-cpu` in `systemtap-toolkit` verwenden, das ähnlich wie `sample-bt` ist, wie folgt:

```
$ ./sample-bt-off-cpu -p 10901 -t 5 > a.bt
WARNING: Tracing 10901 (/opt/nginx/sbin/nginx)...
WARNING: _stp_read_address failed to access memory location
WARNING: Time's up. Quitting now...(it may take a while)
WARNING: Number of errors: 0, skipped probes: 23
```

In `stapxx` ist das Tool zur Analyse der Latenz `epoll-loop-blocking-distr`, das den angegebenen Benutzerprozess abtastet und die Latenzverteilung zwischen aufeinanderfolgenden `epoll_wait`-Systemaufrufen ausgibt.

```
$ ./samples/epoll-loop-blocking-distr.sxx -x 19647 --arg time=60
Start tracing 19647...
Please wait for 60 seconds.
Distribution of epoll loop blocking latencies (in milliseconds)
max/avg/min: 1097/0/0
value |-------------------------------------------------- count
    0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  18471
    1 |@@@@@@@@                                            3273
    2 |@                                                    473
    4 |                                                     119
    8 |                                                      67
   16 |                                                      51
   32 |                                                      35
   64 |                                                      20
  128 |                                                      23
  256 |                                                       9
  512 |                                                       2
 1024 |                                                       2
 2048 |                                                       0
 4096 |                                                       0
```

Wie wir sehen können, zeigt diese Ausgabe, dass die überwiegende Mehrheit der Verzögerungen weniger als 1 ms beträgt, aber es gibt einige, die über 200 ms liegen, und diese sind diejenigen, die zu beachten sind.

## Upstream und Phase-Tracking

Zusätzlich zu Leistungsproblemen, die im Code von OpenResty selbst auftreten können, kann es, wenn OpenResty über Upstream-Module wie `cosocket` oder `proxy_pass` mit Upstream-Diensten kommuniziert, auch erhebliche Auswirkungen auf die Gesamtleistung haben, wenn der Upstream-Dienst selbst eine große Latenz aufweist.

In diesem Fall können wir die Tools `ngx-lua-tcp-recv-time`, `ngx-lua-udp-recv-time` und `ngx-single-req-latency` zur Analyse verwenden. Hier ist ein Beispiel für `ngx-single-req-latency`.

Dieses Tool unterscheidet sich etwas von den meisten Tools innerhalb des Toolsets. Die meisten anderen Tools basieren auf einer großen Anzahl von Stichproben und statistischen Analysen, um eine mathematische Schlussfolgerung über die Verteilung zu ziehen. Stattdessen analysiert `ngx-single-req-latency` einzelne Anfragen und verfolgt die Zeit, die für einzelne Anfragen in verschiedenen Phasen in OpenResty aufgewendet wird, wie z.B. die `rewrite`-, `access`- und `content`-Phasen sowie Upstream.

Sehen wir uns ein konkretes Beispielcode an:

```
# making the ./stap++ tool visible in PATH:
$ export PATH=$PWD:$PATH

# assuming an nginx worker process's pid is 27327
$ ./samples/ngx-single-req-latency.sxx -x 27327
Start tracing process 27327 (/opt/nginx/sbin/nginx)...

POST /api_json
    total: 143596us, accept() ~ header-read: 43048us, rewrite: 8us, pre-access: 7us, access: 6us, content: 100507us
    upstream: connect=29us, time-to-first-byte=99157us, read=103us

$ ./samples/ngx-single-req-latency.sxx -x 27327
Start tracing process 27327 (/opt/nginx/sbin/nginx)...

GET /robots.txt
    total: 61198us, accept() ~ header-read: 33410us, rewrite: 7us, pre-access: 7us, access: 5us, content: 27750us
    upstream: connect=30us, time-to-first-byte=18955us, read=96us
```

Dieses Tool verfolgt die erste Anfrage, auf die es nach dem Start stößt. Die Ausgabe ähnelt `opentracing` sehr, und wir können uns `systemtap-toolkit` und `stapxx` sogar als nicht-invasive Versionen von APM (Application Performance Management) in OpenResty vorstellen.

## Zusammenfassung

Zusätzlich zu den gängigen Tools, über die ich heute gesprochen habe, bietet OpenResty natürlich noch viele weitere Tools, die Sie selbst erkunden und erlernen können.

Es gibt noch einen signifikanten Unterschied zwischen OpenResty und anderen Entwicklungssprachen und Plattformen in Bezug auf Tracing-Technologie, den wir langsam schätzen können.

> Halten Sie den Code sauber und stabil, fügen Sie keine Proben hinzu, sondern nehmen Sie ihn durch externe dynamische Tracking-Techniken auf.

Welche Tools haben Sie verwendet, um Probleme bei der Verwendung von OpenResty zu verfolgen und zu analysieren? Sie sind herzlich eingeladen, diesen Artikel zu teilen, und wir werden gemeinsam teilen und Fortschritte machen.

Share article link

Share

Related Posts

[![OpenResty FAQ | Netzwerkstruktur für Tests, SSL-bezogene Funktionen, DSL, \`ab\`-Tool](https://static.api7.ai/2022/12/02/63896c177fde1.png)](https://api7.ai/learning-center/openresty/faq-3)

## [OpenResty FAQ | Netzwerkstruktur für Tests, SSL-bezogene Funktionen, DSL, \`ab\`-Tool](https://api7.ai/learning-center/openresty/faq-3)

[![Genauigkeit bei Performance-Tests mit \`wrk\`](https://static.api7.ai/2022/11/25/63802abdc3b1b.png)](https://api7.ai/learning-center/openresty/performance-testing-tool-wrk)

## [Genauigkeit bei Performance-Tests mit \`wrk\`](https://api7.ai/learning-center/openresty/performance-testing-tool-wrk)

Table of Contents

- [Beispiel: `shared dict`](#beispiel-shared-dict)
- [on-CPU, off-CPU](#on-cpu-off-cpu)
- [Upstream und Phase-Tracking](#upstream-und-phase-tracking)
- [Zusammenfassung](#zusammenfassung)
