1.Netty模型:①Netty抽象出两组线程池,BossGroup专门负责接收客户端连接,WorkerGroup专门负责网络读写操作②NioEventLoop表示一个不断循环执行处理任务的线程,每个NioEventLoop都有一个selector,用于监听绑定在其上的socket网络通道③NioEventLoop内部采用串行化设计,从消息的读取-》解码-》处理-》编码-》发送,始终由IO线程NioEventLoop负责④NioEventLoopGroup下包含多个NioEventLoop,每个NioEventLoop中包含有一个selector,一个taskQueue,每个NioEventLoop的selector上可以注册监听多个NioChannel,每个NioChannel只会绑定在唯一的NioEventLoop上,每个NioChannel都绑定有一个自己的ChannelPipeline.
2.异步的概念和同步相对,当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、通知和回调来通知调用者。Netty中的I/O操作是异步的,包括Bind,Write,Connect等操作会简单的返回一个ChannelFuture。调用者并不能立刻获得结果,而是通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。Netty的异步模型是建立在future和callback的之上的,callback就是回调,重点说Future,它的核心思想是:假设一个方法fun,计算过程可能非常耗时,等待fun返回显然不合适,那么可以在调用fun的时候,立马返回一个future,后续可以通过future去监控方法fun的处理过程。
3.Future-Listener机制:①当future对象刚刚创建时,处于非完成状态,调用者可以通过返回的channelFuture来获取操作执行的状态,注册监听函数来执行完成后的操作。②常见有如下操作:
通过isDone方法来判断当前操作是否完成
通过isSuccess方法来判断已完成的当前操作是否成功
通过getCause方法来获取已完成的当前操作失败的原因
通过isCancelled方法来判断已完成的当前操作是否被取消
通过addListener方法来注册监听器,当操作已完成将会返回指定的监听器,如果future对象已完成,则通知指定的监听器
4.快速入门实例-HTTP服务:Netty服务器在6668端口监听,浏览器发出请求http://localhost:6668,服务器可以回复消息给客户端“hello,我是服务器”,并对特定请求资源进行过滤。
TestServer.java:
public class TestServer {
public static void main(String[] args) throws Exception{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new TestServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(6668).sync();
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
TestServerInitializer.java
public class TestServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//向管道加入处理器
//得到管道
ChannelPipeline pipeline = socketChannel.pipeline();
// 加入Netty提供的httpServerCodec编解码器
pipeline.addLast("MyHttpServerCode",new HttpServerCodec());
pipeline.addLast("MyTestHttpServerHandler",new TestServerHandler());
}
}
TestServerHandler.java:
// httpObject客户端和服务器端相互通讯的数据被封装成httpObject
public class TestServerHandler extends SimpleChannelInboundHandler<HttpObject> {
// 读取客户端数据
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if(msg instanceof HttpRequest){
System.out.println("msg 类型:"+msg.getClass());
System.out.println("客户端地址"+ctx.channel().remoteAddress());
HttpRequest httpRequest = (HttpRequest) msg;
URI uri = new URI(httpRequest.getUri());
// 通过uri过滤特定资源
if("/favicon.ico".equals(uri.getPath())){
System.out.println("请求了 favicom.ico,不做响应");
return;
}
// 回复信息给浏览器(http协议)
ByteBuf content = Unpooled.copiedBuffer("hello ,我是服务器", CharsetUtil.UTF_8);
// 构建一个http的响应,httpresponse
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
ctx.writeAndFlush(response);
}
}
}