苏苏的博客

简约至极

HAProxy优化应用程序速度

HAProxy

HAProxy高性能的反向代理软件,更专注于TCP,HTTP处理,它可以基于四层或七层进行反向代理,尤其适合于高负载且需要进行七层处理的 Web 站点.

单进程、事件驱动模型,通常用于超高流量的负载均衡.

我们也可以使用它来作为中转站,使直连连通率不好的请求进过中转提升速度.

编译安装

apt-get update && apt-get install -y wget gcc g++ make libpcre++0v5 libpcre++-dev
yum update && yum install wget gcc make
HAPROXY_VERSION=haproxy-1.7.9
CPU_NUM=`cat /proc/cpuinfo | grep processor | wc -l`
wget http://www.haproxy.org/download/1.7/src/${HAPROXY_VERSION}.tar.gz
tar zxf ${HAPROXY_VERSION}.tar.gz
cd ${HAPROXY_VERSION}
export CFLAGS="-O3"
make TARGET=linux2628 ARCH=X86_64 USE_STATIC_PCRE=1 -j$CPU_NUM && make install

编译32位版本make TARGET=linux26 ARCH=i686 USE_STATIC_PCRE=1 -j$CPU_NUM

在64位系统下编译32位需要apt-get install gcc-multilib g++-multilib

我编译好的haproxy version 1.7.9

64位 http://share.suconghou.cn/files/bin/haproxy.xz

32位 http://share.suconghou.cn/files/bin/haproxy.gz

/etc/systemd/system/haproxy.service

[Unit]
Description=haproxy service

[Service]
TimeoutStartSec=0
ExecStart=/usr/local/sbin/haproxy -f /etc/haproxy.cfg
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

alpine里静态编译

apk update && apk upgrade
apk add gcc g++ make wget linux-headers pcre-dev
cd /tmp
HAPROXY_VERSION=haproxy-1.7.9
wget http://www.haproxy.org/download/1.7/src/${HAPROXY_VERSION}.tar.gz
tar zxf ${HAPROXY_VERSION}.tar.gz
cd ${HAPROXY_VERSION}
make TARGET=linux2628 ARCH=X86_64 USE_STATIC_PCRE=1 LDFLAGS="-static" ADDLIB="/usr/lib/libc.a" -j2  && make install

编译很快,一分钟即可编译完成.

不能直接使用LDFLAGS="-static"静态编译. 需要将 /usr/lib/libc.a 静态链接到最终文件内,因此需要添加ADDLIB="/usr/lib/libc.a"

他使得在link 阶段静态链接/usr/lib/libc.a

上述脚本执行后,即可得到可执行文件. strip后大大减小目标文件.

使用Docker版本的HAProxy

这里提供一份编译好的最新版HAProxy镜像 https://hub.docker.com/r/suconghou/haproxy/

useradd -M -s /sbin/nologin haproxy

-M:不创建家目录

-s:指定用户登陆时使用的shell,nologin就是登陆不了

优化国外主机速度

HAProxy有多种连接模型,还有多种负载均衡算法,由于只有一台机器,我们主要侧重于使用它的反向代理.

HAProxy可以一边保持与代理后端的长连接,一边又保持对客户端的连接. 这样双向保持持久连接,省去了中间反复创建连接可以在一定程度上优化速度.

其只需要一个配置文件,配置主要有以下几部分功能

  • default:用于为所有其它配置段提供默认参数
  • frontend:用于定义一系列监听的套接字,这些套接字可接受客户端请求并与之建立连接
  • backend:用于定义一系列后端服务器,代理将会将对应客户端的请求转发至这些服务器
  • listen: 通过关联前端和后端定义了一个完整的代理

配置写在haproxy.cfg文件中,启动的时候指定使用的配置文件.

haproxy -c -f /etc/haproxy/haproxy.cfg检查配置文件,haproxy -f /etc/haproxy/haproxy.cfg使用此配置文件启动

使用listen 直接定义前端/后端

global
        pidfile   /var/run/haproxy.pid
        ulimit-n  15000
        user        nobody
        group       nobody
        daemon

defaults
        log global
        mode    tcp
        retries 3
        option  dontlognull
        timeout connect 1000
        timeout client  150000
        timeout server  150000
        option srvtcpka
        option clitcpka

listen sss
        bind 0.0.0.0:9878
        server v 1.2.3.4:443

timeout 对于时间的单位默认是 ms 可用的单位如下

  - us : microseconds. 1 microsecond = 1/1000000 second
  - ms : milliseconds. 1 millisecond = 1/1000 second. This is the default.
  - s  : seconds. 1s = 1000ms
  - m  : minutes. 1m = 60s = 60000ms
  - h  : hours.   1h = 60m = 3600s = 3600000ms
  - d  : days.    1d = 24h = 1440m = 86400s = 86400000ms

一个简单的配置文件如下

global
    pidfile     /var/run/haproxy.pid
    user        haproxy
    group       haproxy
    daemon

defaults
    mode                    tcp
    log                     global
    retries                 3
    option                  dontlognull
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 30000

frontend http-in
    mode http
    bind 0.0.0.0:1080
    option http-keep-alive
    default_backend  servers

backend servers
    option http-keep-alive
    server myserver 1.2.3.4:80 check maxconn 6000

转发 ssh 服务时,注意,需要将 timeout client timeout server 设置一个较大的时间,如120m 防止静置的时候ssh被断开

示例

global
    pidfile     /var/run/haproxy.pid
    user    nobody
    group       nobody
    ulimit-n  8000
    daemon

defaults
    mode                    tcp
    log                     global
    retries                 3
    option  dontlognull
    option srvtcpka
    option clitcpka
    option http-keep-alive
    timeout connect         10s
    timeout client          120m
    timeout server          120m
    maxconn                 30000

listen vpnssh
    bind 0.0.0.0:27897
    server v 192.243.115.210:27897 maxconn 2048
listen vpn6060
    bind 0.0.0.0:16060
    server v 192.243.115.210:6060 maxconn 2048
listen vpn8080
    bind 0.0.0.0:18080
    server v 192.243.115.210:8080 maxconn 2048
listen vpn19090
    bind 0.0.0.0:19090-19099
    server v 192.243.115.210 maxconn 2048

timeout http request :在客户端建立连接但不请求数据时,关闭客户端连接 timeout queue :等待最大时长 timeout connect: 定义haproxy将客户端请求转发至后端服务器所等待的超时时长 timeout client:客户端非活动状态的超时时长 timeout server:客户端与服务器端建立连接后,等待服务器端的超时时长, timeout http-keep-alive :定义保持连接的超时时长 timeout check:健康状态监测时的超时时间,过短会误判,过长资源消耗

八种负载算法

‘roundrobin’, 简单的轮询 ‘static-rr’, 根据权重 ‘leastconn’, 最少连接者先处理 ‘source’, 根据请求源IP ‘uri’, 根据请求的URI ‘url_param’, 根据请求的URl参数 ‘hdr(name)’ 根据HTTP请求头来锁定每一次HTTP请求 ‘rdp-cookie(name)’ 很据cookie(name)来锁定并哈希每一次TCP请求

长连接

KeepAlive 就是通常所称的长连接,KeepAlive带来的好处是可以减少tcp连接的开销,这对于短response body的请求效果更加明显。

HAProxy后端keepalive指的是在HAProxy服务完一次与后端的交互后,不关闭HAProxy和后端的连接,而是维护这个连接以备后续的请求复用。

HAProxy后端Keepalive 配置,启用HAProxy后端长连接需要配置如下

option http-pretend-keepalive
option srvtcpka
option clitcpka
option forwardfor

其中option forwardfor允许在转发请求到后端时加上X-Forwarded-For头部,可以不使用.

tcp 层的默认链接保持时间,一般默认为2个小时

cat /proc/sys/net/ipv4/tcp_keepalive_time

timeout clienttimeout server 设置的就是当没有数据传送时,最大空闲多少时间就关闭链接

https://serverfault.com/questions/589804/haproxy-configuration-for-rabbitmq/652326#652326

还有一个在应对高并发时通常都需要改的 ulimit -n 8192

ulimit -n 可以查看当前的

-st 是立即结束原有进程(SIGTERM,立即重启)

-sf 是原有进程执行完后退出(SIGUSR1,平滑重启)

重启HAProxy

# haproxy-reload
haproxy -f /etc/haproxy/haproxy.cfg -st $(cat /var/run/haproxy.pid)
# haproxy-hot-reload
haproxy -f /etc/haproxy/haproxy.cfg -sf $(cat /var/run/haproxy.pid)

/etc/rc.local(软连接到/etc/rc.d/rc.local)是开机后自动执行的脚本

可以加入haproxy -f /etc/haproxy/haproxy.cfg到其中实现开机启动.

配置文件参考 https://github.com/chenzhiwei/linux/tree/master/haproxy

一份haproxy加速ss

global
        pidfile   /var/run/haproxy.pid
        ulimit-n  15000

defaults
        log global
        mode    tcp
        retries 3
        option  dontlognull
        timeout connect 120s
        timeout client  120m
        timeout server  120m
        option srvtcpka
        option clitcpka

frontend ss-in
        bind *:80
        default_backend ss-out

backend ss-out
        server server1 208.81.202.x:443 maxconn 20480

可以直接使用listen,更加简洁的创建一个关联server

global
        pidfile   /var/run/haproxy.pid
        ulimit-n  15000
        user        nobody
        group       nobody
        daemon

defaults
        log global
        mode    tcp
        retries 3
        option  dontlognull
        timeout connect 120s
        timeout client  120m
        timeout server  120m
        option srvtcpka
        option clitcpka

listen sss
        bind 0.0.0.0:9878
        server v 192.243.x.x:1443 maxconn 2048

haproxy -D -f /etc/haproxy/haproxy.cfg启动,参数-D为goes daemon

参考 http://liaoph.com/haproxy-tutorial/

https://gist.github.com/SilverBut/32be4a41cbdc50dd3a02627738b2b9cb

升级glibc版本,最新发布 http://www.gnu.org/software/libc/

所有版本见http://mirror.hust.edu.cn/gnu/libc/

错误 libc.so.6: version GLIBC_2.14 not found 表明当前系统的glibc版本较低

strings libc.so.6 |grep GLIBC_可以查看当前系统支持的版本

wget http://mirror.hust.edu.cn/gnu/libc/glibc-2.19.tar.xz
tar Jxf glibc-2.19.tar.xz
cd glibc-2.19
mkdir build
cd build
../configure
make -j4 && make install

https://cnodejs.org/topic/56dc21f1502596633dc2c3dc 此编译需要较长时间

dog-tunnel端口映射

开启服务器端(须有外网IP)

dtunnel_lite -service 0.0.0.0:1234 -v -tcp -xor 121333 > /tmp/dog.log 2>&1 &

开启客户端(任意一台可联网的机器)

反向映射客户机22端口到服务器的30222端口,代理ssh建议使用tcp,pipe通道为1

dtunnel_lite -service 服务器端IP:1234 -v -action 127.0.0.1:22 -encrypt -tcp -xor 121333 -local 172.168.1.99:30222 -r > /tmp/dog.log 2>&1 &

可以使用客户端连接多个服务器,将22端口映射到多个服务器端.

crontab守护进程,每5分钟检查一次

*/5 * * * * sh /data/bin/connect.sh > /tmp/dog.log 2>&1

#!/bin/bash
echo "`date` start shell process ">> /tmp/connect.log
if test $( pgrep -f dtunnel_lite | wc -l ) -eq 0
then
    while true
    do
        echo "`date` dtunnel_lite process is starting...">> /tmp/connect.log
        touch /run/connect.lock
        dtunnel_lite -service x.x.x.x:1234 -v -action 127.0.0.1:22 -encrypt -tcp -xor 121333 -local 172.168.1.99:30222  -r
        echo "`date` dtunnel_lite process killed,todo restart ">> /tmp/connect.log
        sleep 5
    done
else
    touch /run/connect.lock
    echo "`date` dtunnel_lite process is already running ">> /tmp/connect.log
fi

先手动启动一次 sh /data/bin/connect.sh > /tmp/dog.log 2>&1 &

TCP 端口转发

https://boutell.com/rinetd/

https://boutell.com/rinetd/http/rinetd.tar.gz

Socat:

优点:支持 TCP/UDP 转发。缺点:不支持端口段(多个端口需要开启多个转发)

HaProxy:

优点:支持 TCP 转发,支持 端口段 转发。缺点:不支持 UDP 转发。

iptables:

优点:支持 TCP/UDP 转发,支持 端口段 转发。缺点:配置麻烦,容易出错。

socat 支持unixsocket转发

socat TCP4-LISTEN:15432,fork UNIX-CONNECT:/srv/mongodb-27017.sock

haproxy 用作缓存

https://github.com/jiangwenyuan/nuster/wiki/Performance-benchmark:-nuster-vs-nginx-vs-varnish