一、Netty4教程
Netty4是一款使用Java语言基于NIO框架构建的高性能异步网络通信框架,它提供了一种新的方式在Java平台上开发可扩展的、模块化的、高性能的、可维护的TCP/IP服务器和客户端。Netty4的特点是高性能、高清晰度,易于使用和灵活性。
在Netty4的教程中,我们可以学习如何使用Netty4来编写TCP/IP服务器、客户端和代码示例,如下所示:
public class NettyServer {
public static void main(String[] args) throws Exception {
//1.创建EventLoopGroup对象,是一个线程池,实际数量可以根据业务需求调整
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
//2.创建ServerBootstrap对象,是启动服务的工具类
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workGroup)
//3.设置TCP协议的Channel,NioServerSocketChannel是对java.nio.*包的封装
.channel(NioServerSocketChannel.class)
//4.设置对client连接的数据处理逻辑PipeLine
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyServerHandler());
}
})
//5.设置TCP连接参数,SO_BACKLOG是指处于同一时刻待处理的连接队列的最大长度,超出的新连接会被拒绝,jvm会抛出ConnectionRefusedException
.option(ChannelOption.SO_BACKLOG, 100)
//6.设置缓冲区大小,通常可以不设置,会根据操作系统自适应,如果出现流量控制异常,可以考虑增加缓冲区大小
.option(ChannelOption.SO_SNDBUF, 65535)
.option(ChannelOption.SO_RCVBUF, 65535)
//7.设置心跳检测机制以及关闭保护机制,保证TCP的正常关闭,防止TCP连接个数增长到JVM的最大值时出现宕机和内存耗尽等问题
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true);
// Bind and start to accept incoming connections.
//8.绑定端口
ChannelFuture f = b.bind(PORT).sync();
//9.监听channel关闭事件并执行shutdownGracefully关闭服务器和事件处理组
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
二、Netty4 Client Pool
在我们使用Netty4来编写客户端时,为了保证程序的高效性,需要使用连接池来减少重新建立连接带来的开销,使用连接池来管理大量的连接可以提高程序的并发量和性能。
下面是使用Apache Commons Pool结合Netty4实现连接池的代码示例:
public class NettyClientFactory extends BasePooledObjectFactory<NettyClient> {
private String ip;
private int port;
public NettyClientFactory(String ip, int port) {
this.ip = ip;
this.port = port;
}
@Override
public NettyClient create() throws Exception {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new NioEventLoopGroup());
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
//设置重连机制
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast(new NettyClientHandler());
channel.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));
}
});
ChannelFuture channelFuture = bootstrap.connect(ip, port);
channelFuture.awaitUninterruptibly();
if (channelFuture != null && channelFuture.isSuccess()) {
return new NettyClient(channelFuture.channel());
}
return null;
}
@Override
public PooledObject<NettyClient> wrap(NettyClient nettyClient) {
return new DefaultPooledObject<>(nettyClient);
}
}
三、Netty4源码
深入探究Netty4源码可以大幅度提高我们对Netty4的理解和认识,方便我们更好的使用和维护Netty4。
Netty4的主要源码结构如下:
+- common -- 通用的代码 +- buffer -- 字节缓存相关的代码,包括ByteBuf的实现、池化等 +- codec -- 编码和解码相关的代码 +- channel -- 整体框架代码,包括Channel和EventLoop的实现 +- handler -- 处理器相关的代码 +- transport -- 传输相关的代码,包括网络传输和本地传输 +- resolver -- 解析器相关的代码 +- resolver-dns -- DNS解析器相关的代码
其中,参考使用ChannelInboundHandlerAdapter实现简单的数据读取处理,如下代码所示:
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
private static final Logger log = LoggerFactory.getLogger(NettyServerHandler.class);
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
String request = new String(data, "UTF-8");
log.info("Server received message: {}", request);
ByteBuf resp = Unpooled.copiedBuffer("Hello, I'm server!", CharsetUtil.UTF_8);
ctx.write(resp);
ctx.flush();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.error("Exception caught: {}", cause.getMessage());
ctx.close();
}
}
四、Netty4 TCP开发
使用Netty的TCP开发,可以让我们非常轻松、高效、安全地实现TCP协议方面的开发工作。
下面是一个基于Netty4实现的TCP客户端代码示例:
public class NettyTcpClient {
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup(1);
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyClientHandler());
}
});
ChannelFuture f = b.connect(HOST, PORT).sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
五、Netty4核心原理
从底层分析Netty4的核心原理可以更好地帮助我们理解和使用Netty4。
Netty4的核心原理是基于NIO的异步网络通信,NIO通过Selector机制在一组Channel中逐个轮询事件,只有一个线程能够轮询并处理多个Channel,因此Netty4是通过NioEventLoop来负责I/O处理事件。
下面是NioEventLoop的源码片段:
public void run() {
while (!Thread.interrupted()) {
try {
// 通过selector来取到Channel
int numReady = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());
// ...
// 通过selector方式来获取I/O事件
processSelectedKeys();
// 处理Channel上的所有I/O任务和定时任务
runAllTasks();
// ...
} catch (Throwable t) {
// ...
}
}
// ...
}
六、Netty4和5有什么区别
Netty5相比于Netty4在某些方面进行了较大的改变,比如在编解码器方面进行不同程度的优化、异步API使用更加灵活等。
下面是Netty4和Netty5对比的一些区别:
1、Netty4采用EventLoop和EventExecutor分离的设计思路,而Netty5采用异步的ActiveObject计算模型; 2、Netty5新增了一些基于HTTP/2协议的组件; 3、Netty5提供了更加灵活的异步API机制,可以更精细地控制异步事件的执行逻辑; 4、Netty5的通信协议栈进行了重新设计,比如在编解码器方面进行了不同程度的优化; 5、Netty5底层的异步事件处理引擎也进行了改进,更加适配不同场景的使用;
结语
Netty4是一个功能强大、易于使用、高性能的异步网络编程框架,它提供了丰富的网络协议支持和超高的吞吐量,是目前业界最为流行的异步网络编程框架之一。通过对Netty4的全方位解析,更加深入地理解Netty4的使用、原理和优势。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/241632.html
微信扫一扫
支付宝扫一扫