Dieser Artikel vergleicht die Arbeit der einfachsten Dienste, die mit dem Camel-Framework und seinen beiden Komponenten implementiert wurden: HTTP und AHC. Wir werden uns nicht mit der Struktur befassen und mit dem Framework selbst arbeiten, es wird davon ausgegangen, dass der Leser bereits ein wenig damit vertraut ist.
Wir werden einen einfachen Camel-Dienst betrachten, der Anforderungen von der Anlegestellenkomponente empfängt, diese beispielsweise verarbeitet, im Protokoll anzeigt, einen anderen Dienst über http aufruft und die Antwort von diesem verarbeitet, z. B. in das Protokoll schreibt.
Zum Testen wurden JMeter-Skripte verwendet, um unseren Dienst gemäß der beabsichtigten Häufigkeit und Intervallen aufzurufen, sowie ein kleiner HTTP-Dienst, der die Rolle eines externen Dienstes spielt und eine Verzögerung von 5 Sekunden ausführt. Die gesamte Kommunikation erfolgt in einer lokalen Schleife (127.0.0.1), sodass Netzwerklatenzen nicht berücksichtigt werden, aber für die vergleichende Analyse nicht benötigt werden.
HTTP-Komponente
In diesem Abschnitt wird die Standard-HTTP-Komponente für die HTTP-Kommunikation beschrieben. Einfacher Servicecode:
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.to("http://{{another.url}}")
.log("finish process body ${body}");
Hinweis: Das Entfernen von Headern, die mit "CamelHttp" beginnen, ist erforderlich, da sie in der Jetty-Komponente verfügbar sind und den Betrieb der Http-Komponente beeinträchtigen können.
Um den Betrieb dieses Dienstes zu testen, führen wir das JMeter-Skript aus, das 25 gleichzeitige Anforderungen sendet.
Proben |
Mindest |
Max |
Error% |
25 |
5012 |
7013 |
20.000% |
, 20% 5 25 (Read timed out). , http- 20 . connectionsPerRoute
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.to("http://{{another.url}}?connectionsPerRoute=200")
.log("finish process body ${body}");
25 . – jetty-, 200. 4 JMeter:
200
300
300 5 , 5
200 5 , 5
1 JVM 214 , .
:
|
|
200 |
0% |
300 |
34.667% |
300 5 |
71.733% |
200 5 |
0% |
300 , 200 jetty-, 100 jetty, 5 , 10. 34% – 100 .
, – 300 5 , 5 , .. 60 , 200 5 , .
, , , , jetty- .
, jetty-, JVM 1 , Docker- , . .
AHC-
AHC- - Camel HTTP. AsyncHttpClient, () . – http- , , .. 5 . , . :
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.to("ahc:http://{{another.url}}")
.log("finish process body ${body}");
, 300 . , http- . JVM:
, . :
|
|
300 5 |
0% |
800 5 |
0% |
1200 5 |
1.533% |
1600 5 |
15.02% |
, , .
, , 1200 1600 http-, - , .
AHC-
AHC-, . :
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.setHeader("rand", ()->new Random().nextInt(10000) )
.toD("ahc:http://{{another.url}}?rand=${headers.rand}")
.log("finish process body ${body}");
Nach dem Ausführen des Skripts mit einem einmaligen Start von 300 Anforderungen wird der Status der Threads in der JVM:
Wie Sie sehen können, fließt zu viel. Tatsache ist, dass die AHC-Komponente für jeden Endpunkt standardmäßig eine eigene Instanz des AsyncHttpClient-Objekts erstellt, von denen jedes über einen eigenen Pool von Verbindungen und Threads verfügt. Daher werden für jede Anforderung zwei Threads erstellt - ein E / A-Thread, ein weiterer Timer-Thread für Steuern Sie Zeitüberschreitungen und halten Sie die Verbindungen im KeepAlive-Status. Um dies zu vermeiden, müssen Sie die AsyncHttpClient-Instanz auf Komponentenebene konfigurieren, die beim Erstellen an den Endpunkt übergeben wird.
AhcComponent ahc = getContext().getComponent("ahc", AhcComponent.class);
ahc.setClient(new DefaultAsyncHttpClient());
Danach wird die Erstellung vieler AsyncHttpClient-Instanzen gestoppt.