Mit der rasanten Entwicklung der Internettechnologie sind die Anforderungen an hohe Leistung, hohe Parallelität und hohe Verfügbarkeit auf der Serverseite immer höher geworden. Als leistungsstarkes, asynchrones und nicht blockierendes Netzwerkkommunikations-Framework ist Netty erfreut sich bei Entwicklern zunehmender Beliebtheit und Nutzung.
In diesem Artikel wird erläutert, wie Sie mit dem Netty-Framework einen leistungsstarken API-Server implementieren.
1. Was ist Netty? Netty ist ein asynchrones, ereignisgesteuertes Netzwerkanwendungsframework auf Basis von Java NIO, mit dem schnell leistungsstarke und zuverlässige Netzwerkkommunikationsprogramme wie Clients und Server entwickelt werden können.
Zu seinen Kernkomponenten gehören Puffer, Kanal, EventLoop, Codec usw. Buffer ist die Pufferkomponente von Netty, Channel bietet eine abstrakte Netzwerkkommunikationsschnittstelle, EventLoop ist das ereignisgesteuerte Modell von Netty und Codec ist ein Codec. Durch diese Komponenten kann das Netty-Framework leistungsstarke Netzwerkkommunikationsfunktionen mit hoher Parallelität und geringer Latenz bereitstellen.
2. Grundlegende Verwendung von Netty
Zuerst müssen wir Netty-Abhängigkeiten einführen:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.42.Final</version> </dependency>
Dann müssen wir ein Bootstrap-Objekt erstellen und dieses Objekt verwenden, um unseren Netty-Server zu starten:
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new ChunkedWriteHandler()); pipeline.addLast(new HttpServerHandler()); } }); ChannelFuture future = bootstrap.bind(port).sync(); future.channel().closeFuture().sync(); }finally{ bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }
Im obigen Code: hat zwei EventLoopGroup-Objekte erstellt, eine „bossGroup“ zum Empfangen von Client-Anfragen und eine „workerGroup“ zum Verarbeiten von Client-Anfragen. Konfigurieren Sie die Parameter des Netty-Servers über das ServerBootstrap-Objekt, einschließlich des Kommunikationsprotokolls (NioServerSocketChannel), des Prozessors (Handler) und der Kanalinitialisierung sowie anderer Vorgänge.
Wir können auch sehen, dass wir im obigen Code die Komponenten HttpServerCodec und HttpObjectAggregator hinzugefügt haben, um die Kodierung, Dekodierung und Aggregation von HTTP-Anfragen und -Antworten zu implementieren. Gleichzeitig haben wir ChunkedWriteHandler hinzugefügt, um die Verarbeitung großer Datenströme zu implementieren.
Schließlich binden wir den Port und starten den Netty-Server über die Methode „bootstrap.bind“, blockieren den Hauptthread und warten darauf, dass der Netty-Server über die Methode „future.channel().closeFuture().sync()“ heruntergefahren wird .
3. Verwenden Sie Netty, um einen leistungsstarken API-Server zu implementieren.
Für einen API-Server müssen wir normalerweise eine große Anzahl von Anfragen und Antworten verarbeiten und gleichzeitig die Systemverfügbarkeit und eine leistungsstarke Antwortzeit sicherstellen.
Hier nehmen wir die Implementierung eines einfachen API-Servers als Beispiel, um vorzustellen, wie das Netty-Framework zur Implementierung eines Hochleistungs-API-Servers verwendet wird.
1. Schnittstellendefinition
Lassen Sie uns zunächst eine einfache API-Schnittstelle definieren, die zur Implementierung der Funktion zum Abrufen von Benutzerinformationen verwendet wird:
GET /user/{id} HTTP/1.1 Host: localhost:8888
wobei {id} die ID-Nummer des Benutzers ist, müssen wir eine Abfrage basierend auf dieser ID-Nummer durchführen Benutzerinformationen und an den Kunden zurückgegeben.
2. Geschäftsverarbeitung
Als nächstes müssen wir die Geschäftslogikverarbeitung implementieren, das heißt, Benutzerinformationen basierend auf der ID-Nummer in der Client-Anfrage abfragen und die Abfrageergebnisse an den Client zurückgeben.
Erstens erstellen wir einen Prozessor HttpServerHandler, der von SimpleChannelInboundHandler erbt. Wir können unsere Geschäftslogik in diesem Prozessor implementieren.
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { HttpServerRoute route = HttpServerRoute.builder() .addRoute("/user/{id}", new GetUserHandler()) .build(); HttpServerRequest request = new HttpServerRequest(msg); HttpServerResponse response = new HttpServerResponse(ctx, msg); route.route(request, response); } }
Sie können sehen, dass wir im obigen Code den Routenabgleich über das HttpServerRoute-Objekt implementieren. Wenn wir eine Client-Anfrage erhalten, konvertieren wir die Anfrage in ein HttpServerRequest-Objekt, wickeln das Antwortobjekt HttpServerResponse darin ein und verwenden dann das HttpServerRoute-Objekt, um die Routing-Regeln abzugleichen und die Anfrage zur Verarbeitung an den entsprechenden Prozessor zu verteilen.
Wir müssen den GetUserHandler-Prozessor implementieren, der zum Abfragen von Benutzerinformationen basierend auf der Benutzer-ID verwendet wird:
public class GetUserHandler implements HttpServerHandlerInterface { @Override public void handle(HttpServerRequest request, HttpServerResponse response) throws Exception { String id = request.getPathParam("id"); //查询用户信息 User user = UserService.getUserById(id); if (user != null) { JSONObject json = new JSONObject(); json.put("id", user.getId()); json.put("name", user.getName()); response.sendJSON(HttpResponseStatus.OK, json.toJSONString()); } else { response.sendError(HttpResponseStatus.NOT_FOUND); } } }
Im obigen Code fragen wir Benutzerinformationen basierend auf der ID-Nummer in der Anfrage ab und erstellen den JSON des Fordern Sie eine Antwort über JSONObject-String-Daten an und geben Sie schließlich die Abfrageergebnisse an den Client zurück.
Wir müssen auch die UserService-Klasse implementieren, um die Funktion zum Abfragen von Benutzerinformationen bereitzustellen:
public class UserService { public static User getUserById(String id) { //查询数据库中的用户信息 } }
3. Leistungstest
Abschließend testen wir die Antwortzeit und QPS (Parallelität pro Sekunde) des Netty-Hochleistungs-API-Servers Anzahl der von uns umgesetzten Anfragen).
Mit dem Apache ab-Tool können wir mehrere gleichzeitige Client-Anfragen simulieren und Statistiken zur Antwortzeit und QPS-Informationen sammeln. Verwenden Sie den folgenden Befehl:
ab -n 10000 -c 100 -k http://localhost:8888/user/1
Parameterbeschreibung:
-n: Gibt die Gesamtzahl der Anfragen an
-c: Gibt die Anzahl gleichzeitiger Anfragen an
-k: Zeigt die Aktivierung von Keep-Alive-Verbindungen an
Durch Tests haben wir kann die Antwortzeit- und QPS-Informationen abrufen:
Server Software: Server Hostname: localhost Server Port: 8888 Document Path: /user/1 Document Length: 36 bytes Concurrency Level: 100 Time taken for tests: 3.777 seconds Complete requests: 10000 Failed requests: 0 Keep-Alive requests: 10000 Total transferred: 1460000 bytes HTML transferred: 360000 bytes Requests per second: 2647.65 [#/sec] (mean) Time per request: 37.771 [ms] (mean) Time per request: 0.378 [ms] (mean, across all concurrent requests) Transfer rate: 377.12 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 2 1.2 2 10 Processing: 3 32 11.3 32 84 Waiting: 3 32 11.3 32 84 Total: 6 34 11.2 34 86 Percentage of the requests served within a certain time (ms) 50% 34 66% 38 75% 40 80% 42 90% 49 95% 55 98% 64 99% 71 100% 86 (longest request)
Wie Sie sehen können, war unser API-Server in der Lage, die Simulation von 100 gleichzeitigen Anfragen im Test effektiv zu verarbeiten und konnte 2647,65 Anfragen pro Sekunde verarbeiten, mit einer durchschnittlichen Antwortzeit von nur 37,771 Millisekunden.
4. Zusammenfassung
Durch die obige Einführung und die Schritte haben wir gelernt, wie man Netty als Netzwerkkommunikations-Framework verwendet und damit leistungsstarke API-Server entwickelt. Durch die Verwendung des Netty-Frameworks kann die Serverleistung erheblich verbessert werden, sodass unser Server über eine hohe Parallelität, hohe Zuverlässigkeit, geringe Latenz und andere Eigenschaften verfügt. Gleichzeitig verfügt das Netty-Framework über eine hohe Skalierbarkeit und Flexibilität und lässt sich problemlos in jede Anwendung integrieren.
Als Teil des Java-Back-End-Entwicklungstechnologie-Stacks gehört auch die Verwendung des Netty-Frameworks zu den Fähigkeiten, die beherrscht werden müssen.
Das obige ist der detaillierte Inhalt vonJava-Backend-Entwicklung: Implementierung eines leistungsstarken API-Servers mit Netty. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!