Akka HTTP と Netty の主な違いを誰かに説明してもらえますか? Nettyは、FTPなどの他のプロトコルも提供しています。 AkkaHTTPはScalaおよびJavaであり、 アクターモデル上に構築 )で使用できます。ただし、これを除けば、両方とも非同期です。いつAkkaHTTPを使用し、いつNettyを使用しますか?両方の一般的な使用例は何ですか?
これが私が主な対照的な領域として見ているものです:
コーディングスタイル
Nettyの サーバーの破棄の例 を取り上げましょう。これは、ドキュメントの最初のものであることを考えると、おそらく最も簡単な例です。
akka-http
の場合、これは比較的簡単です。
object WebServer {
def main(args: Array[String]) {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
val route =
extractRequestEntity { entity =>
onComplete(entity.discardBytes(materializer)) { _ =>
case _ => complete(StatusCodes.Ok)
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
}
Nettyの場合、これははるかに冗長です。
public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1)
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
// Discard the received data silently.
((ByteBuf) msg).release(); // (3)
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
public class DiscardServer {
private int port;
public DiscardServer(int port) {
this.port = port;
}
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // (7)
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new DiscardServer(8080).run();
}
}
ディレクティブ
私の意見では、akka-httpの最大の強みの1つは ディレクティブ です。これは、複雑な要求処理ロジックにDSLを提供します。たとえば、GET
およびPUT
リクエストに対して1つのメッセージで応答し、他のすべてのリクエストメソッドに対して別のメッセージで応答したいとします。これは、ディレクティブを使用すると非常に簡単です。
val route =
(get | put) {
complete("You sent a GET or PUT")
} ~
complete("Shame shame")
リクエストパスから注文アイテムと数量を取得する場合:
val route =
path("order" / Segment / IntNumber) { (item, qty) =>
complete(s"Your order: item: $item quantity: $qty")
}
この機能はnetty内には存在しません。
ストリーミング
最後に注意するのは、ストリーミングに関することです。 akka-httpはakka-stream
に基づいています。したがって、akka-httpはリクエストエンティティのストリーミングの性質をうまく処理します。 nettyの 受信データを調べる 例を見てください。akkaの場合、これは次のようになります。
//a stream with a Source, intermediate processing steps, and a Sink
val entityToConsole : (RequestEntity) => Future[Done] =
(_ : RequestEntity)
.getDataBytes()
.map(_.utf8String)
.to(Sink.foreach[String](println))
.run()
val route =
extractRequestEntity { entity =>
onComplete(entityToConsole(entity)) { _ =>
case Success(_) => complete(200, "all data written to console")
case Failure(_) => complete(404, "problem writing to console)
}
}
Nettyは、バイトバッファとwhileループで同じ問題を処理する必要があります。
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
try {
while (in.isReadable()) { // (1)
System.out.print((char) in.readByte());
System.out.flush();
}
} finally {
ReferenceCountUtil.release(msg); // (2)
}
}
Akka HTTPサーバーは、高レベルのDSLを備えたHTTPおよびWebSocketサーバーです。 Nettyは、低レベルの「非同期イベント駆動型ネットワークアプリケーションフレームワーク」であり、必要なTCP/UDPプロトコルを実装できます。
したがって、低レベルのネットワークが必要でない限り、プレーンなNettyを使用しないでください。 Nettyを使用するAkkaHTTPに相当するものは、 Netty Reactor のようになり、それらの上位レベルはSpringWebFluxのようになります。
一方、Akka-HTTPは、特定のアプリケーションモデルを提案するフレームワークであるAkkaActorsに基づいています。また、AkkaはScalaに依存しています。これは、Scalaをすでに知っている場合、またはアプリケーションのデバッグ時にScalaを学習する準備ができていない場合、決定に影響を与える可能性があります。