netty基础概念

一、先理解相关概念

BIO阻塞排队点餐,阻塞等待取餐耗资源,效率低,基本已被废弃
NIO非阻塞先取号,等待被叫,再去取餐
AIO异步包厢,点餐后等待端上来就行

1、windows实现成熟,但windows很少用来作为服务器;

2、linux常用来作为服务器,但AIO实现不够成熟;

3、linux下AIO相比NIO性能提升不够明显;

阻塞1、读取数据没准备好时,等待数据返回(死等);2、写操作时缓冲区数据满了,等待数据被消费(死等);
非阻塞读取数据没准备好或写缓冲满时,都直接返回。
同步数据准备就绪后需要调用方主动来读就是同步;
异步数据准备好在回调给程序就是异步

二、BIO的阻塞问题

随着各类NIO框架的发展,以及基于NIO的Web服务器的发展,Java在很多领域取代了C和C++,成为企业服务端应用开发的首选语言。在JDK 1.4推出Java NIO之前,基于Java的所有Socket通信都采用了同步阻塞模式(BIO),这种一请求一应答的通信模型简化了上层的应用开发,但是在性能和可靠性方面却存在着巨大的瓶颈。当并发访问量增大、响应时间增大之后,采用Java BIO开发的服务端软件只有通过硬件的不断扩容来满足高并发和低时延,它极大地增加了企业的成本,并且随着集群规模的不断膨胀,系统的可维护性也面临巨大的挑战,只能通过采购性能更高的硬件服务器来解决问题,这会导致恶性循环。显然BIO无法满足高性能、高并发接入的场景。

同步阻塞是一请求一连接,socket服务端有个Acceptor来处理所有的请求,然后分发给一个对应的线程去处理,每个客户端请求对应一个线程,当请求并发量高的时候,就会出现阻塞,后面会出现大量的连接请求超时,导致客户端以为服务已经挂掉。后面的伪异步I/O只是在此基础上将线程的创建交给线程池来完成,client建立连接作为线程池的一个任务来执行,虽做了一点优化,仍然还是面对同样的阻塞问题。

三、使用NIO编程的优点有什么?

1)客户端发起的连接操作是异步的,可以通过在多路复用器Selector上注册请求,用一个线程来处理多个channel
2)SocketChannel的读写操作都是异步的,如果没有可读写的数据它不会同步等待,直接返回,这样I/O通信线程就可以处理其他的链路,不需要同步等待这个链路可用。
3)线程模型的优化:一个Selector线程可以同时处理成千上万个客户端连接,而且性能不会随着客户端的增加而线性下降,因此,它非常适合做高性能、高负载的网络服务器。

四、主要的模块

1)Buffer(缓冲区):buffer是一个对象,NIO的API相对以前的inputstream和outputstream来说的,所有的数据都是通过缓冲区来处理的(读写),缓冲区实际上是一个数组,通常他是一个字节数组(ByteBuffer),但是这样的buffer是非常难用的。

ByteBuffer.allocate(8) // 初始化

2)Channel(管道):
3)Selector(多路复用器):
selector用一个线程长轮询多个Channel,根据其状态对缓冲区和通道的数据进行操作

4)CharSet 用于将Unicode编解码为对应的序列化码流

五、应用场景有哪些?

在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它已经完全能够满足不同行业的商业应用了。

数据库:Cassandra

大数据处理:Spark、Hadoop

Message Queue:RocketMQ

检索:Elasticsearch

框架:gRPC、Apache Dubbo、Spring5

分布式协调器:ZooKeeper

工具类:async-http-client

其他参考:Netty.docs: Adopters

六、为什么用Netty?

使用jdk提供的NIO API开发异步通信十分复杂,Netty是一个通信框架,有着简单的API,开发容易上手。

1、Netty做得更多:

• 支持常用应用层协议;

• 解决传输问题:粘包、半包现象;

• 支持流量整形;

• 完善的断连、Idle等异常处理等。

2、Netty做得更好之一:规避JDK NIO bug:

3、Netty做得更好之二:API更友好更强大

JDK的NIO一些API不够友好,功能薄弱,例如ByteBuffer-> Netty’sByteBuf

除了NIO外,也提供了其他一些增强:Theadlocal-> Netty’sFastThreadLocal

七、netty实现通信的步骤

1、创建两个NIO线程组,一个专门用于网络事件处理(接受客户端连接),另一个则进行网络通信处理
2、创建一个ServerBootStrap,配置netty的一些列参数,例如接收传出数据的缓存大小等。
3、创建一个实际处理数据的类ChannelInitializer,进行初始化的准备工作,比如设置传出数据的字符集、格式、已经实际处理数据的接口。
4、绑定端口,执行同步阻塞方法等待服务器端启动即可。
通过这么简单的几个步骤,就可以实现一个健壮、稳定的服务端通信,这在之前的NIO是不可能实现的。

八、Reactor的三种模式

Reactor单线程

单个线程处理所有事情,如饭店迎宾、点菜、做菜、上菜、结账、送客一系列操作

Reactor多线程多线程分别处理以上所有事情
主从Reactor

一个线程专门处理连接建立和关闭,其他线程处理业务bossGroup和workerGroup

九、二次编解码器

一次解码器ByteToMessageDecoder
二次解码器

MessageToMessageDecoder

 

netty内置的三种编解码器依次为FixedLengthFrameDecoder、LengthFieldBasedFrameDecoder 、DelimiterBasedFrameDecoder,由于一次解码的结果是字节,为了方便和项目中所使用的对象做转化,就需要二次解码

常用二次编解码器:

Java序列化、Marshaling、XML、JSON、MessagePack、Protobuf

十、心跳keepalive+idle

前者即心跳消息,后者为时间间隔,好比和别人通电话,对方突然不讲话了,等待几秒后,询问还在吗,或者直接挂断,或者重拨。Idle监测,只是负责诊断,诊断后作出不同的行为。

实际应用中:结合起来使用。按需keepalive,保证不会空闲,如果空闲,关闭连接。

1、Server端开启TCP keepalive

bootstrap.childOption(ChannelOption.SO_KEEPALIVE,true) 
bootstrap.childOption(NioChannelOption.of(StandardSocketOptions.SO_KEEPALIVE), true)

提示:.option(ChannelOption.SO_KEEPALIVE,true) 存在但是无效

2、 开启不同的Idle Check:

ch.pipeline().addLast(“idleCheckHandler", 
new IdleStateHandler(0, 20, 0, TimeUnit.SECONDS));

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值