netty和tomcat的hello world性能比較

小弟有點菜, 測試不科學的地方敬請指教。
java

環境:nginx

       16G內存,  8核雙線程CPU,   cenos6,   jmeter,  netty5,   tomcat6, JDK1.7-64web

1    netty的源碼:example下的hello worldbootstrap

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class HttpHelloWorldServer {

	private final int port;

	public HttpHelloWorldServer(int port) {
		this.port = port;
	}

	public void run() throws Exception {
		// Configure the server.
		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		EventLoopGroup workerGroup = new NioEventLoopGroup(50);
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.option(ChannelOption.SO_BACKLOG, 1024);
			b.group(bossGroup, workerGroup)
					.channel(NioServerSocketChannel.class)
					.childHandler(new HttpHelloWorldServerInitializer());

			Channel ch = b.bind(port).sync().channel();
			System.out.println(" connection is ok");
			ch.closeFuture().sync();
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

	public static void main(String[] args) throws Exception {
		int port;
		if (args.length > 0) {
			port = Integer.parseInt(args[0]);
		} else {
			port = 8125;
		}
		new HttpHelloWorldServer(port).run();
	}
}

HttpHelloWorldServerHandler:tomcat

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;

import static io.netty.handler.codec.http.HttpHeaders.Names.*;
import static io.netty.handler.codec.http.HttpHeaders.*;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.*;

public class HttpHelloWorldServerHandler extends ChannelHandlerAdapter {
    private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest req = (HttpRequest) msg;

            if (is100ContinueExpected(req)) {
                ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
            }
            boolean keepAlive = isKeepAlive(req);
            FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(CONTENT));
            response.headers().set(CONTENT_TYPE, "text/plain");
            response.headers().set(CONTENT_LENGTH, response.content().readableBytes());

            if (!keepAlive) {
                ctx.write(response).addListener(ChannelFutureListener.CLOSE);
            } else {
                response.headers().set(CONNECTION, Values.KEEP_ALIVE);
                ctx.write(response);
            }
        }
    }

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

  HttpHelloWorldServerInitializer:app

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

public class HttpHelloWorldServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline p = ch.pipeline();

        // Uncomment the following line if you want HTTPS
        //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
        //engine.setUseClientMode(false);
        //p.addLast("ssl", new SslHandler(engine));

        p.addLast("codec", new HttpServerCodec());
        p.addLast("handler", new HttpHelloWorldServerHandler());
    }
}

2    tomcat的代碼, 就一個sevlet異步

package testTomcatHttp;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		PrintWriter printWriter = resp.getWriter();
		printWriter.println("<h1>Hello World!</h1>");
	}
}

  web.xmljvm

<servlet>  
    <servlet-name>hello</servlet-name>  
    <servlet-class>testTomcatHttp.TestServlet</servlet-class>  
  </servlet>     
  <servlet-mapping>  
    <servlet-name>hello</servlet-name>  
    <url-pattern>/hello</url-pattern>  
  </servlet-mapping>


測試備註:socket

1)    因爲tomcat6中, 有個bug, acceptor參數設置無效,只能是1, 因此咱們只改變maxThreads的值;ide

2)   tomcat和netty的jvm參數配置爲:  -server -Xms2048m -Xmx3098m -Xloggc:/root/nettyhttp/gc.log

3)   jMeter循環次數都是1000次,sleep 1ms

測試用例:

(1)   netty :  acceptor=1,   I/O Threads=50,   jMeter的用戶線程數分別爲100和50

(2)  tomcat nio:  acceptor=1,   maxThreads=50,   jMeter的用戶線程數分別爲100和50

(3)  tomcat bio:  acceptor=1,   maxThreads=50,   jMeter的用戶線程數分別爲100和50

備註: 不穩定,第一次測試500多, 第二次700多,   且剛開始的Throughput很高, 可是越後越慢, 且開始error

(4)  在tomcat bio模式下, 把maxThreads=16   netty I/OThreads默認, 在本機上也是16,

測試的結果,  tomcat只有300多, 且有報錯,   而netty的測試結果800上下,且沒有報錯。


因此, 根據測試結果能夠推斷出,  

  a    netty+http在性能上和可靠性和仍是不錯的, 且能夠nginx搭配使用。

  b     tomcat, nio模式還能夠, 可是bio模式,測試結果不怎麼好。

   且, 

 netty + http 定製不用受web容器的限制, IO線程對於執行時間比較長的task, 能夠異步交給現場池, 猜想tomcat的nio模式中,  actiom-server中也能夠這樣作。可是tomcat, 別人都封裝好了, 不會出現大問題。

具體使用哪一個, 根據場景進行選擇。 


歡迎指教!

相關文章
相關標籤/搜索