Akka HTTP Server 是具有高级 DSL 的 HTTP 和 WebSocket 服务器。Netty 是一个低级的“异步事件驱动的网络应用程序框架”,允许实现您需要的任何 TCP/UDP 协议。
所以,除非你需要一些底层网络,否则你不应该使用普通的 Netty。使用 Netty 的 Akka HTTP 的等价物将类似于Netty Reactor,而在它们之上的更高级别可能是诸如 Spring WebFlux 之类的东西。
另一方面,Akka-HTTP 基于 Akka Actors,这是一个建议特定应用程序模型的框架。此外,Akka 依赖于 Scala,如果您已经了解 Scala,或者您在调试应用程序时尚未准备好学习 Scala,这可能会影响您的决定。
我认为这是主要的可对比领域:
编码风格
让我们以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)
}
Run Code Online (Sandbox Code Playgroud)
对于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();
}
}
Run Code Online (Sandbox Code Playgroud)
指令
我认为,akka-http的最大优势之一就是Directives,它为复杂的请求处理逻辑提供了DSL。例如,假设我们想用一条消息来响应GET和PUT请求,而用另一条消息来响应所有其他请求方法。使用指令非常简单:
val route =
(get | put) {
complete("You sent a GET or PUT")
} ~
complete("Shame shame")
Run Code Online (Sandbox Code Playgroud)
如果要从请求路径获取订单商品和数量:
val route =
path("order" / Segment / IntNumber) { (item, qty) =>
complete(s"Your order: item: $item quantity: $qty")
}
Run Code Online (Sandbox Code Playgroud)
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)
}
}
Run Code Online (Sandbox Code Playgroud)
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)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3449 次 |
| 最近记录: |