Netty学习笔记(一)

  • 时间:2015-02-14
  • 方式:原创

Netty是什么

Netty是一个由事件驱动驱动的异步网络应用程序框架,使用Netty,你可以简单、快速的开发出网络服务器或是客户端;Netty大大简化了网络编程的复杂度;

使用Netty简单、快速的开发并不会降低程序的性能和可维护性;Netty在设计时从众多的协议中吸收了经验;最终,Netty成功的提供了易于开发的高性能、高稳定性及高扩展性的通信框架;

目前使用Netty的项目包括:

  • Dubbo:阿里的RPC中间件;
  • RocketMQ:阿里的消息队列;
  • Finagle:Twitter的RPC中间件;
  • Norbert:LinkedIN的RPC中间件;

注意:Netty并不是Web容器,并没有提供如session,JSTL等常见功能!!

Netty的特点

components.png

设计:

  • 各种传输类型,阻塞和非阻塞套接字统一的API
  • 使用灵活
  • 简单但功能强大的线程模型
  • 无连接的DatagramSocket支持
  • 链逻辑,易于重用

易用性:

  • 提供大量的文档和例子
  • 除了依赖jdk1.6+,没有额外的依赖关系。某些功能依赖jdk1.7+,其他特性可能有相关依赖,但都是可选的。

性能:

  • 比Java APIS更好的吞吐量和更低的延迟
  • 线程池和重用所有消耗较少的资源
  • 尽量减少不必要的内存拷贝

健壮性:

  • 链接快或慢或超载不会导致更多的OutOfMemoryError
  • 在高速的网络程序中不会有不公平的read/write

安全性:

  • 完整的SSL/TLS和StartTLS支持
  • 可以在如Applet或OSGI这些受限制的环境中运行

社区:

  • 版本发布频繁
  • 社区活跃

Hello World

引用Netty

Netty是一个NIO的开源框架,对于Maven项目;可以直接在Pom文件中引用即可;

<dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.0.23.Final</version>
</dependency>

对于非Maven项目;则需要引用Jar包;你可以在这里找到最新的包:

源码部分:

EchoServer.java

package com.violetgo.example.netty.helloworld;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public final class EchoServer {

    public static void main(String[] args) throws Exception {

        // EventLoopGroup 类似线程组,boss用于监听是否有tcp链接过来;worker用于建立链接并处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //如果不设置参数值,则默认取CPU核心数*2
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .option(ChannelOption.SO_BACKLOG, 100)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();

                     p.addLast(new EchoServerHandler());
                 }
             });

            // Start the server.
            ChannelFuture f = b.bind(8007).sync();

            // Wait until the server socket is closed.
            f.channel().closeFuture().sync();
        } finally {
            // Shut down all event loops to terminate all threads.
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

EchoServerHandler.java

package com.violetgo.example.netty.helloworld;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        //这个方法会在每次client有输入的时候调用
        ByteBuf buffer = ctx.alloc().buffer();
        buffer.writeBytes("hello World".getBytes());
        ctx.write (buffer);    
}

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        //这个方法会在每次client有输入完成的时候调用
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

启动server后运行telnet 127.0.0.1 8007 输入任何字符即可看到hello world;

helloworld.png