Dein erstes OpenResty-Programm: Hello World

API7.ai

September 9, 2022

OpenResty (NGINX + Lua)

Wenn wir anfangen, eine neue Programmiersprache zu lernen, bieten Tutorials oft einen einfachen hello world-Fall. Lassen Sie uns also zunächst die Installation überspringen und sehen, wie man diesen Fall in OpenResty schreibt:

$ resty -e "ngx.say('hello world')"
hello world

Dies sollte der einfachste hello world-Code sein, den Sie je gesehen haben, ähnlich wie in Python:

$ python -c 'print("hello world")'
hello world

Hinter diesem Code steckt die Philosophie von OpenResty. Der Code sollte so prägnant sein, dass Sie die Idee von "vom Einstieg bis zur Aufgabe" loswerden. Dieser Beitrag wird sich auf den hello world-Fall konzentrieren.

Wie wir im Beitrag Was ist der Unterschied zwischen OpenResty und NGINX gesagt haben, basiert OpenResty auf NGINX. Daher könnten Sie sich fragen: Warum sehen wir hier nicht den Schatten von NGINX? Machen Sie sich keine Sorgen, fügen wir eine Codezeile hinzu, um zu sehen, was hinter resty läuft:

$ resty -e "ngx.say('hello world'); ngx.sleep(10)" &

Wir haben eine ngx.sleep-Methode hinzugefügt, damit das Programm nach dem Ausdrucken der Zeichenkette hello world nicht beendet wird. Auf diese Weise haben wir die Möglichkeit, Folgendes herauszufinden:

$ ps -ef | grep nginx
root     15944  6380  0 13:59 pts/6    00:00:00 grep --color=auto nginx

Schließlich erscheint der NGINX-Prozess! Es scheint, dass der resty-Befehl im Wesentlichen einen NGINX-Dienst startet. Was ist also resty?

Möglicherweise haben Sie OpenResty noch nicht auf Ihrem Rechner installiert. Lassen Sie uns daher zu den Installationsschritten zurückkehren, die wir am Anfang übersprungen haben, und OpenResty installieren, bevor wir fortfahren.

Installation

Wie bei anderer Open-Source-Software können wir OpenResty auf verschiedene Arten installieren, z. B. über den Paketmanager des Betriebssystems, durch Kompilieren aus dem Quellcode oder über ein Docker-Image. Ich empfehle jedoch, zunächst einen Paketmanager wie yum, apt-get oder brew zu verwenden, um OpenResty zu installieren. In diesem Beitrag werde ich macOS als Beispiel verwenden:

$ brew tap openresty/brewbrew install openresty

Die Verwendung anderer Betriebssysteme ist ähnlich. Fügen Sie zunächst die URL des OpenResty-Repositorys zum Paketmanager hinzu und installieren Sie dann OpenResty über den Paketmanager. Für detailliertere Schritte können Sie die offizielle Dokumentation konsultieren.

Hinter dieser scheinbar einfachen Installation verbergen sich jedoch zwei Probleme:

  1. Warum empfehle ich nicht, es aus dem Quellcode zu installieren?
  2. Warum kann es nicht direkt aus dem offiziellen Repository des Betriebssystems installiert werden, sondern muss zuerst ein anderes Repository eingerichtet werden?

Bitte denken Sie zunächst über diese beiden Fragen nach.

Hier möchte ich noch etwas hinzufügen. In diesem Kurs werde ich viele "Warum"-Fragen hinter den Kulissen stellen. Ich hoffe, dass Sie beim Lernen neuer Dinge nachdenken. Es spielt keine Rolle, ob das Ergebnis richtig oder falsch ist. Leider ist unabhängiges Denken auch im technischen Bereich selten. Aufgrund der Unterschiede in den technischen Bereichen und der Tiefe des Wissens jedes Einzelnen werden Lehrer in jedem Kurs zwangsläufig persönliche Meinungen und Fehler im Wissen haben. Wir können allmählich unser eigenes technisches System bilden, indem wir im Lernprozess ein paar mehr Warum-Fragen stellen und es verstehen.

Viele Ingenieure genießen es, aus dem Quellcode zu bauen, und ich tat dies auch vor vielen Jahren. Wenn ich jedoch ein Open-Source-Projekt verwende, hoffe ich immer, dass ich manuell configure und make aus dem Quellcode durchführen und einige Kompilierungsparameter anpassen kann. Ich habe das Gefühl, dass dies der beste Weg ist, um die Umgebung dieses Rechners anzupassen und seine Leistung zu maximieren.

In der Realität ist dies jedoch nicht der Fall. Jedes Mal, wenn ich den Quellcode kompiliere, stoße ich auf seltsame Umweltprobleme und kann ihn erst nach einigen Schwierigkeiten installieren. Jetzt verstehe ich, dass unser ursprüngliches Ziel darin besteht, Open-Source-Projekte zu verwenden, um Geschäftsanforderungen zu lösen. Wir sollten keine Zeit und Umgebung damit verschwenden, zu kämpfen, ganz zu schweigen von Paketmanagern und Containertechnologien. Diese sind genau dazu da, uns bei der Lösung dieser Probleme zu helfen.

Kehren wir zum Thema zurück. Die Installation von OpenResty aus dem Quellcode ist nicht nur umständlich, sondern Sie müssen auch externe Abhängigkeiten wie PCRE, OpenSSL usw. lösen und manuell Patches für die entsprechende Version von OpenSSL anwenden. Andernfalls fehlen Funktionen bei der Behandlung von SSL-Sitzungen. Zum Beispiel können Lua-APIs wie ngx.sleep, die yield verursachen, nicht verwendet werden. Wenn Sie mehr über diesen Teil erfahren möchten, können Sie die offizielle Dokumentation für detailliertere Informationen konsultieren.

OpenResty pflegt diese Patches im OpenSSL-Paketskript selbst. Wenn OpenResty die OpenSSL-Version aktualisiert, muss es den entsprechenden Patch neu generieren und einen vollständigen Regressionstest durchführen.

Source0: https://www.openssl.org/source/openssl-%{version}.tar.gz

Patch0: https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.1.0d-sess_set_get_cb_yield.patch
Patch1: https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.1.0j-parallel_build_fix.patch

Gleichzeitig können wir uns das Paketskript von OpenResty in CentOS ansehen, um zu sehen, ob es weitere versteckte Punkte gibt:

BuildRequires: perl-File-Temp
BuildRequires: gcc, make, perl, systemtap-sdt-devel
BuildRequires: openresty-zlib-devel >= 1.2.11-3
BuildRequires: openresty-openssl-devel >= 1.1.0h-1
BuildRequires: openresty-pcre-devel >= 8.42-1
Requires: openresty-zlib >= 1.2.11-3
Requires: openresty-openssl >= 1.1.0h-1
Requires: openresty-pcre >= 8.42-1

Wie Sie hier sehen können, pflegt OpenResty seine eigene Version von OpenSSL sowie seine eigenen Versionen von zlib und PCRE. Die letzteren beiden haben jedoch die Kompilierungsparameter angepasst und ihre Patches nicht beibehalten.

Unter Berücksichtigung dieser Faktoren empfehle ich daher nicht, OpenResty aus dem Quellcode zu kompilieren, es sei denn, Sie kennen die Details bereits.

Es sollte Ihnen nun klar sein, warum die Quellcode-Installation nicht empfohlen wird. Als wir die erste Frage beantwortet haben, haben wir auch die zweite Frage beantwortet: Warum kann es nicht direkt aus dem offiziellen Paket-Repository des Betriebssystems installiert werden, sondern muss zuerst ein anderes Repository eingerichtet werden?

Dies liegt daran, dass die offiziellen Repositorys nicht bereit sind, OpenSSL-, PCRE- und zlib-Pakete von Drittanbietern zu akzeptieren, um Verwirrung bei anderen Benutzern zu vermeiden, die nicht wissen, welche sie wählen sollen. Andererseits benötigt OpenResty bestimmte Versionen der OpenSSL- und PCRE-Bibliotheken, um normal zu funktionieren, und die Standardversionen des Systems sind relativ alt.

OpenResty CLI

Nach der Installation von OpenResty ist die OpenResty CLI resty standardmäßig bereits installiert. Es handelt sich um ein Perl-Skript, und wie wir bereits erwähnt haben, sind die OpenResty-Ökosystem-Tools alle in Perl geschrieben, was durch die technische Vorliebe des OpenResty-Autors bestimmt wird.

$ which resty
/usr/local/bin/resty

$ head -n 1 /usr/local/bin/resty
#!/usr/bin/env perl

Die resty CLI ist sehr leistungsstark, und wir können resty -h verwenden oder die offizielle Dokumentation für eine vollständige Funktionsliste lesen. Als Nächstes werde ich zwei interessante Funktionen vorstellen.

$ resty --shdict='dogs 1m' -e 'local dict = ngx.shared.dogs dict:set("Tom", 56) print(dict:get("Tom"))'

56

Das obige Beispiel zeigt eine Nginx-Konfiguration mit dem Lua-Code, die die Einrichtung und Abfrage eines gemeinsam genutzten Speicherwörterbuchs ermöglicht. dogs 1m ist eine Nginx-Konfiguration, die einen gemeinsam genutzten Speicherbereich namens dogs mit einer Größe von 1m deklariert. Der gemeinsam genutzte Speicher wird im Lua-Code als Wörterbuch verwendet.

Außerdem werden die Parameter --http-include und --main-include verwendet, um die NGINX-Konfigurationsdatei einzurichten, sodass wir das obige Beispiel wie folgt umschreiben können:

$ resty --http-conf 'lua_shared_dict dogs 1m;' -e 'local dict = ngx.shared.dogs dict:set("Tom", 56) print(dict:get("Tom"))'

Die Standard-Debugging-Tools in der OpenResty-Welt, wie gdb, valgrind, sysetmtap und Mozilla rr, können auch mit resty verwendet werden, um die normale Entwicklung und Tests zu erleichtern. Sie entsprechen verschiedenen Befehlen von resty, sodass die interne Implementierung einfach ist, nur eine zusätzliche Ebene von Befehlszeilenaufrufen. Nehmen wir valgrind als Beispiel.

$ resty --valgrind -e "ngx.say('hello world'); "

ERROR: failed to run command "valgrind /usr/local/openresty/nginx/sbin/nginx -p /tmp/resty_rJeOWaYGIY/ -c conf/nginx.conf": No such file or directory

Sie sind nicht nur in der OpenResty-Welt anwendbar, sondern auch allgemeine Tools für die Serverseite. Lassen Sie uns sie Schritt für Schritt lernen.

Formelleres "hello world"

Das erste OpenResty-Programm, das wir am Anfang geschrieben haben, verwendete den resty-Befehl ohne den master-Prozess und ohne das Lauschen auf bestimmten Ports. Als Nächstes implementieren wir ein weiteres hello world-Programm.

Wir benötigen mindestens drei Schritte, um es zu vervollständigen.

  1. Erstellen Sie ein Arbeitsverzeichnis.
  2. Ändern Sie die NGINX-Konfigurationsdatei, um Lua-Code darin einzubetten.
  3. Starten Sie den OpenResty-Dienst.

Beginnen wir mit der Erstellung eines Arbeitsverzeichnisses.

$ mkdir openresty-sample
$ cd openresty-sample
$ mkdir logs/ conf/

Das Folgende ist eine minimale nginx.conf mit der OpenResty-Direktive content_by_lua im Stammverzeichnis, die die ngx.say-Methode einbettet.

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location / {
            content_by_lua '
                ngx.say("hello, world")
            ';
        }
    }
}

Stellen Sie sicher, dass openresty zuerst in die PATH-Umgebungsvariable aufgenommen wurde; starten Sie dann den OpenResty-Dienst:

$ openresty -p `pwd` -c conf/nginx.conf

Wenn keine Fehler aufgetreten sind, wurde der OpenResty-Dienst erfolgreich gestartet. Wir können ihn mit dem cURL-Befehl aufrufen, um die zurückgegebenen Ergebnisse zu sehen.

$ curl -i 127.0.0.1:8080

HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
hello, world

Herzlichen Glückwunsch! Das formelle Hello World in OpenResty ist abgeschlossen!

Zusammenfassung

Lassen Sie uns überprüfen, was wir heute gelernt haben. Zunächst starten wir die OpenResty-Installation und CLI mit einer einfachen Zeile "hello, world"-Code und schließlich starten wir den OpenResty-Prozess und führen ein echtes Backend-Programm aus.

Unter ihnen ist resty ein Befehlszeilentool, das wir in Zukunft häufig verwenden werden. Daher wird der Demo-Code im Kurs damit ausgeführt, anstatt den OpenResty-Dienst im Hintergrund zu starten.

Noch wichtiger ist, dass viele kulturelle und technische Details hinter OpenResty verborgen sind, und es ist wie ein Eisberg, der auf dem Meer schwimmt. Durch diesen Kurs hoffe ich, Ihnen ein umfassenderes OpenResty zu zeigen, nicht nur seine offengelegten APIs.