前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >四种方式实现HttpServer并测试负载能力

四种方式实现HttpServer并测试负载能力

作者头像
冬天里的懒猫
发布2021-08-18 18:00:14
3000
发布2021-08-18 18:00:14
举报

1.ServerSocket实现httpServer

1.1 阻塞式

代码:

代码语言:javascript
复制
package com.dhb.gts.javacourse.week2;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

//单线程的socket程序
public class HttpServer01 {

	public static void main(String[] args) throws IOException {
		final ServerSocket serverSocket = new ServerSocket(8801);
		while (true) {
			try {
				final Socket socket = serverSocket.accept();
				service(socket);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static void service(Socket socket) {
		try {
			PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
			printWriter.write("Http/1.1 200 OK");
			printWriter.write("Content-Type:text/html;charset=utf-8");
			String body = "hello,nio1";
			printWriter.println("Content-length:" + body.getBytes().length);
			printWriter.println();
			printWriter.write(body);
			printWriter.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

压测结果:

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8801 -c 40 -N 60
Starting at 2021/8/11 19:31:25
[Press C to stop the test]
123375  (RPS: 1934.5)
---------------Finished!----------------
Finished at 2021/8/11 19:32:28 (took 00:01:03.8117403)
123408  (RPS: 1935)                     Status 303:    123411

RPS: 2022.1 (requests/second)
Max: 170ms
Min: 0ms
Avg: 18.3ms

  50%   below 16ms
  60%   below 18ms
  70%   below 21ms
  80%   below 26ms
  90%   below 32ms
  95%   below 38ms
  98%   below 48ms
  99%   below 57ms
99.9%   below 97ms
HttpServer01测试结果
HttpServer01测试结果

1.2 多线程

代码语言:javascript
复制
package com.dhb.gts.javacourse.week2;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

public class HttpServer02 {

	public static void main(String[] args) throws IOException{
		final ServerSocket serverSocket = new ServerSocket(8802);
		while (true) {
			try {
				final Socket socket = serverSocket.accept();
				new Thread(() -> {
					service(socket);
				}).start();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private static void service(Socket socket) {
		try {
			PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
			printWriter.write("Http/1.1 200 OK");
			printWriter.write("Content-Type:text/html;charset=utf-8");
			String body = "hello,nio1";
			printWriter.println("Content-length:"+body.getBytes().length);
			printWriter.println();
			printWriter.write(body);
			printWriter.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

压测结果

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8802 -c 40 -N 60
Starting at 2021/8/11 19:27:02
[Press C to stop the test]
106020  (RPS: 1663.2)
---------------Finished!----------------
Finished at 2021/8/11 19:28:06 (took 00:01:03.8205636)
Status 303:    106020

RPS: 1735.7 (requests/second)
Max: 214ms
Min: 0ms
Avg: 21.3ms

  50%   below 18ms
  60%   below 21ms
  70%   below 25ms
  80%   below 30ms
  90%   below 37ms
  95%   below 45ms
  98%   below 57ms
  99%   below 68ms
99.9%   below 109ms
HttpServer02测试结果
HttpServer02测试结果

1.3 线程池版本

代码:

代码语言:javascript
复制
package com.dhb.gts.javacourse.week2;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class HttpServer03 {

	public static void main(String[] args) throws IOException{
		ExecutorService executorService  = Executors.newFixedThreadPool(
				Runtime.getRuntime().availableProcessors()*4);
		final ServerSocket serverSocket = new ServerSocket(8803);
		while (true) {
			try {
				final Socket socket = serverSocket.accept();
				executorService.execute(() -> service(socket));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static void service(Socket socket) {
		try {
			PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
			TimeUnit.MILLISECONDS.sleep(1);
			printWriter.write("Http/1.1 200 OK");
			printWriter.write("Content-Type:text/html;charset=utf-8");
			String body = "hello,nio1";
			printWriter.println("Content-length:"+body.getBytes().length);
			printWriter.println();
			printWriter.write(body);
			printWriter.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

压测结果:

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8803 -c 40 -N 60
Starting at 2021/8/11 19:21:14
[Press C to stop the test]
125965  (RPS: 1977.2)
---------------Finished!----------------
Finished at 2021/8/11 19:22:18 (took 00:01:03.8917608)
Status 303:    125965

RPS: 2058.5 (requests/second)
Max: 161ms
Min: 0ms
Avg: 18ms

  50%   below 15ms
  60%   below 18ms
  70%   below 21ms
  80%   below 25ms
  90%   below 31ms
  95%   below 37ms
  98%   below 48ms
  99%   below 59ms
99.9%   below 93ms
HttpServer03测试结果
HttpServer03测试结果

由于在第一组测试的时候,没有增加sleep,得到的测测试结果存在偏差。现在增加1ms的sleep时间。

2.ServerSocket实现httpServer增加sleep

第二组测试: 加上1ms的sleep时间。

2.1 阻塞

-Xms512M -Xmx512M

代码语言:javascript
复制
	private static void service(Socket socket) {
		try {
			PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
			TimeUnit.MILLISECONDS.sleep(1);
			printWriter.write("Http/1.1 200 OK");
			printWriter.write("Content-Type:text/html;charset=utf-8");
			String body = "hello,nio1";
			printWriter.println("Content-length:" + body.getBytes().length);
			printWriter.println();
			printWriter.write(body);
			printWriter.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

测试结果:

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8801 -c 40 -N 60
Starting at 2021/8/11 19:41:09
[Press C to stop the test]
48855   (RPS: 767.1)
---------------Finished!----------------
Finished at 2021/8/11 19:42:13 (took 00:01:03.8082941)
Status 303:    48855

RPS: 798.8 (requests/second)
Max: 130ms
Min: 5ms
Avg: 48.4ms

  50%   below 48ms
  60%   below 50ms
  70%   below 51ms
  80%   below 53ms
  90%   below 56ms
  95%   below 58ms
  98%   below 61ms
  99%   below 63ms
99.9%   below 76ms
PS D:\>
HttpServer01-sleep1ms测试结果
HttpServer01-sleep1ms测试结果

2.2 增加多线程

-Xms512M -Xmx512M

代码语言:javascript
复制
	private static void service(Socket socket) {
		try {
			PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
			TimeUnit.MILLISECONDS.sleep(1);
			printWriter.write("Http/1.1 200 OK");
			printWriter.write("Content-Type:text/html;charset=utf-8");
			String body = "hello,nio1";
			printWriter.println("Content-length:"+body.getBytes().length);
			printWriter.println();
			printWriter.write(body);
			printWriter.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

测试结果:

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8802 -c 40 -N 60
Starting at 2021/8/11 19:44:13
[Press C to stop the test]
105184  (RPS: 1645.5)
---------------Finished!----------------
Finished at 2021/8/11 19:45:16 (took 00:01:03.9565176)
Status 303:    105185

RPS: 1723.6 (requests/second)
Max: 182ms
Min: 1ms
Avg: 21.2ms

  50%   below 18ms
  60%   below 21ms
  70%   below 24ms
  80%   below 29ms
  90%   below 37ms
  95%   below 45ms
  98%   below 57ms
  99%   below 68ms
99.9%   below 108ms
PS D:\>
HttpServer02 sleep 1ms 测试结果
HttpServer02 sleep 1ms 测试结果

2.3 增加线程池

-Xms512M -Xmx512M

代码语言:javascript
复制
	private static void service(Socket socket) {
		try {
			PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
			TimeUnit.MILLISECONDS.sleep(1);
			printWriter.write("Http/1.1 200 OK");
			printWriter.write("Content-Type:text/html;charset=utf-8");
			String body = "hello,nio1";
			printWriter.println("Content-length:"+body.getBytes().length);
			printWriter.println();
			printWriter.write(body);
			printWriter.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

测试结果:

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8803 -c 40 -N 60
Starting at 2021/8/11 19:46:46
[Press C to stop the test]
124993  (RPS: 1959.1)
---------------Finished!----------------
Finished at 2021/8/11 19:47:50 (took 00:01:04.0109473)
Status 303:    124993

RPS: 2041.7 (requests/second)
Max: 174ms
Min: 0ms
Avg: 18ms

  50%   below 15ms
  60%   below 18ms
  70%   below 21ms
  80%   below 25ms
  90%   below 31ms
  95%   below 37ms
  98%   below 46ms
  99%   below 55ms
99.9%   below 97ms
PS D:\>
HttpServer03 sleep 1ms 测试结果
HttpServer03 sleep 1ms 测试结果

3.NettyHttpServer

代码语言:javascript
复制
package com.dhb.gts.javacourse.week2;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class NettyHttpServer {

	public static void main(String[] args) {
		int port = 8808;

		EventLoopGroup bossGroup = new NioEventLoopGroup(2);
		EventLoopGroup workerGroup = new NioEventLoopGroup(16);

		try {
			ServerBootstrap b = new ServerBootstrap();
			b.option(ChannelOption.SO_BACKLOG,128)
					.childOption(ChannelOption.TCP_NODELAY,true)
					.childOption(ChannelOption.SO_KEEPALIVE,true)
					.childOption(ChannelOption.SO_REUSEADDR,true)
					.childOption(ChannelOption.SO_RCVBUF,32*1024)
					.childOption(ChannelOption.SO_SNDBUF,32*1024)
					.childOption(EpollChannelOption.SO_REUSEPORT,true)
					.childOption(ChannelOption.SO_KEEPALIVE,true)
					.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

			b.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
					.handler(new LoggingHandler(LogLevel.INFO))
					.childHandler(new HttpInitializer());

			Channel ch = b.bind(port).sync().channel();
			System.out.println("开启netty http 服务器,监听为 http://127.0.0.1:"+port);
			ch.closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}
}

3.1 不增加sleep

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8808 -c 40 -N 60
Starting at 2021/8/12 20:34:39
[Press C to stop the test]
314648  (RPS: 4901.5)
---------------Finished!----------------
Finished at 2021/8/12 20:35:44 (took 00:01:04.2492745)
Status 200:    314648

RPS: 5152.6 (requests/second)
Max: 212ms
Min: 0ms
Avg: 0.5ms

  50%   below 0ms
  60%   below 0ms
  70%   below 0ms
  80%   below 0ms
  90%   below 0ms
  95%   below 0ms
  98%   below 5ms
  99%   below 9ms
99.9%   below 85ms

测试结果

NettyServer测试结果
NettyServer测试结果

3.2 增加sleep

增加1ms sleep

代码语言:javascript
复制
PS D:\> sb -u http://127.0.0.1:8808 -c 40 -N 60
Starting at 2021/8/12 20:37:33
[Press C to stop the test]
266075  (RPS: 4134.5)
---------------Finished!----------------
Finished at 2021/8/12 20:38:38 (took 00:01:04.3843402)
Status 200:    266076

RPS: 4359.3 (requests/second)
Max: 244ms
Min: 0ms
Avg: 2.4ms

  50%   below 1ms
  60%   below 1ms
  70%   below 1ms
  80%   below 1ms
  90%   below 2ms
  95%   below 8ms
  98%   below 30ms
  99%   below 50ms
99.9%   below 113ms
PS D:\>

测试结果

NettyServer sleep 1ms 测试结果
NettyServer sleep 1ms 测试结果

4.总结

测试结果汇总如下:

测试类型

HttpServer01

HttpServer02

HttpServer03

NettyHttpServer

不增加sleep

2022.1

1735.7

2058.5

5152.6

sleep(1ms)

798.8

1645.5

2041.7

4359.3

可以发现,当不增加sleep的时候,不采用多线程的效率高于多线程。这种情况非常理想。不符合现实场景。但是也说明多线程的线程切换占用了系统的开销。 增加了sleep之后,这符合我们的期望结果,阻塞式的响应非常低,只有700多rps。这能区分增加线程池的优势。 采用netty之后,效果明显提升了很多,netty采用了异步非阻塞IO。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-08-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.ServerSocket实现httpServer
    • 1.1 阻塞式
      • 1.2 多线程
        • 1.3 线程池版本
        • 2.ServerSocket实现httpServer增加sleep
          • 2.1 阻塞
            • 2.2 增加多线程
              • 2.3 增加线程池
              • 3.NettyHttpServer
                • 3.1 不增加sleep
                  • 3.2 增加sleep
                  • 4.总结
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档