1 概述
Nginx采用的是IO复用模型,能处理超高并发。
Go语言采用协程,能轻量级的处理超高并发。
那么在不考虑业务逻辑复杂的前提下,即假如将Nginx和Go都提供一个/test接口,并在接口逻辑中都只是让其做20毫秒的耗时操作,那么这两者的性能差异大概是多少呢?尝试一下
2 环境说明
Centos 服务器环境说明:
3 源代码
3.1 go
package main
import (
"net/http"
"time"
"log"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 模拟 20ms 业务处理
time.Sleep(20 * time.Millisecond)
w.Write([]byte("OK"))
}
func main() {
http.HandleFunc("/test", handler)
log.Println("Go server listening on :8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
3.2 nginx openresty
worker_processes auto;
events {
worker_connections 10240;
}
http {
# 如果你原来有其它配置项(如 log_format、lua_shared_dict 等),保留它们
server {
listen 8081;
location = /test {
content_by_lua_block {
-- 模拟 20 ms 业务处理
ngx.sleep(0.02)
ngx.say("OK")
}
}
}
}
4 启动服务
go服务启动端口为8080
nginx openresty 服务启动端口为8081
5 ab工具压测
5.1 第一轮:100并发共请求1万次
go:
ab -n 10000 -c 100 http://127.0.0.1:8080/
Concurrency Level: 100
Time taken for tests: 2.134 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10000
Total transferred: 1760000 bytes
HTML transferred: 190000 bytes
Requests per second: 4685.38 [#/sec] (mean)
Time per request: 21.343 [ms] (mean)
Time per request: 0.213 [ms] (mean, across all concurrent requests)
Transfer rate: 805.30 [Kbytes/sec] received
nginx:
Concurrency Level: 100
Time taken for tests: 3.322 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 1288900000 bytes
HTML transferred: 1286460000 bytes
Requests per second: 3010.62 [#/sec] (mean)
Time per request: 33.216 [ms] (mean)
Time per request: 0.332 [ms] (mean, across all concurrent requests)
Transfer rate: 378944.26 [Kbytes/sec] received
小结:100并发情况下,go的QPS为4685,nginx的qps为3010
5.2 第二轮:500并发共请求5万次
ab -n 50000 -c 500 http://127.0.0.1:8080/
go:
Concurrency Level: 500
Time taken for tests: 8.483 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Non-2xx responses: 50000
Total transferred: 8800000 bytes
HTML transferred: 950000 bytes
Requests per second: 5893.87 [#/sec] (mean)
Time per request: 84.834 [ms] (mean)
Time per request: 0.170 [ms] (mean, across all concurrent requests)
Transfer rate: 1013.01 [Kbytes/sec] received
nginx:
Concurrency Level: 500
Time taken for tests: 18.526 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Total transferred: 6444500000 bytes
HTML transferred: 6432300000 bytes
Requests per second: 2698.86 [#/sec] (mean)
Time per request: 185.264 [ms] (mean)
Time per request: 0.371 [ms] (mean, across all concurrent requests)
Transfer rate: 339702.78 [Kbytes/sec] received
奇怪,为什么500并发情况下,go的QPS有5893,而Nginx只有2698
5.3 第三轮:1000并发共请求10万次
go:
Concurrency Level: 1000
Time taken for tests: 21.770 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Non-2xx responses: 100000
Total transferred: 17600000 bytes
HTML transferred: 1900000 bytes
Requests per second: 4593.43 [#/sec] (mean)
Time per request: 217.702 [ms] (mean)
Time per request: 0.218 [ms] (mean, across all concurrent requests)
Transfer rate: 789.50 [Kbytes/sec] received
nginx:
Concurrency Level: 1000
Time taken for tests: 39.272 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 12889000000 bytes
HTML transferred: 12864600000 bytes
Requests per second: 2546.37 [#/sec] (mean)
Time per request: 392.715 [ms] (mean)
Time per request: 0.393 [ms] (mean, across all concurrent requests)
Transfer rate: 320509.78 [Kbytes/sec] received
1000并发下,go的QPS有4593,nginx的QPS只有2546
6 小结
1.在如上配置的服务器环境+配置(注意:Nginx的配置应该可以一定程度上进行调优,这里暂时先不测试了)的情况下
2.go和nginx都提供一个/test的接口,且耗时都是在固定20秒的情况下
3.1000并发请求是,go的QPS为4.5k左右,nginx的QPS大概为2.5k左右。
7 临时想到的Python和Java
7.1 Python3.6
既然看到了go语言的情况,自然又要拿出我们的老朋友python来测试一下了:
import asyncio
from aiohttp import web
async def handler(request):
# 模拟 20 毫秒的耗时操作
await asyncio.sleep(0.02)
return web.Response(text="OK")
app = web.Application()
app.router.add_get('/test', handler)
if __name__ == '__main__':
web.run_app(app, host='0.0.0.0', port=8080)

在经过了漫长的等待:故障了!
所以决定将并发控制在200,总请求数控制在20000
Concurrency Level: 200
Time taken for tests: 52.494 seconds
Complete requests: 20000
Failed requests: 0
Write errors: 0
Non-2xx responses: 20000
Total transferred: 3440000 bytes
HTML transferred: 280000 bytes
Requests per second: 381.00 [#/sec] (mean)
Time per request: 524.941 [ms] (mean)
Time per request: 2.625 [ms] (mean, across all concurrent requests)
Transfer rate: 64.00 [Kbytes/sec] received
从这里来看python3.6的QPS大概是381(注意!应该是有调优空间的,且每个接口中耗时20毫秒)
7.2 java1.8
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class SimpleHttpServer {
public static void main(String[] args) throws IOException {
// 创建 HTTP 服务器,监听端口 8080
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
// 创建上下文,处理 /test 路径的请求
server.createContext("/test", new MyHandler());
// 设置默认的执行器
server.setExecutor(null);
// 启动服务器
server.start();
System.out.println("Java HTTP server started on port 8080");
}
static class MyHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
try {
// 模拟 20 毫秒的耗时操作
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
String response = "OK";
exchange.sendResponseHeaders(200, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
200并发2万请求试试:3171
Concurrency Level: 200
Time taken for tests: 6.306 seconds
Complete requests: 20000
Failed requests: 0
Write errors: 0
Non-2xx responses: 20000
Total transferred: 2420000 bytes
HTML transferred: 1000000 bytes
Requests per second: 3171.68 [#/sec] (mean)
Time per request: 63.058 [ms] (mean)
Time per request: 0.315 [ms] (mean, across all concurrent requests)
Transfer rate: 374.78 [Kbytes/sec] received
1000并发10万请求试试:5271
Concurrency Level: 1000
Time taken for tests: 18.969 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Non-2xx responses: 100000
Total transferred: 12100000 bytes
HTML transferred: 5000000 bytes
Requests per second: 5271.80 [#/sec] (mean)
Time per request: 189.688 [ms] (mean)
Time per request: 0.190 [ms] (mean, across all concurrent requests)
Transfer rate: 622.94 [Kbytes/sec] received
8 总结
1.go1.20 QPS 4.5k左右
2.nginx QPS 2.5k左右
3.python3.6 QPS 381左右
4.java1.8 QPS 5.2k左右
难不成是我测试的有问题?怎么java比go的QPS居然还要高?(有可能是调优问题+环境问题,go语言的性能可能在更高配置的环境下可能性能更高)该数据仅供参考