web-dev-qa-db-ja.com

AkkaHTTPとNettyの違い

Akka HTTPNetty の主な違いを誰かに説明してもらえますか? Nettyは、FTPなどの他のプロトコルも提供しています。 AkkaHTTPはScalaおよびJavaであり、 アクターモデル上に構築 )で使用できます。ただし、これを除けば、両方とも非同期です。いつAkkaHTTPを使用し、いつNettyを使用しますか?両方の一般的な使用例は何ですか?

14
Kris

これが私が主な対照的な領域として見ているものです:

コーディングスタイル

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を学習する準備ができていない場合、決定に影響を与える可能性があります。