NGINX、HAProxy和Traefik负载均衡能力对比
网上有很多讨论Nginx和HAProxy的文章,很多文章基本都是说这样子的内容:
一、Nginx优点:
1、工作在网络7层之上,可针对http应用做一些分流的策略,如针对域名、目录结构,它的正规规则比HAProxy更为强大和灵活,所以,目前为止广泛流行。
2、Nginx对网络稳定性的依赖非常小,理论上能ping通就能进……
二、HAProxy优点:
1、HAProxy是支持虚拟主机的,可以工作在4、7层(支持多网段)
2、HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测……
详细我就不全部贴了,大家也可以自己在google出来,很多一边倒都说HAProxy的负载均衡能力比Nginx的要强,但是这些文章,很大一部分没有一个真实的数据反映出HAProxy和Nginx哪一个能力更强,而且就算有,都是基于比较旧的版本去测试了。
这次我就亲自测试Nginx和HAProxy的负载均衡能力上的区别,等着,标题不是还有一个Traefik吗?嗯,在我搜索过程,我发现有外国的小伙也在讨论Traefik,Traefik是一个反向代理器,是一个比较年轻的项目,对容器支持十分友好,早就2017年,我就在项目使用过,不过仅是在反向代理这一块,在负载均衡上面没有太多深入研究,中文社区中,对他的测评并不多,但很多说法都是说这货的能力比较弱,事实真的如此吗?
故事背景
公司在一个项目上需要用到负载均衡,但在我工作这么多年上,我仅在测试环境上自己部署过Nginx的负载均衡,在生产环境上面,一直都是用云平台提供的负载均衡服务,所以目前为止,对负载均衡的能力掌握比较小,所以我透过这次的测试来了解目前市面常用的负载均衡器的对比。
测试要求
- 负载均衡使用的是7层模型(所以这里没有提到LVS的原因)
- 需要解析HTTPS,在负载均衡直接解析HTTPS,到达后面服务后直接用HTTP,避免后续服务重新解析,消耗性能
前期准备
本次用到服务器5台,配置均为4 CPUs,8G内存,40G存储空间,centOS 7.4 系统。
服务器1 IP:172.18.128.254
服务器2 IP:172.18.128.255
服务器3 IP:172.18.129.0
服务器4 IP:172.18.129.1
服务器5 IP:172.18.129.2
服务器1、2、3用作部署Web服务,服务器4用作部署负载均衡服务,服务器5用作Web客户端。
开始部署
首先部署服务器1、2、3的Web服务,Web服务是一个由go编写的服务,代码如下:
package main
import (
"log"
"fmt"
"net/http"
"runtime"
"io/ioutil"
)
//Define the port used for this web application
var SERVER_PORT = ":8000"
//Read the content of a file
func serveContent(file string) string {
b, err := ioutil.ReadFile(file)
if err != nil {
log.Print(err)
return "{error:\"Resource not found\"}"
}
str := string(b)
return str
}
//REST handler
func handler(w http.ResponseWriter, r *http.Request) {
log.Print("Processing request: ", r.URL.Path[1:])
str := serveContent(r.URL.Path[1:])
fmt.Fprintf(w, str)
}
//Main program
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
log.Print("Starting webserver on Port", SERVER_PORT)
http.HandleFunc("/", handler)
http.ListenAndServe(SERVER_PORT, nil)
}
我再编写一个文件用于接下来请求用的:
# hello.txt
{output:"I Love Spring Cloud"}
部署服务器4的负载均衡服务,由于我比较懒,所有测试服务我都是用Docker来部署,至于HTTPS的证书,是通过Let's Encrypt去申请的,具体申请方法我再另一篇文章会有所提到。
首先,我们来编写各个服务用到的配置文件,
Nginx的配置文件:
# /opt/app/nginx/config/minsheng.conf
upstream minsheng.ms {
server 172.18.128.254:8000;
server 172.18.129.0:8000;
server 172.18.128.255:8000;
}
server{
listen 80;
listen 443 ssl;
server_name test.ruishanio.net;
ssl_certificate /etc/nginx/ssl/test.ruishanio.net/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/test.ruishanio.net/test.ruishanio.net.key;
ssl_trusted_certificate /etc/nginx/ssl/test.ruishanio.net/ca.cer;
location / {
proxy_pass http://minsheng.ms;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
HAProxy的配置文件:
# /opt/app/haproxy/conf/haproxy.cfg
frontend https_frontend
bind *:443 ssl crt /etc/ssl/test.ruishanio.net/test.ruishanio.net.pem
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto:\ https
default_backend web_server
backend web_server
mode http
balance roundrobin
server s1 172.18.128.254:8000 inter 2000 fall 3
server s2 172.18.129.0:8000 inter 2000 fall 3
server s3 172.18.128.255:8000 inter 2000 fall 3
Traefik的配置文件:
# /opt/app/traefik/conf/traefik.toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "/etc/ssl/test.ruishanio.net/fullchain.cer"
keyFile = "/etc/ssl/test.ruishanio.net/test.ruishanio.net.key"
[file]
[backends]
[backends.backend1]
[backends.backend1.servers]
[backends.backend1.servers.server0]
url = "http://172.18.128.254:8000"
weight = 1
[backends.backend1.servers.server1]
url = "http://172.18.129.0:8000"
weight = 1
[backends.backend1.servers.server2]
url = "http://172.18.128.255:8000"
weight = 1
[frontends]
[frontends.frontend1]
entryPoints = ["http", "https"]
backend = "backend1"
passHostHeader = true
[[tls]]
entryPoints = ["https"]
[tls.certificate]
certFile = "/etc/ssl/test.ruishanio.net/fullchain.cer"
keyFile = "/etc/ssl/test.ruishanio.net/test.ruishanio.net.key"
部署命令分别是:
# Nginx
docker run -d --net=host -v /opt/app/nginx/config/:/etc/nginx/conf.d/ -v /opt/app/ssl:/etc/nginx/ssl --name nginx nginx
# HAProxy
docker run -d --net=host -v /opt/app/haproxy/conf/:/usr/local/etc/haproxy -v /opt/app/ssl:/etc/ssl --name=haproxy haproxy
# Traefik
docker run -d --net=host -v /opt/app/traefik/conf/:/etc/traefik -v /opt/app/ssl/:/etc/ssl --name=traefik traefik
最后,我们部署测试机的环境,我们选用 wrk 作为测试工具,CentOS安装wrk参考这里:Installing wrk on Linux
进行测试
现在我们开始进行测试,首先我们分别裸跑三个服务的性能会到哪里。
$ wrk -t 10 -c 200 -d 60s -T 30s --latency http://172.18.128.254:8000/hello.txt
Running 1m test @ http://172.18.128.254:8000/hello.txt
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.47ms 3.26ms 48.20ms 76.78%
Req/Sec 6.75k 445.49 21.86k 86.84%
Latency Distribution
50% 3.44ms
75% 5.26ms
90% 7.68ms
99% 13.68ms
4030219 requests in 1.00m, 568.84MB read
Requests/sec: 67058.69
Transfer/sec: 9.46MB
$ wrk -t 10 -c 200 -d 60s -T 30s --latency http://172.18.128.255:8000/hello.txt
Running 1m test @ http://172.18.128.255:8000/hello.txt
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 15.04ms 80.06ms 1.06s 97.78%
Req/Sec 5.39k 532.13 12.06k 93.46%
Latency Distribution
50% 4.38ms
75% 7.02ms
90% 11.02ms
99