haproxy安装以及简单示例
haproxy是个高性能的tcp和http的反向代理。它就是个代理。不像nginx还做web服务器
haproxy安装
-
下载及安装haproxy(安装包下载需FQ)
$ cd /opt/k8s/keepalive-haproxy $ wget https://www.haproxy.org/download/2.1/src/haproxy-2.1.3.tar.gz $ tar -xzvf haproxy-2.1.3.tar.gz $ cd haproxy-2.1.3/ $ make TARGET=linux53 CPU=x86_64 USE_OPENSSL=1 USE_SYSTEMD=1 $ mkdir -p /opt/k8s/haproxy $ make install PREFIX=/opt/k8s/haproxy/
-
USE_OPENSSL=1 开启https
-
USE_SYSTEMD=1 指定为systemd模式,否则不能通过systemd进行启动,报错信息
master-worker mode with systemd support (-Ws) requested, but not compiled. Use master-worker mode (-W) if you are not using Type=notify in your unit file or
-
recompile with USE_SYSTEMD=1.
```
* TARGET=linux53 CPU=x86_64参数,通过uname -a 查看机器对应的系统内核信息决定
```
$ uname -a
Linux master 5.3.0-40-generic #32~18.04.1-Ubuntu SMP Mon Feb 3 14:05:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
```
* PREFIX 指定安装路径
-
使用随安装包提供的配置示例启动haproxy
$ cd /opt/k8s/keepalive-haproxy/haproxy-2.1.3 $ mkdir /opt/k8s/haproxy/conf # 复制示例配置文件 $ cp examples/option-http_proxy.cfg /opt/k8s/haproxy/conf/ # 启动 $ /opt/k8s/haproxy/sbin/haproxy -f /opt/k8s/haproxy/conf/option-http_proxy.cfg
配置 haproxy 日志
因为haproxy会使用rsyslog进行日志处理,所以需要配置rsyslog
-
查看rsyslog的配置,
$ cat /etc/rsyslog.conf # # Include all config files in /etc/rsyslog.d/ # $IncludeConfig /etc/rsyslog.d/*.conf
- /etc/rsyslog.conf 这个是ubuntu系统下的路径,其他系统要查看相对应的配置
- 意思rsyslog会读取/etc/rsyslog.d/下面的 *.conf来进行日志配置
-
在/etc/rsyslog.d/下追加haproxy.conf
$ cat > haproxy.conf<< EOF $ModLoad imudp $UDPServerRun 514 local0.* /var/log/haproxy.log EOF
- 将haproxy日志写入到/var/log/haproxy.log
-
重启rsyslog
$ systemctl restart rsyslog
-
停掉演示例子
$ ps -elf | grep -e PID -e haproxy $ kill -9 ${上一步骤查出的PID}
下面通过具体例子来说明如何利用haproxy对我们的业务进行负载均衡
-
部署图如下
- 客户端调用haproxy:8089,haproxy利用指定负载均衡算法,将请求代理到具体的后端服务
- haproxy在9188上启动监听,响应haproxy自身的状态信息
-
对应的haproxy配置文件
$ cd /opt/k8s/haproxy/conf cat >haproxy.cfg << EOF global maxconn 20000 log 127.0.0.1 local0 info uid 200 gid 200 chroot /opt/k8s/haproxy nbproc 1 daemon defaults mode http retries 3 timeout connect 10s timeout client 20s timeout server 30s frontend web bind *:8089 mode http log global option httplog option dontlognull option nolinger option http_proxy maxconn 8000 timeout client 30s default_backend web-srv backend web-srv mode http option redispatch option abortonclose balance roundrobin cookie SERVERID option httpchk GET /health server web1 192.168.0.114:8086 check cookie server1 inter 2000 fall 3 weight 30 server web2 192.168.0.107:8086 check cookie server1 inter 2000 fall 3 weight 30 listen admin_stats bind 0.0.0.0:9188 mode http stats uri /haproxy-status stats auth admin:admin123 EOF
-
验证配置文件
$ /opt/k8s/haproxy/sbin/haproxy -f /opt/k8s/haproxy/conf/haproxy.cfg -c Configuration file is valid
- 追加 -c 参数,只针对配置文件格式内容进行验证,并不真正启动服务
-
启动后端服务
后端服务采用spring boot编写的一个web程序,里面提供了两个restful API,一个用来做health检查,另一个用来调用测试,在application.yml中将端口设置成8086。
核心代码如下:
@RequestMapping("/header/list") public String listHeader(HttpServletRequest request) { Enumeration<String> headers = request.getHeaderNames(); while (headers.hasMoreElements()) { String header = headers.nextElement(); log.info(header + " is " + request.getHeader(header)); } return "OK"; } @RequestMapping("/health") public String health(HttpServletRequest request) { return "OK"; }
将服务打成可执行jar后,在192.168.0.107、和192.168.0.114上启动
-
启动haproxy
$ cd /opt/k8s/haproxy $ ./sbin/haproxy -f conf/haproxy.cfg
-
查看统计页面
- 可以看到对应的后端web1、web2都正常运行
-
访问 http://192.168.0.107:8089/header/list,观察启动的两个后端服务的日志,可以看到每次haproxy会选一个后端服务响应我们的请求
-
查看haproxy日志
$ tail -10 /var/log/haproxy.log Mar 13 10:24:14 localhost haproxy[19512]: 192.168.0.108:56975 [13/Mar/2020:10:24:14.523] web web-srv/web1 0/0/0/11/11 200 181 - - ---- 2/2/0/0/0 0/0 "GET /header/list HTTP/1.1" Mar 13 10:24:14 localhost haproxy[19512]: 192.168.0.108:56975 [13/Mar/2020:10:24:14.561] web web-srv/web2 1/0/0/4/5 200 1117 - - ---- 2/2/0/0/0 0/0 "GET /favicon.ico HTTP/1.1" Mar 13 10:28:50 localhost haproxy[19512]: 192.168.0.108:57713 [13/Mar/2020:10:28:50.103] web web-srv/web1 0/0/4/12/16 200 181 - - ---- 2/1/0/0/0 0/0 "GET /header/list HTTP/1.1"
模拟故障、故障恢复
-
停掉107服务器上的spring boot工程
-
再次观察haproxy的统计页面
- 其中107服务器上对应的后端服务web2被标记成了DOWN
- 此时继续请求http://192.168.0.107:8089/header/list,会发现haproxy只把请求转发给正常的服务器114
-
恢复107服务器上的spring boot服务
-
再次观察haproxy的统计页面,会发现web2状态重新变成UP,107上的spring boot也能收到haproxy分发过来的请求。
这样利用haproxy的负载技术,不仅仅实现了流量的分发,也在一定程度上提升了系统容错性
将haproxy设置成系统服务
采用此模式,编译阶段必须指定USE_SYSTEMD=1
-
编写haproxy服务启动脚本
$ cat > //etc/systemd/system/haproxy.service <<"EOF" [Unit] Description=HAProxy Load Balancer After=network.target [Service] ExecStartPre=/opt/k8s/haproxy/sbin/haproxy -f /opt/k8s/haproxy/conf/haproxy.cfg -c -q ExecStart=/opt/k8s/haproxy/sbin/haproxy -Ws -f /opt/k8s/haproxy/conf/haproxy.cfg ExecReload=/bin/kill -USR2 $MAINPID [Install] WantedBy=multi-user.target EOF
- 启动参数-W 以master-worker模式工作,在此模式下可通过发送SIGUSR2信号重新加载haproxy
-
启动haproxy
$ systemctl daemon-reload $ systemctl start haproxy $ systemctl status haproxy ● haproxy.service - HAProxy Load Balancer Loaded: loaded (/etc/systemd/system/haproxy.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-03-13 11:48:25 CST; 13s ago Process: 14757 ExecStartPre=/opt/k8s/haproxy/sbin/haproxy -f /opt/k8s/haproxy/conf/haproxy.cfg -c -q (code=exited, status=0/SUCCESS) Main PID: 14758 (haproxy) Tasks: 2 (limit: 4915) CGroup: /system.slice/haproxy.service ├─14758 /opt/k8s/haproxy/sbin/haproxy -Ws -f /opt/k8s/haproxy/conf/haproxy.cfg └─14759 /opt/k8s/haproxy/sbin/haproxy -Ws -f /opt/k8s/haproxy/conf/haproxy.cfg
- 状态为running表示正常,否则 通过 journalctl -u haproxy查看具体原因
-
设置成开机启动
$ systemctl enable haproxy.service
遇到问题
-
configure: error: no acceptable C compiler found in $PATH
$ apt install gcc
-
Can not include OpenSSL headers files
$ apt-get install libssl-dev
-
systemd/sd-daemon.h: 没有那个文件或目录
$ apt install libsystemd-dev
-
400 bad request
一开始不懂haproxy的配置语法,在backend中追加了option http_proxy
去掉这个配置就可以了