今天说一下netty ,最近使用公司自主研发的高可用分布式消息中间件时候发现启动日志和依赖的jar包中都有netty ,之前用dubbo的时候了解过dubbo采用NIO进行通讯,于是开始对netty产生兴趣,
netty的简介: Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
Netty的特性
1)设计
统一的API,适用于不同的协议(阻塞和非阻塞)
基于灵活、可扩展的事件驱动模型
高度可定制的线程模型
可靠的无连接数据Socket支持(UDP)
2)性能
更好的吞吐量,低延迟
更省资源
尽量减少不必要的内存拷贝
3)安全
完整的SSL/TLS和STARTTLS的支持
能在Applet与Android的限制环境运行良好
4)健壮性
不再因过快、过慢或超负载连接导致OutOfMemoryError
不再有在高速网络环境下NIO读写频率不一致的问题
netty的应用
典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信,其中,服务提供者和服务消费者之间,服务提供者、服务消费者和性能统计节点之间使用 Netty 进行异步/同步通信。
除了 Dubbo 之外,阿里的消息中间件 RocketMQ 的消息生产者和消息消费者之间,也采用 Netty 进行高性能、异步通信。
除了阿里之外,很多其它的大型互联网公司或者电商内部也已经大量使用 Netty 构建高性能、分布式的网络服务器。
大数据领域:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨节点通信,它的 Netty Service 基于 Netty 框架二次封装实现。
大数据计算往往采用多个计算节点和一个/N个汇总节点进行分布式部署,各节点之间存在海量的数据交换。由于 Netty 的综合性能是目前各个成熟 NIO 框架中最高的,因此,往往会被选中用作大数据各节点间的通信。
企业软件:企业和 IT 集成需要 ESB,Netty 对多协议支持、私有协议定制的简洁性和高性能是 ESB RPC 框架的首选通信组件。事实上,很多企业总线厂商会选择 Netty 作为基础通信组件,用于企业的 IT 集成。
通信行业:Netty 的异步高性能、高可靠性和高成熟度的优点,使它在通信行业得到了大量的应用。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
今天带大家过一下hell world
首先我们看些server端代码:
public class Server {
public static void main(String[] args) throws InterruptedException {
//用于处理服务器端接受客户端的连接
EventLoopGroup eventLoopGroup=new NioEventLoopGroup();
//进行网络通信
EventLoopGroup GventLoopGroup=new NioEventLoopGroup();
//用于服务器通道的一系列配置
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(eventLoopGroup,GventLoopGroup)//绑定两个线程组
.channel(NioServerSocketChannel.class) //指定nio模式
.option(ChannelOption.SO_BACKLOG,1024) //设定tcp的缓冲
.option(ChannelOption.SO_SNDBUF,3*1024) //设定发送缓冲大小
.option(ChannelOption.SO_RCVBUF,3*1024) //设定接受缓冲大小
.option(ChannelOption.SO_KEEPALIVE,true) //保持连接
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//具体接受方法的数据处理方法
socketChannel.pipeline().addLast(new ServerHandler());
}
});
//进行绑定
ChannelFuture cf=serverBootstrap.bind(8765).sync();
//关闭等待
cf.channel().closeFuture().sync();
GventLoopGroup.shutdownGracefully();
eventLoopGroup.shutdownGracefully();
}
}
我们的serverHandler是自己实现的一个类,用来处理接收的数据
public class ServerHandler extends ChannelHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("server channel active... ");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "utf-8");
System.out.println("Server :" + body );
String response = "进行返回给客户端的响应:" + body ;
ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
//.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx)
throws Exception {
System.out.println("通讯完毕");
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable t)
throws Exception {
ctx.close();
}
启动右键启动server
接下来看下我们的客户端代码
public class Client {
public static void main(String[] args) throws InterruptedException {
//实例化一个线程组
EventLoopGroup group=new NioEventLoopGroup();
Bootstrap b=new Bootstrap();
b.group(group)
//绑定一个线程组
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ClientHandler());
}
});
//连接服务端
ChannelFuture cf=b.connect("127.0.0.1",8765).sync();
//发送消息
cf.channel().writeAndFlush(Unpooled.copiedBuffer("hell world".getBytes()));
cf.channel().closeFuture().sync();
group.shutdownGracefully();
}
}
我们的ClientHandler
public class ClientHandler extends ChannelHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "utf-8");
System.out.println("Client :" + body);
String response = "收到服务器端的返回信息:" + body;
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.close();
}
}
这个类也是自己实现,具体是处理服务端的返回
这是控制台:
我的jar依赖:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
这个就是简单的netty的hell world
给你们推荐一个不错的帖子http://ifeve.com/netty5-user-guide/ Netty 5用户指南