《 Netty权威指南(第2版)》 学习感悟

                                        《 Netty权威指南(第2版)》 学习感悟

1:Netty是什么?

        Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序dsf。

        也就是说,Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
       “快速”和“简单”并不意味着会让你的最终应用产生维护性或性能上的问题。Netty 是一个吸收了多种协议的实现经验,这些协议包括FTP,SMTP,HTTP,各种二进制,文本协议,并经过相当精心设计的项目,最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。
        Netty具有如下优势:
  •        处理大容量数据流更简单
  •        处理协议编码和单元测试更简单
  •        I/O超时和idle状态检测
  •        应用程序的关闭更简单,更安全
  •        更可靠的OutOfMemoryError预防

         传输方式为:

  •           基于BIO和NIO的UDP传输
  •           本地传输(又名 in-VM传输)
  •           HTTP通道,可绕过防火墙

          

2:Netty可以做什么?

              netty是一套在java NIO的基础上封装的便于用户开发网络应用程序的api. 应用场景很多,诸如阿里的消息队列(RocketMQ),分布式rpc(Dubbo)通信层都使用到了netty(dubbo可以用服务发现自由选择通信层). 主要优点个人总结如下:


        1. netty是非阻塞事件驱动框架, 并结合线程组(group)的概念,可以很好的支持高并发,慢连接的场景。

         2. 编程接口非常容易,并且也较好的解决了TCP粘包/拆包的问题.netty提供了自己的ByteBuf和channel,相比于jdk的ByteBuffer和channel来说更简便灵活操作, 并提供了pipeline的概念,并针对每个contextHandler都可以由用户定义, 方便直接. 

        3. 有一些web框架已经开始直接使用netty做为底层通信服务,诸如play. 这样play就不用依赖于容器去进行部署,在没有nginx做反向代理的情况下也能支持高并发.编解码器可以随意扩展,今天是个web,明天就可以是一个ftp或email服务器,个人觉得比较灵活。
 
        《 Netty权威指南(第2版)》试读章节是服务端创建,其对原生NIO类库的使用复杂性进行了讲解,对Netty服务端穿件的时序图和步骤进行了详细说明,对Netty源码对服务端创建进行剖析,最后对新的客户端接入进行了源码层面的分析和讲解。通过本章节的学习,读者可以掌握Netty服务端创建并且可以在实际中使用,编写出高效的代码。
      Netty服务端创建时序图:
          
《 Netty权威指南(第2版)》 学习感悟
 
   Netty服务端创建程序:
       
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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.codec.http.HttpContentDecompressor;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.innoplay.httpserver.config.ConfigInfo;
import com.innoplay.httpserver.config.ConfigProperties;
import com.innoplay.service.context.ApplicationContextUtil;

/**
 * server main entrance, netty tcp server listen on configInfo.listenPort
 * 
 */
public class HttpServer {
	
	

	/**
	 * init load config information
	 */
	private static ConfigInfo configInfo;

	private static final Logger logger = LoggerFactory
			.getLogger(HttpServer.class);

	private static ServerBootstrap bootstrap;
	

	/**
	 * start server method
	 * 
	 * @param args
	 * @throws IOException
	 */
	private void start() throws Exception {
		EventLoopGroup group = new NioEventLoopGroup(configInfo.getThreadNum());
		try {
			bootstrap = new ServerBootstrap();
			bootstrap
					.group(group)
					.channel(NioServerSocketChannel.class)
					.localAddress(
							new InetSocketAddress(configInfo.getListenPort()))
					.childHandler(new ChannelInitializer<SocketChannel>() {

						/*
						 * (non-Javadoc)
						 * 
						 * @see
						 * io.netty.channel.ChannelInitializer#initChannel(io
						 * .netty.channel.Channel)
						 */
						@Override
						protected void initChannel(SocketChannel ch)
								throws Exception {

							ch.pipeline().addLast(new HttpServerCodec());
							ch.pipeline().addLast(new HttpContentDecompressor());
							ch.pipeline().addLast(new HttpObjectAggregator(Integer.MAX_VALUE));//定义
							ch.pipeline().addLast(new HttpServerHandler());

						}
					});

			ChannelFuture f = bootstrap.bind().sync();
			logger.info(HttpServer.class.getName()
					+ " started and listen on " + f.channel().localAddress());
			f.channel().closeFuture().sync();
			
		} finally {
			group.shutdownGracefully().sync();
		}
	}

	/**
	 * main entrance
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			//program argument setting/windows/linux
			//conf.path=E:\Workspace\server\trunk\innoplay-httpserver\target\conf
			if(args != null) {
				for(String s : args) {
					if(s.startsWith("--conf.path")) {
						System.setProperty(ConfigProperties.CONFIGPATH, s.replace("--conf.path=", ""));
				        PropertyConfigurator.configure(System.getProperty(ConfigProperties.CONFIGPATH) + File.separator + "log4j.properties");   

						logger.info("System has received conf.path: {}", s);
					}
				}
			} else {
				logger.error("please setting the --conf.path=XXXX, system exited!");
				System.exit(-1);
			}
	        configInfo = ConfigProperties.loadProperties();
	        
//			ApplicationContext context = new FileSystemXmlApplicationContext(System.getProperty(ConfigProperties.CONFIGPATH) + File.separator +"applicationContext.xml");
			ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
			ApplicationContextUtil.setContext(context);
			HttpServer server = new HttpServer();
			server.start();
			
		} catch (Exception e) {
			logger.error("Server occur an error!", e.getCause());
			e.printStackTrace();
		}
	}

	public static void close() {
		if (bootstrap != null) {
			try {
				bootstrap.group().shutdownGracefully().sync();
			} catch (InterruptedException e) {
				logger.error("Server close occur an error!", e.getCause());
				e.printStackTrace();
			}
		}
	}
}
 
     相信这本书对学习Netty的爱好者有很好的帮助,对编写出高效的代码有很好的帮助。
 
 

相关推荐