Play框架的Netty Http服务器实现
Play使用Bootstrap初始化服务器Channel,设置Channel类,EventLoop和Handler等。 (Play没有使用专为服务器准备的ServerBoostrap,而是使用更加通用的Bootstrap。这样就可以自己安排对客户端Channel的设置)
private def bind(address: InetSocketAddress): (Channel, Source[Channel, _]) = {
val serverChannelEventLoop = eventLoop.next
// Watches for channel events, and pushes them through a reactive streams publisher.
val channelPublisher = new HandlerPublisher(serverChannelEventLoop, classOf[Channel])
val channelClass = transport match {
case Native => classOf[EpollServerSocketChannel]
case Jdk => classOf[NioServerSocketChannel]
}
//使用Bootstrap创建服务器Channel
val bootstrap = new Bootstrap()
.channel(channelClass)
.group(serverChannelEventLoop)
.option(ChannelOption.AUTO_READ, java.lang.Boolean.FALSE) // publisher does ctx.read()
.handler(channelPublisher)
.localAddress(address)
setOptions(bootstrap.option, nettyConfig.getConfig("option"))
val channel = bootstrap.bind.await().channel()
//将服务器Channel收集到allChannels中
allChannels.add(channel)
//返回服务器Channel, 和Akka Stream Source
(channel, Source.fromPublisher(channelPublisher))
}
当有新的客户端连接服务器时,服务器Channel上的Handler HandlerPublisher会读取到新连接的客户端Channel,然后将客服端Channel发布到到Akka Stream。在Akka Stream Sink中进行客户端Pipeline的设置和Event loop的绑定,并将所有的客户端Channel收集到NettyServer.allChannels属性中。