Dieser Artikel beschreibt Leistungsprobleme im Zusammenhang mit der Verwendung der Formate LocalDateTime und Instant Time, auf die Alibaba-Ingenieure während des Serialisierungsprozesses gestoßen sind.
Von Lv Renqi
Bei der Durchführung eines Leistungsdrucktests mit einer neuen Version von Apache Dubbo das Attribut der Klasse Transfer Object (TO) Ich habe ein verwandtes Problem gefunden. Durch Ändern von "Date" in "LocalDateTime" wurde der Durchsatz von 50.000 auf 20.000 reduziert und die Antwortzeit von 9 ms auf 90 ms erhöht.
Von diesen Änderungen waren wir am meisten besorgt über die Änderung der Reaktionszeit. Die Reaktionszeit ist in vielerlei Hinsicht der Eckpfeiler guter Leistungsdaten, da Leistungsindikatoren erst dann von Bedeutung sind, wenn ein bestimmtes Reaktionszeitniveau sichergestellt ist. Für Stresstests sind Gigabit-pro-Sekunde- (GPS) und Transaktions-pro-Sekunde- (TPS) Nummern nur zulässig, wenn die Zielantwortzeitnummern erreicht sind. Reine theoretische Zahlen sind bedeutungslos. Beim Cloud Computing ist jede Antwortzeit wichtig. Eine Verlängerung der Antwortzeit des zugrunde liegenden Dienstes um 0,1 ms bedeutet eine Erhöhung der Gesamtkosten um 10%.
Die Latenz ist wie die Achillessehne eines Systems mit Remote-Benutzern. Die Verzögerung des Datenpakets erhöht sich pro 100 km um 1 Millisekunde. Die Wartezeit zwischen Hangzhou und Shanghai beträgt etwa 5 Millisekunden, und die Wartezeit zwischen Shanghai und Shenzhen ist aufgrund der erheblich größeren Entfernung natürlich noch höher. Das direkte Ergebnis der Latenz ist eine Verlängerung der Antwortzeit, die die Benutzererfahrung insgesamt verschlechtert und die Kosten erhöht.
Wenn die Anforderung die Datensätze in derselben Zeile in verschiedenen Einheiten ändert, sind die Kosten sehr hoch, selbst wenn sie konsistent und konsistent sein können. Remote Fast Service Framework, Ein in Alibaba weit verbreitetes verteiltes RPC-Service-Framework. Wenn ein Dienst bei einer Anforderung, die mehr als zehnmal Zugriff auf den Dienst 0.18e27d1f7aNxOS (HSF) oder eine andere entfernte Datenbank erfordert, einen anderen Dienst anruft, wird die Latenz sofort mit einem Schneeballeffekt hinzugefügt.
Der Umgang mit der Zeit ist überall in der Welt der Informatik. Ohne den strengen Zeitbegriff wären 99,99% der Anträge bedeutungslos und unpraktisch. Dies gilt insbesondere für die zeitorientierte benutzerdefinierte Verarbeitung, die heutzutage in den meisten Überwachungssystemen in der Cloud zu finden ist.
Java Development Kit 8 (JDK 8) Zuvor java.util.Date
wurde verwendet, um Datum und Uhrzeit zu beschreiben, und java.util.Calendar
wurde für zeitbezogene Berechnungen verwendet. JDK 8 führt bequemere Zeitklassen wie "Instant", "LocalDateTime", "OffsetDateTime" und "ZonedDateTime" ein. Im Allgemeinen haben diese Klassen die Zeitverarbeitung komfortabler gemacht.
Instant
speichert Zeitstempel im UTC-Format (Agreement World Time) und bietet eine maschinenseitige oder interne Zeitanzeige. Es eignet sich für Szenarien zur Datenbankspeicherung, Geschäftslogik, zum Datenaustausch und zur Serialisierung. "LocalDateTime", "OffsetDateTime" und "ZonedDateTime" enthalten Zeitzonen- oder Saisoninformationen und bieten Benutzern eine Zeitanzeige zur Eingabe und Ausgabe von Daten. Wenn dieselbe Zeit an verschiedene Benutzer ausgegeben wird, sind die Werte unterschiedlich. Beispielsweise wird Käufern und Verkäufern die Lieferzeit einer Bestellung zu unterschiedlichen Ortszeiten angezeigt. Sie können sich diese drei Klassen als Werkzeuge vorstellen, die nach außen und nicht nach den internen Arbeitsteilen der Anwendung gerichtet sind.
Kurz gesagt, "Instant" eignet sich für Back-End-Dienste und -Datenbanken, während "LocalDateTime" und seine Kohorte für Front-End-Dienste und -Anzeigen geeignet sind. Die beiden sind theoretisch kompatibel, erfüllen aber tatsächlich unterschiedliche Funktionen. Das internationale Business-Team verfügt über eine Fülle von Erfahrungen und Ideen in dieser Hinsicht.
Date
und Instant
werden häufig verwendet, um Dubbo in das interne High Speed Services Framework (HSF) von Alibaba zu integrieren.
Sie können versuchen, es zu reproduzieren, um ein genaues Bild von den Leistungsproblemen zu erhalten, die Sie zuvor gesehen haben. Aber zuerst betrachten wir die Leistungsvorteile von "Instant" anhand einer kurzen Demo. Betrachten Sie dazu das allgemeine Szenario, ein Datum im Format "Datum" zu definieren und dann das Format "Sofort" zu verwenden.
@Benchmark
@BenchmarkMode(Mode.Throughput)
public String date_format() {
Date date = new Date();
return new SimpleDateFormat("yyyyMMddhhmmss").format(date);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
public String instant_format() {
return Instant.now().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(
"yyyyMMddhhmmss"));
}
Führen Sie anschließend den Stresstest 30 Sekunden lang an vier lokalen gleichzeitigen Threads aus. Das Ergebnis ist wie folgt.
Benchmark Mode Cnt Score Error Units
DateBenchmark.date_format thrpt 4101298.589 ops/s
DateBenchmark.instant_format thrpt 6816922.578 ops/s
Aus diesen Ergebnissen können wir schließen, dass "Instant" hinsichtlich der Formatleistung vorteilhaft ist. Tatsächlich hat Instant auch für andere Vorgänge einen Leistungsvorteil. Beispielsweise wurde festgestellt, dass Instant beim Addieren und Subtrahieren von Datum und Uhrzeit eine vielversprechende Leistung zeigt.
Als Replikation des oben gezeigten Problems Java und Hessian (optimiert für Taobao) Wir haben auch Stresstests durchgeführt, um die Leistungsänderungen während der Serialisierungs- bzw. Deserialisierungsvorgänge festzustellen.
Hessisch ist HSF 2.2 und Dubbos Standard-Serialisierungsschema:
@Benchmark
@BenchmarkMode(Mode.Throughput)
public Date date_Hessian() throws Exception {
Date date = new Date();
byte[] bytes = dateSerializer.serialize(date);
return dateSerializer.deserialize(bytes);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
public Instant instant_Hessian() throws Exception {
Instant instant = Instant.now();
byte[] bytes = instantSerializer.serialize(instant);
return instantSerializer.deserialize(bytes);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
public LocalDateTime localDate_Hessian() throws Exception {
LocalDateTime date = LocalDateTime.now();
byte[] bytes = localDateTimeSerializer.serialize(date);
return localDateTimeSerializer.deserialize(bytes);
}
Das Ergebnis war wie folgt. Bei Verwendung des hessischen Protokolls sank der Durchsatz bei Verwendung der Formate "Instant" und "LocalDateTime" stark. In der Realität ist der Durchsatz 100-mal niedriger als bei Verwendung des Datumsformats. Bei weiteren Untersuchungen stellten wir fest, dass der serialisierte Byte-Stream "Datum" 6 Byte beträgt, während der LocalDateTime-Stream 256 Byte beträgt. Es erhöht auch die Kosten der Netzwerkbandbreite für die Übertragung. Die in Java integrierte Serialisierungslösung weist einen leichten Rückgang auf, macht jedoch keinen wesentlichen Unterschied.
Benchmark Mode Cnt Score Error Units
DateBenchmark.date_Hessian thrpt 2084363.861 ops/s
DateBenchmark.localDate_Hessian thrpt 17827.662 ops/s
DateBenchmark.instant_Hessian thrpt 22492.539 ops/s
DateBenchmark.instant_Java thrpt 1484884.452 ops/s
DateBenchmark.date_Java thrpt 1500580.192 ops/s
DateBenchmark.localDate_Java thrpt 1389041.578 ops/s
Unsere Analyse ist wie folgt. Das Datum ist eine von acht primitiven Arten der Serialisierung hessischer Objekte.
Zweitens musste Instant sowohl für die Serialisierung als auch für die Deserialisierung "Class.forName" durchlaufen, was zu einem starken Rückgang des Durchsatzes und der Antwortzeit führte. Daher hat Date einen Vorteil.
Ich habe festgestellt, dass Sie Hessisch aktualisieren und optimieren können, indem Sie com.alibaba.com.caucho.hessian.io.Serializer in einer Klasse wie Instant über eine Erweiterung implementieren und in der SerializerFactory registrieren, also in diesem Artikel Sie können das angesprochene Problem lösen. Es wird jedoch Kompatibilitätsprobleme mit früheren und zukünftigen Versionen geben. Dies ist ein ernstes Problem. Alibabas ziemlich komplexe Abhängigkeiten machen dies unmöglich. Angesichts dieses Problems können wir nur empfehlen, Datum als bevorzugtes Zeitattribut für die TO-Klasse zu verwenden.
Technisch gesehen ist das RPC-Protokoll von HSF ein Protokoll auf Sitzungsebene, und die Versionserkennung wird auch hier durchgeführt. Die Präsentationsschicht der Servicedaten ist jedoch in einem selbstbeschreibenden Serialisierungsframework wie Hessisch implementiert und weist keine Versionserkennung auf. Daher ist ein Upgrade sehr schwierig.
Recommended Posts