OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandelnWir veröffentlichen das Transkript des Konferenzberichts erneut HighLoad ++ 2016, die vom 7. bis 8. November letzten Jahres in Skolkovo bei Moskau stattfand. Wladimir Protasow erklärt, wie man die NGINX-Funktionalität mit OpenResty und Lua erweitert.

Hallo zusammen, mein Name ist Vladimir Protasov, ich arbeite für Parallels. Ich erzähle dir ein wenig über mich. Ich verbringe drei Viertel meines Lebens damit, Code zu schreiben. Ich bin im wahrsten Sinne des Wortes ein Programmierer durch und durch geworden: Manchmal sehe ich Code in meinen Träumen. Ein Viertel des Lebens besteht aus industrieller Entwicklung, dem Schreiben von Code, der direkt in die Produktion geht. Code, den einige von Ihnen verwenden, aber nicht kennen.

Um Ihnen mitzuteilen, wie schlimm es war. Als ich noch ein kleiner Junge war, kam ich herein und sie gaben mir diese zwei Terabyte-Datenbanken. Es ist jetzt für alle Highload da. Ich ging zu Konferenzen und fragte: „Leute, sagt mir, habt ihr Big Data, ist alles cool?“ Wie viele Stützpunkte gibt es dort? Sie antworteten mir: „Wir haben 100 Gigabyte!“ Ich sagte: „Cool, 100 Gigabyte!“ Und ich habe mir überlegt, wie ich das Pokerface geschickt wahren kann. Du denkst, ja, die Jungs sind cool, und dann kommst du zurück und bastelst an diesen Multi-Terabyte-Datenbanken herum. Und das ist ein Junior. Können Sie sich vorstellen, was für ein Hit das ist?

Ich kenne mehr als 20 Programmiersprachen. Das musste ich im Laufe der Arbeit herausfinden. Sie geben Ihnen Code in Erlang, in C, in C++, in Lua, in Python, in Ruby, in etwas anderem, und Sie müssen alles herausschneiden. Im Allgemeinen musste ich. Es war nicht möglich, die genaue Zahl zu berechnen, aber irgendwo bei etwa 20 ging die Zahl verloren.

Da hier jeder weiß, was Parallels ist und was wir tun, werde ich nicht darüber sprechen, wie cool wir sind und was wir tun. Ich kann Ihnen nur sagen, dass wir 13 Büros auf der ganzen Welt haben, mehr als 300 Mitarbeiter und Entwicklung in Moskau, Tallinn und Malta. Wenn Sie möchten, können Sie nach Malta ziehen, wenn es im Winter kalt ist und Sie Ihren Rücken wärmen müssen.

Insbesondere schreibt unsere Abteilung in Python 2. Wir sind im Geschäft und haben keine Zeit, modische Technologien einzuführen, also leiden wir. Wir haben Django, weil es alles hat, und wir haben den Überschuss genommen und ihn weggeworfen. Auch MySQL, Redis und NGINX. Wir haben auch viele andere coole Sachen. Wir haben MongoDB, wir haben Hasen, die herumlaufen, wir haben einfach nichts – aber es gehört nicht mir, und ich mache es nicht.

OpenResty

Ich habe von mir erzählt. Mal sehen, worüber ich heute sprechen werde:

  • Was ist OpenResty und womit wird es gegessen?
  • Warum das Rad neu erfinden, wenn wir Python, NodeJS, PHP, Go und andere coole Dinge haben, mit denen jeder zufrieden ist?
  • Und ein paar Beispiele aus dem wirklichen Leben. Ich musste den Bericht stark kürzen, da ich ihn für 3,5 Stunden hatte, daher wird es nur wenige Beispiele geben.

OpenResty ist NGINX. Dank ihm haben wir einen vollwertigen Webserver, der gut geschrieben ist und schnell arbeitet. Ich denke, die meisten von uns verwenden NGINX in der Produktion. Ihr wisst alle, dass er schnell und cool ist. Sie haben darin coole synchrone E/A erstellt, sodass wir nichts auf die gleiche Weise durchlaufen müssen, wie es in Python der Fall war. Gevent ist cool, cool, aber wenn Sie C-Code schreiben und mit gevent etwas schief geht, werden Sie beim Debuggen verrückt. Ich habe die Erfahrung gemacht: Es hat ganze zwei Tage gedauert, bis ich herausgefunden habe, was da schief gelaufen ist. Wenn jemand nicht ein paar Wochen vorher gegraben, das Problem gefunden, es ins Internet geschrieben und Google es nicht gefunden hätte, dann wären wir völlig verrückt geworden.

NGINX führt bereits Caching und statische Inhalte durch. Sie müssen sich keine Gedanken darüber machen, wie Sie es menschlich machen, damit Sie nicht irgendwo langsamer werden und nicht irgendwo Deskriptoren verlieren. Nginx ist sehr bequem bereitzustellen, Sie müssen nicht darüber nachdenken, was Sie nehmen sollen – WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx wurde installiert, den Admins übergeben, sie wissen, wie man damit arbeitet. Nginx bearbeitet Anfragen strukturiert. Ich werde etwas später darüber sprechen. Kurz gesagt, es gibt eine Phase, in der er die Anfrage einfach angenommen hat, in der er sie bearbeitet hat und in der er den Inhalt an den Benutzer weitergegeben hat.

Nginx ist cool, aber es gibt ein Problem: Es ist nicht flexibel genug, selbst mit all den coolen Funktionen, die die Jungs in die Konfiguration eingefügt haben, obwohl es anpassbar ist. Diese Kraft reicht nicht aus. Deshalb haben die Jungs von Taobao vor langer Zeit, ich glaube vor etwa acht Jahren, Lua eingebaut. Was gibt er?

  • Größe. Es ist klein. LuaJIT verursacht etwa 100–200 Kilobyte Speicher-Overhead und minimalen Leistungs-Overhead.
  • Geschwindigkeit. Der LuaJIT-Interpreter liegt in vielen Situationen nahe an C, in manchen Situationen verliert er gegen Java, in manchen überholt er es. Eine Zeit lang galt er als modernster, coolster JIT-Compiler. Jetzt gibt es kühlere, aber die sind sehr schwer, zum Beispiel der gleiche V8. Einige JS-Interpreter und Java HotSpot sind an manchen Stellen schneller, verlieren aber dennoch an manchen Stellen.
  • Leicht zu lernen. Wenn Sie beispielsweise über eine Perl-Codebasis verfügen und nicht Booking sind, werden Sie keine Perl-Programmierer finden. Weil sie nicht da sind, wurden sie alle weggebracht, und es ist langwierig und schwierig, sie zu unterrichten. Wenn Sie Programmierer für etwas anderes suchen, müssen diese möglicherweise auch umgeschult oder gefunden werden. Im Fall von Lua ist alles einfach. Lua kann von jedem Junior in drei Tagen erlernt werden. Ich brauchte ungefähr zwei Stunden, um es herauszufinden. Zwei Stunden später war ich bereits damit beschäftigt, Code in der Produktion zu schreiben. Ungefähr eine Woche später ging er direkt zur Produktion und verließ das Unternehmen.

Im Ergebnis sieht es so aus:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Hier gibt es viel. OpenResty hat eine Reihe von Modulen zusammengestellt, sowohl Luash als auch Engines. Und Sie haben alles bereit – bereitgestellt und funktionsfähig.

Примеры

Genug der Texte, kommen wir zum Code. Hier ist ein kleines Hallo Welt:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Was ist dort? Dies ist der Standort des Motors. Wir machen uns keine Sorgen, wir schreiben kein eigenes Routing, wir nehmen kein vorgefertigtes – wir haben es bereits in NGINX, wir leben gut und faul.

content_by_lua_block ist ein Block, der besagt, dass wir Inhalte mithilfe eines Lua-Skripts bereitstellen. Wir nehmen eine Engines-Variable remote_addr und hineinschlüpfen string.format. Das ist ja so, das und sprintf, nur in Lua, nur richtig. Und wir geben es dem Kunden.

Als Ergebnis wird es so aussehen:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Aber zurück zur realen Welt. In der Produktion stellt niemand Hello World bereit. Unsere Anwendung geht normalerweise in die Datenbank oder woanders hin und wartet die meiste Zeit auf eine Antwort.

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Sitzt einfach da und wartet. Es ist nicht sehr gut. Wenn 100.000 Nutzer kommen, ist es für uns sehr hart. Nehmen wir daher eine einfache Anwendung als Beispiel. Wir werden nach Bildern suchen, zum Beispiel Katzen. Nur werden wir nicht nur suchen, sondern die Schlüsselwörter erweitern und, wenn der Benutzer nach „Kätzchen“ gesucht hat, Katzen, Flauschige usw. finden. Zuerst müssen wir die Anfragedaten im Backend abrufen. Es sieht aus wie das:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Mit zwei Zeilen können Sie GET-Parameter ohne Komplikationen abrufen. Dann erhalten wir diese Informationen beispielsweise aus einer Datenbank mit einer Tabelle nach Schlüsselwort und Erweiterung mithilfe einer regulären SQL-Abfrage. Alles ist einfach. Es sieht aus wie das:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Wir verbinden die Bibliothek resty.mysql, die wir bereits im Bausatz haben. Wir müssen nichts installieren, alles ist bereit. Geben Sie an, wie eine Verbindung hergestellt und eine SQL-Abfrage erstellt wird:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Es ist ein wenig beängstigend, aber es funktioniert. Hier ist 10 die Grenze. Wir holen 10 Platten heraus, wir sind faul, wir wollen nicht mehr zeigen. In SQL habe ich das Limit vergessen.

Dann finden wir Bilder für alle Anfragen. Wir sammeln eine Reihe von Anfragen und füllen eine Lua-Tabelle mit dem Namen aus reqs, und TU ngx.location.capture_multi.

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Alle diese Anfragen laufen parallel und die Antworten werden an uns zurückgesendet. Die Laufzeit entspricht der Reaktionszeit des langsamsten. Wenn wir alle innerhalb von 50 Millisekunden antworten und hundert Anfragen gesendet haben, erhalten wir innerhalb von 50 Millisekunden eine Antwort.

Da wir faul sind und die HTTP-Verarbeitung und das Caching nicht schreiben wollen, lassen wir NGINX alles für uns erledigen. Wie Sie gesehen haben, gab es eine Anfrage url/fetch, da ist er:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Wir machen einfach proxy_pass, geben Sie an, wo zwischengespeichert werden soll, wie es geht, und alles funktioniert für uns.

Dies reicht jedoch nicht aus, wir müssen die Daten weiterhin an den Benutzer weitergeben. Die einfachste Idee besteht darin, alles ganz einfach in zwei Zeilen in JSON zu serialisieren. Wir geben Content-Type, wir geben JSON.

Es gibt jedoch eine Schwierigkeit: Der Benutzer möchte JSON nicht lesen. Wir müssen Frontend-Entwickler gewinnen. Manchmal haben wir zunächst keine Lust darauf. Ja, und SEO-Spezialisten werden sagen, dass es ihnen egal ist, wenn wir nach Bildern suchen. Und wenn wir ihnen Inhalte geben, werden sie sagen, dass unsere Suchmaschinen nichts indizieren.

Was tun damit? Selbstverständlich geben wir dem Benutzer HTML. Das Generieren mit Handles ist nicht selbstverständlich, daher möchten wir Vorlagen verwenden. Dafür gibt es eine Bibliothek lua-resty-template.

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Sie müssen die drei gefürchteten Buchstaben OPM gesehen haben. OpenResty verfügt über einen eigenen Paketmanager, über den Sie eine Reihe verschiedener Module installieren können, insbesondere lua-resty-template. Es handelt sich um eine einfache Vorlagen-Engine, die den Django-Vorlagen ähnelt. Dort können Sie Code schreiben und Variablenersetzungen durchführen.

Als Ergebnis wird alles ungefähr so ​​aussehen:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Wir haben die Daten genommen und die Vorlage erneut in zwei Zeilen gerendert. Der Benutzer ist glücklich, hat Katzen bekommen. Da wir die Anfrage ausgeweitet haben, hat er auch einen Seebären für Kätzchen bekommen. Man weiß nie, vielleicht hat er danach gesucht, aber er konnte seine Bitte nicht richtig formulieren.

Alles ist cool, aber wir befinden uns in der Entwicklung und möchten es den Benutzern noch nicht zeigen. Lassen Sie uns eine Autorisierung durchführen. Sehen wir uns dazu an, wie NGINX die Anfrage im Hinblick auf OpenResty verarbeitet:

  • Erste Phase - Zugang, als der Benutzer gerade kam und wir ihn anhand der Header, der IP-Adresse und anderer Daten betrachteten. Sie können es sofort abhacken, wenn es uns nicht gefällt. Dies kann zur Autorisierung verwendet werden. Wenn wir viele Anfragen erhalten, können wir diese in dieser Phase problemlos abschneiden.
  • umschreiben. Einige Anforderungsdaten werden neu geschrieben.
  • Inhalt. Wir geben dem Benutzer Inhalte.
  • Header-Filter. Ändern Sie die Antwortheader. Wenn wir verwendet haben proxy_pass, können wir einige Header neu schreiben, bevor wir sie dem Benutzer geben.
  • Körperfilter. Wir können den Körper verändern.
  • Log - Protokollierung. Es ist möglich, Protokolle in Elasticsearch ohne eine zusätzliche Ebene zu schreiben.

Unsere Autorisierung wird in etwa so aussehen:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Wir werden es noch hinzufügen location, den wir zuvor beschrieben haben, und fügen Sie dort den folgenden Code ein:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Wir schauen, ob wir einen Cookie-Token haben. Wenn nicht, werfen wir eine Genehmigung ein. Benutzer sind schlau und vermuten möglicherweise, dass ein Cookie-Token gesetzt werden muss. Deshalb werden wir es auch in Redis einfügen:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Der Code für die Arbeit mit Redis ist sehr einfach und unterscheidet sich nicht von anderen Sprachen. Gleichzeitig werden alle Ein-/Ausgaben, was da ist, was hier ist, nicht blockiert. Wenn Sie synchronen Code schreiben, funktioniert dieser asynchron. Wie bei gevent, nur gut gemacht.

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Lassen Sie uns die Autorisierung selbst durchführen:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Wir sagen, dass wir den Anfragetext lesen müssen. Wir erhalten POST-Argumente und prüfen, ob Login und Passwort korrekt sind. Wenn dies nicht der Fall ist, werfen wir eine Autorisierung ein. Und wenn sie richtig sind, schreiben wir den Token an Redis:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Vergessen Sie nicht, das Cookie zu setzen, dies geschieht ebenfalls in zwei Zeilen:

OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Das Beispiel ist einfach und spekulativ. Natürlich werden wir keinen Service anbieten, der Menschen Katzen zeigt. Aber wer kennt uns? Schauen wir uns also an, was in der Produktion getan werden kann.

  • Minimalistisches Backend. Manchmal müssen wir ziemlich viele Daten an das Backend weitergeben: Irgendwo müssen wir das Datum ersetzen, irgendwo müssen wir eine Art Liste anzeigen, sagen, wie viele Benutzer sich derzeit auf der Website befinden, einen Zähler oder Statistiken hinzufügen. Etwas so Kleines. Einige minimale Teile können sehr einfach hergestellt werden. Das wird schnell, einfach und großartig sein.
  • Datenvorverarbeitung. Manchmal möchten wir Anzeigen in unsere Seite einbetten und nehmen diese Anzeigen mit API-Anfragen entgegen. Das geht hier ganz einfach. Wir laden unser Backend nicht, das bereits hart arbeitet. Hier können Sie abholen und abholen. Wir können etwas JS formen oder, im Gegenteil, etwas ablösen, vorverarbeiten, bevor wir es dem Benutzer geben.
  • Fassade für Microservice. Das ist auch ein sehr guter Fall, ich habe ihn umgesetzt. Davor habe ich für Tenzor gearbeitet, ein elektronisches Berichtsunternehmen, das Berichte für etwa die Hälfte der juristischen Personen im Land bereitstellt. Wir haben einen Dienst erstellt, viele Dinge werden dort mit demselben Mechanismus erledigt: Routing, Autorisierung und mehr.
    OpenResty kann als Bindeglied für Ihre Microservices verwendet werden, um einen einzigen Zugriff auf alles und eine einzige Schnittstelle bereitzustellen. Da Microservices so geschrieben werden können, dass Sie hier Node.js, hier PHP, hier Python und hier etwas Erlang haben, verstehen wir, dass wir nicht überall den gleichen Code neu schreiben wollen. Daher kann OpenResty an der Vorderseite eingesteckt werden.

  • Statistiken und Analysen. Normalerweise befindet sich NGINX am Eingang und alle Anfragen werden darüber weitergeleitet. An diesem Ort ist es sehr bequem zu sammeln. Sie können etwas sofort berechnen und irgendwohin werfen, zum Beispiel dasselbe Elasticsearch, Logstash, oder es einfach in das Protokoll schreiben und es dann irgendwohin senden.
  • Mehrbenutzersysteme. Online-Spiele eignen sich beispielsweise auch sehr gut. Heute wird Ihnen Alexander Gladysh in Kapstadt erklären, wie Sie mit OpenResty schnell einen Prototyp eines Multiplayer-Spiels erstellen können.
  • Anforderungsfilterung (WAF). Mittlerweile ist es in Mode, alle Arten von Webanwendungs-Firewalls zu erstellen, und es gibt viele Dienste, die diese bereitstellen. Mithilfe von OpenResty können Sie sich eine Webanwendungs-Firewall erstellen, die Anfragen einfach und unkompliziert nach Ihren Anforderungen filtert. Wenn Sie Python haben, verstehen Sie, dass Ihnen PHP definitiv nicht injiziert wird, es sei denn, Sie starten es natürlich irgendwo von der Konsole aus. Sie wissen, dass Sie MySQL und Python haben. Wahrscheinlich können sie hier versuchen, eine Art Verzeichnisdurchlauf durchzuführen und etwas in die Datenbank einzuschleusen. So können Sie dumme Anfragen schnell und kostengünstig direkt an der Front herausfiltern.
  • Gemeinschaft. Da OpenResty auf NGINX basiert, hat es einen Bonus – diesen NGINX-Community. Es ist sehr umfangreich und viele der Fragen, die Sie zunächst haben werden, wurden bereits von der NGINX-Community beantwortet.

    Lua-Entwickler. Gestern habe ich mit den Jungs gesprochen, die zum HighLoad++-Schulungstag gekommen sind, und gehört, dass nur Tarantool in Lua geschrieben ist. Das ist nicht so, viele Dinge sind in Lua geschrieben. Beispiele: OpenResty, Prosody XMPP-Server, Love2D-Spiel-Engine, Lua wird in Warcraft und anderswo geskriptet. Es gibt viele Lua-Entwickler, sie haben eine große und reaktionsfähige Community. Alle meine Lua-Fragen wurden innerhalb weniger Stunden beantwortet. Wenn Sie an die Mailingliste schreiben, gibt es buchstäblich in wenigen Minuten bereits eine Reihe von Antworten, die beschreiben, was und wie, was was ist. Es ist großartig. Leider gibt es nicht überall eine so freundliche, aufrichtige Gemeinschaft.
    OpenResty verfügt über GitHub, wo Sie ein Problem eröffnen können, wenn etwas kaputt geht. Es gibt eine Mailingliste bei Google Groups, in der Sie allgemeine Themen besprechen können, es gibt eine Mailingliste auf Chinesisch – man weiß nie, vielleicht sprechen Sie kein Englisch, aber Sie haben Chinesischkenntnisse.

Ergebnisse

  • Ich hoffe, ich konnte vermitteln, dass OpenResty ein sehr praktisches Web-Framework ist.
  • Die Eintrittsschwelle ist niedrig, da der Code dem ähnelt, was wir schreiben, und die Sprache recht einfach und minimalistisch ist.
  • Es bietet asynchrone E/A ohne Rückrufe, wir werden keine Nudeln haben, da wir manchmal in NodeJS schreiben können.
  • Die Bereitstellung ist einfach, da wir nur NGINX mit dem richtigen Modul und unserem Code benötigen und alles sofort funktioniert.
  • Große und reaktionsfähige Community.

Ich habe nicht im Detail erzählt, wie das Routing funktioniert, es stellte sich heraus, dass es eine sehr lange Geschichte war.

Danke!


Vladimir Protasov – OpenResty: NGINX in einen vollwertigen Anwendungsserver verwandeln

Source: habr.com

Kommentar hinzufügen