缘起
在工作中,有一个feature用到了netty的LocalChannel的功能,之前由于时间太紧没有机会总结下这个LocalChannel,今天有时间就过来写一下。
LocalChannel介绍
LcoalChannel是Netty提供的用来在同一个JVM内部实现client和server之间通信的transport。它的实现主要是通过内存里的对象作为通信介质,不会像NIO下的channel,会占用一个文件描述符;因此使用它不会影响到你系统上的打开文件数,也就不会影响到你系统所能管理的连接数了。对于在同一个JVM内部使用netty的机制进行通信的话,还是很轻量级的。
示例
工作中的使用还是比较负载的,我在这里写了一个简单的例子,下面的讨论都是参照这个例子的。
LocalServer代码示例
LocalClient代码示例
可以看到使用方式跟使用其他的channel没有什么区别,需要注意的就是,LocalChannel也实现了自己的EventLoop,所以在使用的时候还要是配套的使用相对应的LocalEventLoopGroup。
内部实现
LocalServerChannel的bind
首先要看的当然就是server启动之后是怎么监听端口的,从示例代码中可以看出,使用LocalChannel的Server端所bind的地址只是一个字符串,并不是ip+port的形式,这也说明了LocalChannel的东西是不会占用你的端口的。
当你初始化了ServerBootStrap之后就要把它绑定到这个字符串所代表的“端口”上来,那么它是怎么做的呢?我这里抓了一下它的调用栈,我觉得它已经可以说明一切了。
"localEventLoopGroup-2-1@1385" prio=10 tid=0xd nid=NA runnable
java.lang.Thread.State: RUNNABLE
at io.netty.channel.local.LocalChannelRegistry.register(LocalChannelRegistry.java:32)
at io.netty.channel.local.LocalServerChannel.doBind(LocalServerChannel.java:91)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:485)
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1081)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:502)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:487)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:904)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:198)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:348)
at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(