Netty实战(一)

科技资讯 投稿 4700 0 评论

Netty实战(一)

目录
    第一章 Java网络编程
    • 1.1 Java NIO
    • 1.2 选择器
  • 第二章 Netty是什么
      2.1 Netty简介
  • 2.2 Netty的特性
      2.2.1 设计
    • 2.2.2 易于使用
    • 2.2.3 性能
    • 2.2.4 健壮性
    • 2.2.5 安全性
    • 2.2.6 社区驱动
  • 2.3 Netty的使用者
  • 2.4 异步和事件驱动
      2.4.1 异步
  • 2.4.2 异步和伸缩性
  • 第三章 Netty核心组件
      3.1 Channel
  • 3.2 回调
  • 3.3 Future
      3.3.1 如何使用ChannelFutureListener
  • 3.4 事件和ChannelHandler
  • 3.5 Future、回调和 ChannelHandler
  • 3.6 选择器、事件和 EventLoop
  • 第一章 Java网络编程

            //创建一个新的 ServerSocket,用以监听指定端口上的连接请求
            ServerSocket serverSocket = new ServerSocket(portNumber);
            //对 accept()方法的调用将被阻塞,直到一个连接建立.随后返回一个新的 Socket 用于客户端和服务器之间的通信。该 ServerSocket 将继续监听传入的连接。
            Socket clientSocket = serverSocket.accept();
            //这些流对象都派生于该套接字的流对象
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//从一个字符输入流中读取文本
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);//打印对象的格式化的表示到文本输出流
            String request, response;
            //处理循环开始
            while ((request = in.readLine()) != null) { //readLine()方法将会阻塞,直到一个由换行符或者回车符结尾的字符串被读取。
                if ("Done".equals(request)) { //如果客户端发送了“Done”,则退出处理循环
                    break;
                }
                //请求被传递给服务器的处理方法
                response = processRequest(request);//客户端的请求已经被处理
                out.println(response);//服务器的响应被发送给了客户端
                //继续执行处理循环
            }
    

    这样有几个不足之处:

    3、即使用户有足够的资源来支撑这种方案,但当连接数达到10000以上的时候上下文的切换还是非常麻烦的。

    1.1 Java NIO

      可以使用 setsockopt()方法配置套接字,以便读/写调用在没有数据的时候立即返回

    Java 对于非阻塞 I/O 的支持是在 2002 年引入的,位于 JDK 1.4 的 java.nio 包中。NIO 最开始是新的输入/输出(New Input/Output)的英文缩写,但是,该Java API 已经出现足够长的时间了,不再是“新的”了,因此,如今大多数的用户认为NIO 代表非阻塞 I/O(Non-blocking I/O),而阻塞I/O(blocking I/O)是旧的输入/输出(old input/output,OIO)。你也可能遇到它被称为普通I/O(plain I/O)的时候。

    1.2 选择器

    这种设计带来更好的资源管理:

      使用较少的线程便可以处理许多连接,因此也减少了内存管理和上下文切换所带来开销。
    • 当没有 I/O 操作需要处理的时候,线程也可以被用于其他任务。

    不容易。特别是,在高负载下可靠和高效地处理和调度 I/O 操作是一项繁琐而且容易出错的任务,这些Netty可以更好的帮我们来处理。

    第二章 Netty是什么

    2.1 Netty简介

    java开源框架,它提供异步的、事件驱动的网络应用程序框架和工具。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。

    2.2 Netty的特性

    2.2.1 设计

      统一的 API,支持多种传输类型,阻塞的和非阻塞的。
    • 简单而强大的线程模型。
    • 真正的无连接数据报套接字支持。
    • 链接逻辑组件以支持复用。

    2.2.2 易于使用

      详实的Javadoc和大量的示例集。
    • 不需要超过JDK 1.6+的依赖。(一些可选的特性可能需要Java 1.7+和/或额外的依赖)。

    2.2.3 性能

      拥有比 Java 的核心 API 更高的吞吐量以及更低的延迟。
    • 得益于池化和复用,拥有更低的资源消耗。
    • 最少的内存复制。

    2.2.4 健壮性

      不会因为慢速、快速或者超载的连接而导致 OutOfMemoryError。
    • 消除在高速网络中 NIO 应用程序常见的不公平读/写比率。

    2.2.5 安全性

      完整的 SSL/TLS 以及 StartTLS 支持。
    • 可用于受限环境下,如 Applet 和 OSGI。

    2.2.6 社区驱动

      发布快速而且频繁。

    2.3 Netty的使用者

    每当你使用Twitter,你便是在使用Finagle,它们基于Netty的系统间通信框架。Facebook在Nifty中使用了Netty,它们的Apache Thrift服务。可伸缩性和性能对这两家公司来说至关重要,他们也经常为Netty贡献代码 。反过来,Netty 也已从这些项目中受益,通过实现 FTP、SMTP、HTTP 和 WebSocket 以及其他的基于二进制和基于文本的协议,Netty 扩展了它的应用范围及灵活性。

    2.4 异步和事件驱动

    2.4.1 异步

    它可以以任意的顺序响应在任意的时间点产生的事件。

    2.4.2 异步和伸缩性

    异步和可伸缩性之间的联系又是什么呢?

    • 选择器使得我们能够通过较少的线程便可监视许多连接上的事件。

    第三章 Netty核心组件

    3.1 Channel

    Channel 是 Java NIO 的一个基本构造。它代表一个到实体(如一个硬件设备、一个文件、一个网络套接字或者一个能够执行一个或者多个不同的I/O操作的程序组件)的开放连接,如读操作和写操作。目前,可以把 Channel 看作是传入(入站)或者传出(出站)数据的载体。因此,它可以被打开或者被关闭,连接或者断开连接。

    3.2 回调

    就是一个方法,一个指向已经被提供给另外一个方法的方法的引用。这使得后者可以在适当的时候调用前者。回调在广泛的编程场景中都有应用,而且也是在操作完成后通知相关方最常见的方式之一。

    public class ConnectHandler extends ChannelInboundHandlerAdapter {
    
        //当一个新的连接已经被建立时,channelActive(ChannelHandler Context)将会被调用
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("Client " + ctx.channel().remoteAddress() + " connected");
        }
    }
    

    当一个新的连接已经被建立时,ChannelHandler 的 channelActive()回调方法将会被调用,并将打印出一条信息。

    3.3 Future

    异步操作的结果的占位符;它将在未来的某个时刻完成,并提供对其结果的访问。

    ChannelFuture提供了几种额外的方法,这些方法使得我们能够注册一个或者多个ChannelFutureListener实例。

    每个 Netty 的出站 I/O 操作都将返回一个 ChannelFuture,它们都不会阻塞。

    Channel channel = ...;
    //异步地连接到远程节点
    ChannelFuture future = channel.connect(
    new InetSocketAddress("192.168.0.1", 25));
    

    像这样connect()方法将会直接返回,而不会阻塞,该调用将会在后台完成。这究竟什么时候会发生
    则取决于若干的因素,但这个关注点已经从代码中抽象出来了。因为线程不用阻塞以等待对应的操作完成,所以它可以同时做其他的工作,从而更加有效地利用资源。

    ps:如果在 ChannelFutureListener 添加到 ChannelFuture 的时候,ChannelFuture 已经完成,那么该 ChannelFutureListener 将会被直接地通知。

    3.3.1 如何使用ChannelFutureListener

    Channel channel = ...;
    //异步连接到远程节点
    ChannelFuture future = channel.connect(new InetSocketAddress("192.168.0.1", 25));
    //注册一个 ChannelFutureListener,以便在操作完成时获得通知
    future.addListener(new ChannelFutureListener() {
    //检查操作的状态
    @Override
    public void operationComplete(ChannelFuture future) {
    //如果操作是成功的,则创建一个 ByteBuf 以持有数据
    if (future.isSuccess()){
    ByteBuf buffer = Unpooled.copiedBuffer("Hello",Charset.defaultCharset());
    //将数据异步地发送到远程节点。返回一个 ChannelFuture
    ChannelFuture wf = future.channel().writeAndFlush(buffer);
    ....
    } else {
    //如果发生错误,则访问描述原因的 Throwable。接下来的处理可以根据具体业务来处理
    Throwable cause = future.cause();
    cause.printStackTrace();
    }
    }
    });
    

    我们可以把ChannelFutureListener 看作是回调的一个更加精细的版本。

    3.4 事件和ChannelHandler

      记录日志;
    • 数据转换;
    • 流控制;
    • 应用程序逻辑。

    Netty 是一个网络编程框架,所以事件是按照它们与入站或出站数据流的相关性进行分类的。

    入站数据或者相关的状态更改而触发的事件包括:

      连接已被激活或者连接失活。
    • 数据读取。
    • 用户事件。
    • 错误事件。

    出站事件是未来将会触发的某个动作的操作结果,这些动作包括:

      打开或者关闭到远程节点的连接。
    • 将数据写到或者冲刷到套接字。

    目前暂时可以认为每个 ChannelHandler 的实例都类似于一种为了响应特定事件而被执行的回调。

    3.5 Future、回调和 ChannelHandler

    Netty的异步编程模型是建立在Future和回调的概念之上的,而将事件派发到ChannelHandler的方法则发生在更深的层次上。结合在一起,这些元素就提供了一个处理环境,使你的应用程序逻辑可以独立于任何网络操作相关的顾虑而独立地演变。这也是 Netty 的设计方式的一个关键目标。拦截操作以及高速地转换入站数据和出站数据,都只需要你提供回调或者利用操作所返回的Future。这使得链接操作变得既简单又高效,并且促进了可重用的通用代码的编写。

    3.6 选择器、事件和 EventLoop

      注册感兴趣的事件。
    • 将事件派发给 ChannelHandler。
    • 安排进一步的动作。

    EventLoop 本身只由一个线程驱动,其处理了一个 Channel 的所有 I/O 事件,并且在该EventLoop 的整个生命周期内都不会改变。这个简单而强大的设计消除了你可能有的在ChannelHandler 实现中需要进行同步的任何顾虑,因此,你可以专注于提供正确的逻辑,用来在有感兴趣的数据要处理的时候执行。如同我们在详细探讨 Netty 的线程模型时将会看到的,该 API 是简单而紧凑的。

    编程笔记 » Netty实战(一)

    赞同 (29) or 分享 (0)
    游客 发表我的评论   换个身份
    取消评论

    表情
    (0)个小伙伴在吐槽