一、初识Netty
- Netty 是一一个提供了易于使用的API的客户端/服务器框架
- 并发高- NIO (非阻塞IO )
- 传输快-零拷贝
二、阻塞与非阻塞
- 线程访问资源,该资源是否准备就绪的一种处理方式
阻塞:线程访问资源时,如遇到资源正在处理,则等待该资源处理完毕
非阻塞:线程访问资源时,如遇到资源正在处理,则等待访问其它资源,以此类推
三、同步与异步
- 同步和异步是指访问数据的一种机制
同步:线程在访问数据的时候,等待数据处理完毕返回结果
异步:线程在访问数据时,不会等待数据处理结果,直接处理下一个数据,数据处理完成后异步通知
四、BIO、NIO、AIO
- BIO:同步阻塞IO,Block IO
- NIO:同步非阻塞IO,New IO ( Non-Block IO )
- AIO:异步非阻塞IO
生活实例
- BIO:去上厕所,坑全满,此时我一直光等着,主动观察哪个坑位好了,只要有坑位释放了,我就立马去占坑
- NIO :厕所坑全满,此时我跑出去抽烟或者做别的事, 然后时不时再主动的去厕所有没有坑释放,如果有坑了自己去占坑
- 异步阻塞:我在厕所里,等有人好了之后来通知后,然后再去占坑
- AIO :我在厕所外抽眼玩手机,等有人好了之后来通知我去占坑
五、Reactor线程模型
- 单线程模型 :所有的IO操作都由同一-个NIO线程处理的
- 多线程模型:由一组NIO线程处理IO操作
- 主从线程模型:一组线程池接受请求, -组线程池处理io
六、根据主从线程模型编写Netty的一个小Demo
需求:实现客户端发送一个请求,服务器返回hello netty
步骤:
- 首先编写启动类
public class HelloServer {
public static void main(String[] args) throws InterruptedException {
//定义一对线程组
//主线程组,用于接受客户端的连接,但是不做任何处理,跟老板一样,不做事
EventLoopGroup bossGroup = new NioEventLoopGroup();
//从线程组,老板线程组会把任务丢给他,让手下线程组去做任务
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//netty服务器的创建,ServerBootstrap是一个启动类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)//设置主从线程组
.channel(NioServerSocketChannel.class)//设置nio双向通道
.childHandler(new HelloServerInitializer());//子处理器,用于处理workerGroup
//启动server,并且设置8088为启动的端口号,同时启动的方式为同步
ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
//监听关闭的channel,设置为同步方式
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
- 编写初始化器,channel注册后,会执行里面的相应的初始化方法
public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
//通过SocketChannel获取相应的管道
ChannelPipeline pipeline = channel.pipeline();
//通过管道,添加handler
//HttpServerCodec是由netty自己提供的一个助手类,可以理解为拦截器
//当请求到服务端时,我们需要做编码,响应到客户端做编码
pipeline.addLast("HttpServerCodec",new HttpServerCodec());
//添加自定义的助手类,返回"hello netty"
pipeline.addLast("customHandler",new CustomHandler());
}
}
- 编写自定义助手类,请求进来后,会执行我们自定义的操作,这里是返回一个"Hello Netty"
public class CustomHandler extends SimpleChannelInboundHandler<HttpObject> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
//获取channel
Channel channel = channelHandlerContext.channel();
if(httpObject instanceof HttpRequest){
//显示客户端的远程地址
System.out.println(channel.remoteAddress());
//定义发送的数据消息
ByteBuf content = Unpooled.copiedBuffer("Hello Netty", CharsetUtil.UTF_8);
//构建一个http response
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());
//把响应刷到客户端
channelHandlerContext.writeAndFlush(response);
}
}
}
- 运行代码后,在浏览器输入http://localhost:8088/即可看到打印出来的"Hello Netty"
Demo源码地址:https://github.com/xiaohuoban00/HelloNetty