1.Jboss Netty项目-优秀的NIO框架
下载
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();
}
}
}