兰州建设局网站,wordpress指定分类文章列表,连锁餐厅vi设计公司,ui培训机构排名Netty Home Netty GitHub
Netty简介
Netty是由JBOSS提供的一个java开源框架#xff0c;现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具#xff0c;用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说#xff0c;Netty 是一个…Netty Home Netty GitHub
Netty简介
Netty是由JBOSS提供的一个java开源框架现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说Netty 是一个基于NIO的客户、服务器端的编程框架使用Netty 可以确保你快速和简单的开发出一个网络应用例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程例如基于TCP和UDP的socket服务开发。 “快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议包括FTP、SMTP、HTTP等各种二进制文本协议的实现经验并经过相当精心设计的项目。最终Netty 成功的找到了一种方式在保证易于开发的同时还保证了其应用的性能稳定性和伸缩性。
本质
网络应用程序框架
实现
异步、事件驱动
特性
高性能、可维护、快速开发
用途
开发服务器和客户端
优势
支持常用的应用层协议解决传输中粘包、半包问题支持流量整性完善的断连、Idle 等异常处理等
三种 I/O 模式
阻塞与非阻塞 阻塞没有数据传过来时读会阻塞直到有数据缓冲区满时写操作也会阻塞。非阻塞遇到这种情况会直接返回。连接数高的情况下阻塞 - 耗资源、效率低。异步与同步 数据就绪后自己去读就是同步数据就绪直接读好再回调给程序是异步。 对于 Nio 与 Bio 来说特定场景下如连接数少并发度低BIO 性能不输 NIO。
通用的 NIO 实现Common在 Linux 下也是使用 epollNetty 重新单独实现暴露了更多的可控参数例如JDK 的 NIO 默认实现是水平触发Netty 是边缘触发默认和水平触发可切换Netty 实现的垃圾回收更少、性能更好 对于 ServerSocketChannel工厂模式 泛型 反射实现
三种 Reactor Reactor 及三种版本
Reactor 是一种开发模式模式的核心流程 注册感兴趣的事件 - 扫描是否有感兴趣的事件发生 - 事件发生后做出相应的处理。
Thread-Per-Connection 模式 Reactor 模式 V1单线程 Reactor 模式 V2多线程
Reactor 模式 V3主从多线程 在 Netty 中使用 Reactor 模式 TCP 粘包/半包
什么是粘包和半包
粘包的主要原因 发送方每次写入数据 套接字缓冲区大小 接收方读取套接字缓冲区数据不够及时半包的主要原因 发送方写入数据 套接字缓冲区大小 发送的数据大于协议的 MTUMaximum Transmission Unit最大传输单元必须拆包根本原因 TCP 是流式协议消息无边界 说明UDP 像邮寄的包裹虽然一次运输多个但每个包裹都有“界限”一个一个签收 所以无粘包、半包问题
解决粘包和半包问题的几种常用方法 Netty 对三种常用封帧方式的支持 常用的“二次”编解码方式
假设我们把解决半包粘包问题的常用三种解码器叫一次解码器那么我们在项目中除了可选的的压缩解压缩之外还需要一层解码因为一次解码的结果是字节需要和项目中所使用的对象做转化方便使用这层解码器可以称为“二次解码器”相应的对应的编码器是为了将 Java 对象转化成字节流方便存储或传输。
一次解码器ByteToMessageDecoder io.netty.buffer.ByteBuf 原始数据流- io.netty.buffer.ByteBuf 用户数据二次解码器MessageToMessageDecoder io.netty.buffer.ByteBuf 用户数据- Java Object
常用的“二次”编解码方式
• Java 序列化 • Marshaling • XML • JSON • MessagePack • Protobuf • 其他
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(PersonOuterClass.Person.getDefaultInstance()));
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());keepalive 与 Idle 监测
keepalive
需要 keepalive 的场景包含三点对端异常“崩溃”、对端在但是处理不过来、对端在但是不可达。 不做 keepalive 的后果连接已坏但是还浪费资源维持下次直接用会直接报错。
TCP keepalive 核心参数
net.ipv4.tcp_keepalive_time 7200 net.ipv4.tcp_keepalive_intvl 75 net.ipv4.tcp_keepalive_probes 9 当启用默认关闭keepalive 时TCP 在连接没有数据通过的7200秒后发送 keepalive 消息当探测没有确认时按75秒的重试频率重发一直发 9 个探测包都没有确认就认定连接失效。 所以总耗时一般为2 小时 11 分钟 (7200 秒 75 秒* 9 次)
应用层 keepalive
协议分层各层关注点不同 传输层关注是否“通”应用层关注是否可服务 服务器连接在但是不定可以服务例如服务不过来等TCP 层的 keepalive 默认关闭且经过路由等中转设备 keepalive 包可能会被丢弃TCP 层的 keepalive 时间太长 默认 2 小时虽然可改但属于系统参数改动影响所有应用
HTTP 属于应用层协议但是常常听到名词“ HTTP Keep-Alive ”指的是对长连接和短连接的选择 Connection : Keep-Alive 长连接HTTP/1.1 默认长连接不需要带这个 header Connection : Close 短连接
Idle 监测
Idle 监测只是负责诊断诊断后做出不同的行为决定 Idle 监测的最终用途 • 发送 keepalive :一般用来配合 keepalive 减少 keepalive 消息。 Keepalive 设计演进V1 定时 keepalive 消息 - V2 空闲监测 判定为 Idle 时才发keepalive。 • V1keepalive 消息与服务器正常消息交换完全不关联定时就发送 • V2有其他数据传输的时候不发送 keepalive 无数据传输超过一定时间判定为 Idle再发 keepalive 。
直接关闭连接 • 快速释放损坏的、恶意的、很久不用的连接让系统时刻保持最好的状态。 • 简单粗暴客户端可能需要重连。 实际应用中结合起来使用。按需 keepalive 保证不会空闲如果空闲关闭连接。
在Netty 中开启 TCP keepalive 和 Idle 检测
开启keepalive
Server 端开启 TCP keepalive
bootstrap.childOption(ChannelOption.SO_KEEPALIVE,true)
bootstrap.childOption(NioChannelOption.of(StandardSocketOptions.SO_KEEPALIVE), true)提示.option(ChannelOption.SO_KEEPALIVE,true) 存在但是无效
开启不同的 Idle Check
ch.pipeline().addLast(“idleCheckHandler, new IdleStateHandler(0, 20, 0, TimeUnit.SECONDS));“锁”事
锁的对象和范围 - 减少粒度
Synchronized method - Synchronized block
锁的对象本身大小 - 减少空间占用
AtomicLong - Volatile long AtomicLongFieldUpdater
锁的速度 - 提高速度
高并发时java.util.concurrent.atomic.AtomicLong - java.util.concurrent.atomic.LongAdder
不同场景选择不同的并发类 - 因需而变
Object.wait/notify - CountDownLatch
衡量好锁的价值 - 能不用则不用
对竞争的态度乐观锁java.util.concurrent 包中的原子类与悲观锁Synchronized) 等待锁的人是否公平而言公平锁 new ReentrantLock (true)与非公平锁 new ReentrantLock () 是否可以共享共享锁与独享锁ReadWriteLock 其读锁是共享锁其写锁是独享锁
内存使用
减少对像本身大小
用基本类型就不要用包装类 应该定义成类变量的不要定义为实例变量
对分配内存进行预估
对于已经可以预知固定 size 的 HashMap避免扩容 根据接受到的数据动态调整guess下个要分配的 Buffer 的大小
Zero-Copy
使用逻辑组合代替实际复制 使用包装代替实际复制 调用 JDK 的 Zero-Copy 接口
堆外内存
内存池
轻量级对象池实现 io.netty.util.Recycler