Nginx openresty web服务 与 Go 原生web服务性能对比

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语言的性能可能在更高配置的环境下可能性能更高)该数据仅供参考

相关推荐
stark张宇35 分钟前
超越 Hello World:深入小程序 Hybrid 初衷、安全配置与上线全链路
nginx·微信小程序·php
希晨er4 小时前
Nginx从入门到实践:安装、配置与应用
nginx
jc06205 小时前
4.5-中间件之Nginx
运维·服务器·nginx
梁梁梁梁较瘦6 小时前
Go工具链
go
半枫荷9 小时前
六、Go语法基础(条件控制和循环控制)
go
青鱼入云12 小时前
对比nginx、kong、apisix、zuul、gateway网关
nginx·gateway·kong
程序员勾践1 天前
安装nginx
linux·nginx·centos
半枫荷2 天前
五、Go语法基础(输入和输出)
go
小王在努力看博客2 天前
CMS配合闲时同步队列,这……
go
fxshy2 天前
CentOS 7上安装并配置Nginx监听81端口的完整指南
linux·nginx·centos