Als ich Vorheriger Artikel schrieb, reagierte die von mir selbst erstellte Umgebung ohne Server nur langsam. Es gab ein Hautgefühl. Ich stellte mir vor, dass es langsamer als ein allgemeiner Server sein würde, da der Container intern mit Docker gestartet wurde. Aber um wie viel verschlechtert sich die Reaktionsgeschwindigkeit? Es gibt nicht viele vergleichende Artikel, deshalb habe ich beschlossen, sie tatsächlich zu messen.
Ein kurzer Überblick über das technische Gebiet der serverlosen Architektur
Nach dem Artikel
Ist geschrieben. Dies bedeutet, dass in einer ähnlichen Umgebung ohne Server vorhergesagt werden kann, dass die Antwortzeit ungefähr gleich oder etwas langsamer sein wird.
Wir verwenden eine lokale Umgebung ohne Server mit dem Namen Iron Functions. Diesbezüglich habe ich in der Vergangenheit einen Einführungsartikel geschrieben. Schauen Sie also bitte dort nach.
Grob gesagt handelt es sich um ein praktisches Produkt, mit dem Sie problemlos eine Umgebung ohne Server wie AWS Lambda einführen können.
Diesmal wird für den Benchmark die Sprache Go, Node.js und Python verwendet. Schreiben Sie in jeder Sprache Code, der fast gleich funktioniert. Mal sehen, wie groß der Unterschied ist, wenn sie auf Serverless und auf HTTP-Servern ausgeführt werden, die für jede Sprache (Native) integriert sind.
Go Serverless
package main
import (
"encoding/json"
"fmt"
"os"
)
type Person struct {
Name string
}
func main() {
p := &Person{Name: "World"}
json.NewDecoder(os.Stdin).Decode(p)
fmt.Printf("Hello %v!", p.Name)
}
Go Native
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Person struct {
Name string
}
func handler(w http.ResponseWriter, r *http.Request) {
p := &Person{Name: "World"}
json.NewDecoder(r.Body).Decode(p)
fmt.Fprintf(w, "Hello %v!", p.Name)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":2000", nil)
}
Node.js Serverless
name = "World";
fs = require('fs');
try {
obj = JSON.parse(fs.readFileSync('/dev/stdin').toString())
if (obj.name != "") {
name = obj.name
}
} catch(e) {}
console.log("Hello", name, "from Node!");
Node.js Native
const http = require('http');
name = "World";
http.createServer(
(req, res) => {
var body = "";
req.on(
"data",
(chunk) => { body+=chunk; }
);
req.on(
"end",
() => {
obj = JSON.parse(body);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello ' + obj.name + " from Node Native!");
}
);
}
).listen(6000);
Python Serverless
import sys
sys.path.append("packages")
import os
import json
name = "World"
if not os.isatty(sys.stdin.fileno()):
obj = json.loads(sys.stdin.read())
if obj["name"] != "":
name = obj["name"]
print "Hello", name, "!!!"
Python Native
from http.server import BaseHTTPRequestHandler,HTTPServer
from json import loads
from io import TextIOWrapper
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers.get('content-length'))
text = TextIOWrapper(self.rfile).read(content_length)
self.send_response(200)
self.send_header('Content-type','text/plain')
self.end_headers()
obj = loads(text)
self.wfile.write("Hello {name} !! Welcome to Native Python World!!".format(name=obj["name"]).encode("utf-8"))
PORT = 1000
server = HTTPServer(("127.0.0.1", PORT), Handler)
print("serving at port", PORT)
server.serve_forever()
Der Server für jeden Benchmark wird auf demselben Computer ausgeführt. Ubuntu 16.04 auf einer virtuellen Maschine mit 1 Kern und 2 GB Speicher. Der Server, der die Last stellt, und der Server, der die Last empfängt, sind identisch und verwenden Apache Bench. Bereiten Sie das folgende json und vor
johnny.json
{
"name":"Johnny"
}
Das Laden erfolgt durch Auslösen der Nachbearbeitung mit Apache Bench. Die Anzahl der Anfragen beträgt 100 und die Anzahl der Parallelen beträgt 5. (Die Anzahl der Anfragen ist gering. Wird später beschrieben.) Zu diesem Zeitpunkt wird die Zeit bis zur Rückgabe der Antwort vom Server (Antwortzeit) gemessen.
#XXXX/XXXX ergänzt gegebenenfalls
ab -n 100 -c 5 -p johnny.json -T "Content-Type: application/json" http://localhost:XXXXX/XXXXX
Response Time | min[ms] | mean[ms] | std[ms] | median[ms] | max[ms] | Natives Verhältnis(mean) |
---|---|---|---|---|---|---|
Go Serverless | 3951 | 6579 | 1010 | 6512 | 8692 | 1644.75 |
Go Native | 0 | 4 | 5 | 2 | 37 | - |
Node Serverless | 5335 | 14917 | 3147 | 15594 | 20542 | 621.54 |
Node Native | 5 | 24 | 45 | 12 | 235 | - |
Python Serverless | 5036 | 13455 | 4875 | 14214 | 29971 | 840.94 |
Python Native | 6 | 16 | 4 | 16 | 26 | - |
** Bitte beachten Sie, dass die vertikale Achse der folgenden Abbildung eine logarithmische Skala ist (die Größenbeziehung wird zum leichteren Verständnis in Logarithmus ausgedrückt) **
Wie Sie der Tabelle entnehmen können, ist die Umgebung ohne Server mit ** Go mehr als 1600-mal langsamer als die native Umgebung. Sie können sehen, dass andere Node.js 600-mal langsamer und Python 800-mal langsamer ist. ** ** ** Wenn Sie die Ergebnisse von Python und Node.js vergleichen, finden Sie es möglicherweise seltsam, dass Python schneller ist. Wenn ich einen Folgetest in der nativen Umgebung versuchte, war Python manchmal schneller, wenn die Anzahl der Anforderungen gering und die Anzahl der Parallelen gering war. Wenn die Anzahl der Anforderungen 10.000 oder mehr beträgt, kann Node.js stabiler verarbeitet werden und die Verarbeitung wird schneller als bei Python abgeschlossen. Darüber hinaus führte die native Implementierung von Python manchmal zu einem Fehler und die Anforderung konnte nicht normal verarbeitet werden. Wahrscheinlich ist Go, das einen Geschwindigkeitsunterschied zu dieser Anzahl von Anforderungen aufweist, abnormal eingestellt. Hier möchte ich es mit dem oben erwähnten "AWS Lambda hat eine Verarbeitungszeit von 250 ms bis 8000 ms" vergleichen. Das Ergebnis dieser Benchmark war ein Ergebnis mit wenig persönlichem Unbehagen. Als ich mit Curl selbst eine Anfrage an Iron Functions gestellt habe, fühlte ich mich "langsam", und wenn ich für jede Anfrage einen Docker mache, denke ich, dass es keine Hilfe dafür gibt. Andererseits hatte ich den Eindruck, dass die 250 ms von AWS Lambda sehr schnell sind.
Betrachtet man AWS Lambda, so scheint es zwei Arten von Startmethoden zu geben: Kaltstart und Warmstart. Ersteres unterscheidet sich nicht von dem intuitiven Serverless, und das Bild lautet, dass "für jede Anforderung ein Container erstellt wird", und letzteres scheint "ein einmal erstellter Container wird wiederverwendet". Auf diese Weise ist die Lambda-Implementierung schneller, da möglicherweise kein Container erstellt wird. Es scheint, dass. Ich denke, das ist der Grund, warum wir in 250 ms am schnellsten reagieren können. Auf der anderen Seite implementiert Iron Functions wahrscheinlich nur einen Kaltstart, also denke ich, dass es nicht so schnell ist. Wenn Go jedoch in einer von mir erstellten Umgebung ohne Server ausgeführt wird, ist Max von ca. 8600 ms meiner Meinung nach eine gute Verarbeitungsgeschwindigkeit. Natürlich gibt es einen Unterschied in der Anzahl der Kunden, die verarbeitet werden, aber ist die Geschwindigkeit der Containererstellung / -entsorgung nicht tatsächlich gleich? Ich dachte.
Unten finden Sie einen Link zur Preisliste von AWS Lambda.
AWS Lambda Preisgestaltung https://aws.amazon.com/jp/lambda/pricing/
Der Preisplan scheint nach Nutzungsdauer * Speichernutzung berechnet zu werden, und es scheint, dass Sie die CPU nicht auswählen können. Wie ist die CPU zugeordnet? Es wurde in Hilfe geschrieben.
Und noch ein Artikel, der folgende Artikel
Die Geschichte der Produktionseinführung des Serverless Framework
Es wurde angegeben. Ich habe einige Umgebungstests ohne Server durchgeführt, aber die CPU-Auslastung des Host-Computers nimmt erheblich zu. Daher habe ich mich gefragt, wie die Host-Seite (Amazon) zahlen könnte, aber es scheint, dass der stündliche Stückpreis auf der Amazon-Seite hoch angesetzt ist. Außerdem wird Serverless grundsätzlich so ausgeführt, dass die Antwort erst zurückgegeben werden kann, nachdem der Container gestartet und verworfen wurde. Daher frage ich mich, ob die CPU für eine schnelle Antwort auf einen guten Wert eingestellt ist. Ich dachte.
Normalerweise beträgt die Anzahl der Benchmarks 10.000, oder ich denke, dass einige Muster ausgeführt werden. In diesem Experiment ist die Anzahl der Anforderungen jedoch auf ungefähr 100 begrenzt. Es gibt zwei Gründe. Eins ist, weil es "langsam" ist. Bei der Ausführung mit Serverless dauert es am schnellsten etwa 4000 ms. Daher haben wir keine großen Anfragen bewertet, da dies nicht realistisch war. Das zweite ist, weil es "instabil" ist. Eisenfunktionen haben ein instabiles Verhalten. Selbst wenn die Anforderung ungefähr 100 Mal ist, kann sie daher ungefähr 10 Mal fehlschlagen. Wenn Sie daher die Anzahl der Parallelen oder die Anzahl der Anforderungen erhöhen, besteht eine hohe Wahrscheinlichkeit, dass die Verarbeitung nicht möglich ist. Dies scheint auch vom Lebenszyklus des Doquer-Containers mit Eisenfunktionen abzuhängen, und es war ein Produkt, das eine Zeitüberschreitung aufwies oder keine Zeitüberschreitung aufwies, selbst wenn dieselbe Anfrage gesendet wurde, und es schwierig war, einen genauen Wert zu erhalten. Daher folgen die in diesem Artikel beschriebenen Daten dem Verarbeitungszeitwert selbst. Ich denke eher, dass es genauer ist zu erkennen, dass es im Vergleich zu Native eine Reihenfolge für die Verarbeitungszeit gibt. Auch die Tatsache, dass die Maschine, die die Last aufbringt, und die Maschine, die die Last empfängt, identisch sind, kann ein leicht ungenauer Benchmark sein. Dies liegt einfach daran, dass ich nicht zwei Umgebungen vorbereitet habe. Wenn Sie sich jedoch den Geschwindigkeitsunterschied zwischen der nativen Implementierung und der serverlosen Implementierung ansehen, ist es möglicherweise kein Problem, wenn Sie den Serverstatus beibehalten. .. Ich denke.
Dieser Benchmark hat sehr lange gedauert. Die Veröffentlichung wurde erheblich verzögert, da die Anforderung höchstens 600 Mal 3 bis 4 Stunden dauerte. Und die Langsamkeit von Serverless ist zu einem wirklich bemerkenswerten Ergebnis geworden. Lass es uns benutzen. Ich dachte, aber ich sollte es für eine Weile stoppen ... Andererseits ist AWS Lambda ausgezeichnet ... Und die Geschwindigkeit von Go's http-Server ist erstaunlich. Ich hätte nie gedacht, dass selbst eine so kleine Bank schnell sein würde. Außerdem ist Iron Functions schmerzhaft, da es fast kein japanisches Know-how gibt. Tatsächlich gibt es einen Reverse-Proxy namens fnlb, und eine Methode zum Clustering durch diesen wird ebenfalls offiziell vorbereitet. Dann ist es einfacher zu skalieren. Obwohl ich denke, dass der Vorgang an sich zu langsam ist, kann es wichtig sein, mehr zu tun oder den Engpass zu verbessern. Iron Functions selbst ist in erster Linie in Go geschrieben, also sollte es nicht so langsam sein, aber ... ich frage mich, ob es sich um den Docker-Container handelt ... Hmm. Es ist ein langer Weg ohne Server.
Recommended Posts