GolangNote

Golang笔记

一个golang 服务与nginx 压力测试的例子

Permalink

这是 hgfischer 写的 Nginx 和 Go 作web 服务的压力测试,主要对下面不同的使用方式做比较:

  • Go HTTP standalone (as the control group)
  • Nginx proxy to Go HTTP
  • Nginx fastcgi to Go TCP FastCGI
  • Nginx fastcgi to Go Unix Socket FastCGI

Nginx 配置

INI: nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
user www-data;
worker_processes auto;
worker_rlimit_nofile 200000;
pid /var/run/nginx.pid;

events {
    worker_connections 10000;
    use epoll;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 300;
    keepalive_requests 10000;
    types_hash_max_size 2048;

    open_file_cache max=200000 inactive=300s; 
    open_file_cache_valid 300s; 
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    server_tokens off;
    dav_methods off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log /var/log/nginx/access.log combined;
    error_log /var/log/nginx/error.log warn;

    gzip off;
    gzip_vary off;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*.conf;
}

虚拟主机配置

INI: nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
upstream go_http {
    server 127.0.0.1:8080;
    keepalive 300;
}

server {
    listen 80;
    server_name go.http;
    access_log off;
    error_log /dev/null crit;

    location / {
        proxy_pass http://go_http;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

upstream go_fcgi_tcp {
    server 127.0.0.1:9001;
    keepalive 300;
}

server {
    listen 80;
    server_name go.fcgi.tcp;
    access_log off;
    error_log /dev/null crit;

    location / {
        include fastcgi_params;
        fastcgi_keep_conn on;
        fastcgi_pass go_fcgi_tcp;
    }
}

upstream go_fcgi_unix {
    server unix:/tmp/go.sock;
    keepalive 300;
}

server {
    listen 80;
    server_name go.fcgi.unix;
    access_log off;
    error_log /dev/null crit;

    location / {
        include fastcgi_params;
        fastcgi_keep_conn on;
        fastcgi_pass go_fcgi_unix;
    }
}

测试用的go 代码

Go: 测压
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package main

import (
    "fmt"
    "log"
    "net"
    "net/http"
    "net/http/fcgi"
    "os"
    "os/signal"
    "syscall"
)

var (
    abort bool
)

const (
    SOCK = "/tmp/go.sock"
)

type Server struct {
}

func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    body := "Hello World\n"
    // Try to keep the same amount of headers
    w.Header().Set("Server", "gophr")
    w.Header().Set("Connection", "keep-alive")
    w.Header().Set("Content-Type", "text/plain")
    w.Header().Set("Content-Length", fmt.Sprint(len(body)))
    fmt.Fprint(w, body)
}

func main() {
    sigchan := make(chan os.Signal, 1)
    signal.Notify(sigchan, os.Interrupt)
    signal.Notify(sigchan, syscall.SIGTERM)

    server := Server{}

    go func() {
        http.Handle("/", server)
        if err := http.ListenAndServe(":8080", nil); err != nil {
            log.Fatal(err)
        }
    }()

    go func() {
        tcp, err := net.Listen("tcp", ":9001")
        if err != nil {
            log.Fatal(err)
        }
        fcgi.Serve(tcp, server)
    }()

    go func() {
        unix, err := net.Listen("unix", SOCK)
        if err != nil {
            log.Fatal(err)
        }
        fcgi.Serve(unix, server)
    }()

    <-sigchan

    if err := os.Remove(SOCK); err != nil {
        log.Fatal(err)
    }
}

GOMAXPROCS = 1 时比较结果

Go standalone

Bash: Go standalone
1
2
3
4
5
6
7
8
9
# wrk -t100 -c5000 -d30s http://127.0.0.1:8080/
Running 30s test @ http://127.0.0.1:8080/
  100 threads and 5000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   116.96ms   17.76ms 173.96ms   85.31%
    Req/Sec   429.16     49.20   589.00     69.44%
  1281567 requests in 29.98s, 215.11MB read
Requests/sec:  42745.15
Transfer/sec:      7.17MB

Nginx + Go through HTTP

Bash: Nginx + Go through HTTP
1
2
3
4
5
6
7
8
9
# wrk -t100 -c5000 -d30s http://go.http/
Running 30s test @ http://go.http/
  100 threads and 5000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   124.57ms   18.26ms 209.70ms   80.17%
    Req/Sec   406.29     56.94     0.87k    89.41%
  1198450 requests in 29.97s, 201.16MB read
Requests/sec:  39991.57
Transfer/sec:      6.71MB

Nginx + Go through FastCGI TCP

Bash: Nginx + Go through FastCGI TCP
1
2
3
4
5
6
7
8
9
10
# wrk -t100 -c5000 -d30s http://go.fcgi.tcp/
Running 30s test @ http://go.fcgi.tcp/
  100 threads and 5000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   514.57ms  119.80ms   1.21s    71.85%
    Req/Sec    97.18     22.56   263.00     79.59%
  287416 requests in 30.00s, 48.24MB read
  Socket errors: connect 0, read 0, write 0, timeout 661
Requests/sec:   9580.75
Transfer/sec:      1.61MB

Nginx + Go through FastCGI Unix Socket

Bash: Nginx + Go through FastCGI Unix Socket
1
2
3
4
5
6
7
8
9
10
# wrk -t100 -c5000 -d30s http://go.fcgi.unix/
Running 30s test @ http://go.fcgi.unix/
  100 threads and 5000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   425.64ms   80.53ms 925.03ms   76.88%
    Req/Sec   117.03     22.13   255.00     81.30%
  350162 requests in 30.00s, 58.77MB read
  Socket errors: connect 0, read 0, write 0, timeout 210
Requests/sec:  11670.72
Transfer/sec:      1.96MB

原文 《Benchmarking Nginx with Go

本文网址: https://golangnote.com/topic/69.html 转摘请注明来源

Related articles

Golang http IPv4/IPv6 服务

Golang 的网络服务,如果不指定IPv4 或 IPv6,如果VPS 同时支持 IPv4 和 IPv6,`net.Listen()` 只会监听 IPv6 地址。但这不影响客户端使用 IPv4 地址来访问。...

Write a Comment to "一个golang 服务与nginx 压力测试的例子"

Submit Comment Login
Based on Golang + fastHTTP + sdb | go1.22.3 Processed in 1ms