1.前言

上一章结合Java的NIO例子,讲解了多路IO复用的一个基本使用方法,通过实际编码加深对其理解。本章开始进入Netty的环节,前面两章都是为了Netty进行铺垫说明。此节将对比Java的NIO例子,说明Netty的一个基本设计,如果前面理解透彻,对Netty的学习将非常有帮助。

国际惯例,将Netty官网的基本描述放上:Netty是一个为了快速开发可维护的高性能协议服务器和客户端的异步事件驱动的网络应用程序框架。快速简单并不意味着应用会受到可维护和性能问题。其设计非常谨慎,使用了多种协议,如FTP、SMTP、HTTP和各种二进制和基于文本的遗留协议。Netty成功的找到了一种方法,可以在不妥协的情况下实现开发、性能、稳定、灵活。

以上的描述主要关注的就两点:1.异步事件驱动;2.多种协议解析。另外,Netty有较高的吞吐量,低延迟,更少的资源浪费,最小不必要的内存拷贝。

2.例子

2.1 服务端

Java的NIO中我提到服务端基础的4个内容:1.线程池;2.端口;3.Selector;4.Channel。Netty实际上也就是这些内容,但是Netty作为一个封装好了的框架,其不会让我们自己获取Selector,毕竟不是所有的IO都是这种方式,连接过程进行的封装(连接、读取、写入、断开连接),另一个就是在之前没有讲到的协议解析。我们都知道TCP实际上是有粘包的问题,一般需要一个协议避免这个问题,前面也说到了Netty支持很多协议,demo会体现这一点。

    public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("===>receive msg:" + msg);
ctx.channel().writeAndFlush("server get msg:" + msg +"\r\n");
}
});
}
});
ChannelFuture future = bootstrap.bind(7777).sync();
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

EventLoopGroup就是Netty根据JDK提供的线程池框架进行二次封装的一个线程池类。ServerBootstrap是启动类,首先要对其进行一系列设置:1.设置线程池;2.设置IO方式(由channel确定);3.设置handler(handler就是Netty的一个非常重要的封装了,实际上我们对于IO关心的就只有连接的生命周期而已,handler就是对于连接的各个生命周期提供了一个处理相应业务的入口);4.绑定端口。这个和Java的例子前面部分是不是很像,只是对于事件的处理不需要开发者关注了,取而代之的是开发者只需要关注handler对连接各个阶段的处理即可,根据channel类型的不同,Netty对于IO事件的处理全部转换成了Handler。

这里我们主要关注的就是handler了,这对于之前是一个新概念。上面例子就设计了一个最简单的handler了,handler采取的是职责链设计模式,并且其是有先后顺序的,这个不能乱。想一下,读取数据,读出来的都是二进制,第一步当然就是对二进制进行解析,解析出一个完整的协议,多的部分不要,少了继续等待数据到来。DelimiterBasedFrameDecoder就是进行了这个操作,其以换行符作为约定的协议。获取协议之后第二步自然是解析协议了,StringDecoder就是这个用处,即我们希望客户端发送的是带换行符的字符串。那么StringEncoder是干啥用的?这个不是对协议进行编码吗?实际上hander管理了读取的处理,也管理写的操作,我们也需要一个协议返回给客户端。所以handler分为两类,in和out,in会处理read事件,out会处理write事件。最后一个handler就是自定义的一个in类型的handler了,解析完协议后我们要做什么操作,就在这里完成了,这个就是我们的业务层。

2.2 客户端

客户端之前没有使用线程池,但是Netty依旧使用了线程池,因为又不是只有socket需要线程处理,耗时不需要同步执行的业务操作也可以使用多线程技术。其它的地方区别就不是很大了,具体看代码。

    public static void main(String[] args) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group);
b.channel(NioSocketChannel.class);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
}
});
}
}); Channel ch = b.connect("127.0.0.1", 7777).sync().channel();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while(true) {
line = in.readLine();
if("close".equals(line)) {
break;
}
ch.writeAndFlush(line + '\n');
}
ch.close().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}

上面代码有个特殊的地方在于其只需要一个线程池,服务端设置的bossGroup看上章的内容应该也容易理解,服务端的主线程实际上是被select阻塞了的,所以服务端Netty对于主线程也交由线程池处理了,客户端不存在这个问题。

3.Netty核心概念

上面是一个非常基础的demo,但是麻雀虽小五脏俱全(也许不算全),其给出了Netty中几个重要的概念。

Bootstrap或者是ServerBootstrap:Netty的启动类,基本的参数,选择都要在这里设置完成。

EventLoopGroup或者是EventLoop:Netty封装的线程池,需要针对channel选择合适的线程池

  Channel:Netty对于不同的IO处理是由Channel决定的,Channel中有其它核心的概念,这里不进行介绍

  Handler:处理IO各个生命周期节点的对应类,handler也产生了一系列概念,这个之后介绍。

  Future或者是Promise:这个是异步的核心,主要获取异步操作的结果,很重要。

这5个是由demo得出来的核心内容,实际上Netty很复杂,由这些核心会引出其它的核心内容。这里不进行介绍,相关章节会进行说明。

4.后记

本节主要是贯穿前面的章节,以Netty和Java的例子,对Netty进行一个入门的了解,有了Java例子的基础,就不会对Netty的简单配置最终为什么能达到所要的效果一无所知。仔细思考就能大致明白Netty的Nio是如何处理的了。后续章节将以Netty核心概念为主题,介绍Netty整体的一个结构。

漫谈NIO(3)之Netty实现的更多相关文章

  1. NIO高性能框架-Netty

    一:Netty是什么 ? Netty是目前最流行的由JBOSS提供的一个Java开源框架NIO框架,Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客 ...

  2. 漫谈Java IO之 Netty与NIO服务器

    前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...

  3. 漫谈NIO(2)之Java的NIO

    1.前言 上章提到过Java的NIO采取的是多路IO复用模式,其衍生出来的模型就是Reactor模型.多路IO复用有两种方式,一种是select/poll,另一种是epoll.在windows系统上使 ...

  4. 漫谈NIO(1)之计算机IO实现

    1.前言 此系列将尽可能详细介绍断更博客半年以来个人的一个成长,主要是对Netty的源码的一个解读记录,将从整个计算机宏观IO体系上,到Java的原生NIO例子最后到Netty的源码解读.不求完全掌握 ...

  5. BIO,NIO,AIO到NETTY

    NIO 近期接触了几个产品都触及NIO,要么应用,要么改造项目,听多了也有些了解,但仍然不能真正理解,工期比较赶,还是要潜心下来看看. NIO是什么呢,应该是NOT-BLOCKING IO的意思,不阻 ...

  6. 从 BIO、NIO 聊到 Netty,最后还要实现个 RPC 框架!

    大家好,我是 「后端技术进阶」 作者,一个热爱技术的少年. 觉得不错的话,欢迎 star!ღ( ´・ᴗ・` )比心 Netty 从入门到实战系列文章地址:https://github.com/Snai ...

  7. android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup

    android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup 复制netty包 ...

  8. Java异步NIO框架Netty实现高性能高并发

    原文地址:http://blog.csdn.net/opengl_es/article/details/40979371?utm_source=tuicool&utm_medium=refer ...

  9. 【netty】(1)---BIO NIO AIO演变

    BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用的技术. Net ...

随机推荐

  1. python文件对比

    #-*- encoding:utf-8 -*- class loadDatas(object): def __init__(self): self.path='./data' def load_com ...

  2. (线段树 && 字符串的处理)codeforces -- 570C

    链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87813#problem/J Description Daniel has a s ...

  3. (匹配 匈牙利)棋盘游戏 -- Hdu --1281

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1281 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  4. Java中JNI的使用详解第三篇:JNIEnv类型中方法的使用

    转自: http://blog.csdn.net/jiangwei0910410003/article/details/17466369 上一篇说道JNIEnv中的方法的用法,这一篇我们就来通过例子来 ...

  5. C++中的乱七八糟问题

    1   在编写的c++程序中,如果是窗口,有时会一闪就消失了,如果不想让其消失,在程序结尾处添加: #include“iostream.h” system("pause"); 分析 ...

  6. OpenGL常用的函数

    OpenGL常用的函数 1. void glBegin(GLenummode) void glEnd(void) 参数说明: mode:创建图元的类型.可以是以下数值 GL_POINTS:把每一个顶点 ...

  7. C - 无间道之并查集 HihoCoder - 1066

    输入 每个测试点(输入文件)有且仅有一组测试数据. 每组测试数据的第1行为一个整数N,表示黑叔叔总共进行的操作次数. 每组测试数据的第2~N+1行,每行分别描述黑叔叔的一次操作,其中第i+1行为一个整 ...

  8. spring mvc 注解@Controller @RequestMapping @Resource的详细例子

    现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了.不过 ...

  9. SQL SERVER 2014--内存表实现秒杀场景

    ===================================== 网上针对“秒杀”的解决方案很多,数据拆分化解热点,READPAST解决锁问题,应用程序排队限制并发等等很多方式,各有优缺点, ...

  10. Openwrt 远程调试

    此文已由作者吴志勐授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 本文以自己的程序WFD为例: 1,为路由器固件刷上gdbserver 在宿主端,使用make menucon ...