下载 http://www.jboss.org/netty/downloads.html
简介 http://www.jboss.org/netty
Jboss的Netty项目旨在提供异步驱动的网络应用程序的框架和工具, 可以用于快速开发, 可方便维护的、高性能的、高扩展性的服务器/客户端之间的通迅协议。
Plurk是一个快速成长,并且已经成为互联网上最大的几个使用python语言的网站之之一,Plurk尝试了以下一些框架/web容器:
Python Twisted:太耗资源了
Jetty:iGoogle的web容器,可惜一万并发的时候用了2G的内存
Apache Tomcat:太吃内存了
Apache MINA:文档很糟糕,可扩展性很差
最后,Plurk发现Netty非常优秀, 在一台四核的服务器上,10万的并发只用了some GB的内存和20%左右的CPU
JBoss社区最近发布了Netty 3.1.0,为用户提供了编写客户/服务网络应用的另一选择。Netty自称是:
一款异步的事件驱动的网络应用框架和工具,用于快速开发可维护的高性能、高扩展性协议服务器和客户端。也就是说,Netty是一个NIO客户端/服务器框架,支持快速、简单地开发网络应用,如协议服务器和客户端。它极大简化了网络编程,如TCP和UDP套接字服务器。
关于Netty的分类,它与Apache Mina和Grizzly属于同一舞台。该最新版本包含了一系列功能和性能、API可用性的增强。其中包括:
* 更简单的大数据流(例子)
* 更多可靠的OutOfMemoryError预防机制
* 新的传输
o 基于OIO和NIO的UDP传输
o VM内传输
o HTTP隧道
* 与Google Protocol Buffers集成
* 与JBoss Microcontainer、OSGI、Guice和Spring集成
HTTP隧道功能满足了用户的迫切需求,在早期发布说明中总结到:
HTTP隧道传输(位于org.jboss.netty.channel.socket.http)是一种套接字传输,支持任意已经存在的套接字应用在HTTP之上通过代理传输。这种传输在需要越过防火墙而不修改现存服务器应用时特别有用。工作原理如下:
Http隧道客户端套接字通道 --> 对HTTP友好的防火墙 --> Servlet容器 (如Tomcat、Jetty) --> Http隧道Servlet --> 你的服务器应用
当然在选择一个框架用于开发网络应用时,性能和可扩展性是重要因素。Netty团队在他们的网站上提供了性能信息。你也可以在Apache Mina网站上找到它的性能数据。Nicholas Hagen发布了一系列博文,记录了他如何选择 Mina、Grizzly或者Netty。最终他决定选用Netty,不过指出:
总的来说,在性能、内存和功能使用方面,我倾向于Netty,而不是Mina和Grizzly。请注意你需要通过自己的分析来决定哪种框架适合你的需求。
Netty下一版本3.2.0,目前正在开发过程中。
JBoss社区最近发布了Netty 3.1.0,为用户提供了编写客户/服务网络应用的另一选择。Netty自称是:
一款异步的事件驱动的网络应用框架和工具,用于快速开发可维护的高性能、高扩展性协议服务器和客户端。也就是说,Netty是一个NIO客户端/服务器框架,支持快速、简单地开发网络应用,如协议服务器和客户端。它极大简化了网络编程,如TCP和UDP套接字服务器。
关于Netty的分类,它与Apache Mina和Grizzly属于同一舞台。该最新版本包含了一系列功能和性能、API可用性的增强。其中包括:
* 更简单的大数据流(例子)
* 更多可靠的OutOfMemoryError预防机制
* 新的传输
o 基于OIO和NIO的UDP传输
o VM内传输
o HTTP隧道
* 与Google Protocol Buffers集成
* 与JBoss Microcontainer、OSGI、Guice和Spring集成
HTTP隧道功能满足了用户的迫切需求,在早期发布说明中总结到:
HTTP隧道传输(位于org.jboss.netty.channel.socket.http)是一种套接字传输,支持任意已经存在的套接字应用在HTTP之上通过代理传输。这种传输在需要越过防火墙而不修改现存服务器应用时特别有用。工作原理如下:
Http隧道客户端套接字通道 --> 对HTTP友好的防火墙 --> Servlet容器 (如Tomcat、Jetty) --> Http隧道Servlet --> 你的服务器应用
当然在选择一个框架用于开发网络应用时,性能和可扩展性是重要因素。Netty团队在他们的网站上提供了性能信息。你也可以在Apache Mina网站上找到它的性能数据。Nicholas Hagen发布了一系列博文,记录了他如何选择 Mina、Grizzly或者Netty。最终他决定选用Netty,不过指出:
总的来说,在性能、内存和功能使用方面,我倾向于Netty,而不是Mina和Grizzly。请注意你需要通过自己的分析来决定哪种框架适合你的需求。
Netty下一版本3.2.0,目前正在开发过程中,路线图可以在这里查看。
此版本的主要更新:
处理大容量数据流更简单
处理协议编码和单元测试更简单
I/O超时和idle状态检测
应用程序的关闭更简单,更安全
更可靠的OutOfMemoryError预防
新的传输方式:
1.基于OIO和NIO的UDP传输
2.本地传输(又名 in-VM传输)
3.HTTP通道,可绕过防火墙
新的编码器:
1.HTTP客户端和服务器端
2.用于实现各种专有协议的工具
与其他技术的整合:
1.Google Protocol Buffers
2.JBoss Microcontainer, OSGi, Guice以及Spring
package example.helloword.server; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import example.helloword.NetConstant; public class Server { private static Server server = new Server(); private ServerBootstrap bootstrap; private Server() {} public static Server getInstance() { return server; } public void start() { bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors .newCachedThreadPool())); bootstrap.setPipelineFactory(new ServerPipelineFactory()); bootstrap.bind(new InetSocketAddress(NetConstant.server_port)); } public void stop() { bootstrap.releaseExternalResources(); } public static void main(String[] args) { Server server = Server.getInstance(); server.start(); } }
package example.helloword.server; import static org.jboss.netty.channel.Channels.pipeline; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.handler.codec.string.StringDecoder; import org.jboss.netty.handler.codec.string.StringEncoder; public class ServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipleline = pipeline(); pipleline.addLast("encode", new StringEncoder()); pipleline.addLast("decode", new StringDecoder()); pipleline.addLast("handler", new ServerHandler()); return pipleline; } }
package example.helloword.server; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class ServerHandler extends SimpleChannelUpstreamHandler { public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { System.out.println("recive message,message content:" + e.getMessage()); e.getChannel().write("byte"); } public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { e.getChannel().close(); } }
package example.helloword.client22; import static org.jboss.netty.channel.Channels.pipeline; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; import org.jboss.netty.handler.codec.frame.LengthFieldPrepender; import org.jboss.netty.handler.codec.string.StringDecoder; import org.jboss.netty.handler.codec.string.StringEncoder; public class ClientPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipleline = pipeline(); pipleline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); pipleline.addLast("frameEncode", new LengthFieldPrepender(4, false)); pipleline.addLast("encode", new StringEncoder()); pipleline.addLast("decode", new StringDecoder()); pipleline.addLast("handler", new ClinetHandler()); return pipleline; } }
package example.helloword.client22; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import example.helloword.NetConstant; import example.helloword.client2.ClientPipelineFactory; public class ClientPool { public static ClientPool clientPool = new ClientPool(); private ClientBootstrap bootstrap; private ClientPool() { bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors .newCachedThreadPool())); bootstrap.setPipelineFactory(new ClientPipelineFactory()); bootstrap.setOption("tcpNoDelay", true); bootstrap.setOption("keepAlive", true); } public static ClientPool getInstance() { return clientPool; } public void getChannelFuture(String host, int port, String message) { ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, NetConstant.server_port)); future.awaitUninterruptibly(); if (!future.isSuccess()) { future.getCause().printStackTrace(); future.getChannel().getCloseFuture().awaitUninterruptibly(); return; } future.getChannel().write(message); } public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 1000; i++) { ClientPool.getInstance().getChannelFuture("127.0.0.1", 0, "test" + i); Thread.sleep(1000 * 3); } } }
2、apache mina
下载 http://mina.apache.org/downloads.html
public class Test { public static void main(String[] args) throws IOException { HttpServer httpServer; httpServer = HttpServer.create(new InetSocketAddress(81), 5); httpServer.createContext("/", new Handler()); httpServer.start(); } static class Handler implements HttpHandler { public void handle(HttpExchange exchange) throws IOException { Headers requestHeaders = exchange.getRequestHeaders(); Headers responseHeaders = exchange.getResponseHeaders(); responseHeaders.set("Content-Type", "text/plain"); exchange.sendResponseHeaders(200, 0L); OutputStream responseBody = new BufferedOutputStream(exchange.getResponseBody(), 64*1024); responseBody.write("Hello!".getBytes()); responseBody.close(); exchange.close(); } } }
import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory; import org.apache.mina.filter.ssl.SslFilter; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * (<b>Entry point</b>) Echo server * * @author The Apache MINA Project ([email protected]) * @version $Rev: 677923 $, $Date: 2008-07-18 16:55:24 +0200 (Fri, 18 Jul 2008) $ */ public class Main { /** Choose your favorite port number. */ private static final int PORT = 8080; /** Set this to true if you want to make the server SSL */ private static final boolean USE_SSL = false; public static void main(String[] args) throws Exception { SocketAcceptor acceptor = new NioSocketAcceptor(); DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); // Bind acceptor.setHandler(new EchoProtocolHandler()); acceptor.bind(new InetSocketAddress(PORT)); System.out.println("Listening on port " + PORT); for (;;) { System.out.println("R: " + acceptor.getStatistics().getReadBytesThroughput() + ", W: " + acceptor.getStatistics().getWrittenBytesThroughput()); Thread.sleep(3000); } } }
import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.ssl.SslFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link IoHandler} implementation for echo server. * * @author The Apache MINA Project ([email protected]) * @version $Rev: 713957 $, $Date: 2008-11-14 10:27:16 +0100 (Fri, 14 Nov 2008) $, */ public class EchoProtocolHandler extends IoHandlerAdapter { private final Logger logger = LoggerFactory.getLogger(getClass()); @Override public void sessionCreated(IoSession session) { session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); // We're going to use SSL negotiation notification. session.setAttribute(SslFilter.USE_NOTIFICATION); } @Override public void sessionClosed(IoSession session) throws Exception { logger.info("CLOSED"); } @Override public void sessionOpened(IoSession session) throws Exception { logger.info("OPENED"); } @Override public void sessionIdle(IoSession session, IdleStatus status) { logger.info("*** IDLE #" + session.getIdleCount(IdleStatus.BOTH_IDLE) + " ***"); } @Override public void exceptionCaught(IoSession session, Throwable cause) { session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { // Write the received data back to remote peer session.write(((IoBuffer) message).duplicate()); } }
public class Test { public static void main(String[] args) throws IOException { HttpServer httpServer; httpServer = HttpServer.create(new InetSocketAddress(81), 5); httpServer.createContext("/", new Handler()); httpServer.start(); } static class Handler implements HttpHandler { public void handle(HttpExchange exchange) throws IOException { Headers requestHeaders = exchange.getRequestHeaders(); Headers responseHeaders = exchange.getResponseHeaders(); responseHeaders.set("Content-Type", "text/plain"); exchange.sendResponseHeaders(200, 0L); OutputStream responseBody = new BufferedOutputStream(exchange.getResponseBody(), 64*1024); responseBody.write("Hello!".getBytes()); responseBody.close(); exchange.close(); } } }