首页 » MySQL/TiDB/GoldenDB, 系统相关 » 注意:HAProxy可能限制MySQL的最大连接数

注意:HAProxy可能限制MySQL的最大连接数

MySQL架构中经常会遇到和keepalived、HAProxy中间件的组合,解决MySQL的高可用与负载均衡的需求, 但是会给数据库配置带来复杂性。如果没有把这些组件与MySQL级联配置,可能会出现一些意向不到的问题,了解HaProxy就变的重要,近期一个客户在这样的环境做压力测试时,MySQL数据库的max_connections最大链接数已调整到10000, 但一应用反馈链接报错,从数据库上看链接最大也就在2000左右,并且MySQL日志未出现报错,如达到连接最大限制, 并且在HAProxy配置文件中发现也有maxconn=20000的配置. 最后确认还是HaProxy的配置问题。

查看HAProxy版本

# haproxy -v
HA-Proxy version 1.5.14 2015/07/02

Note:
这个软件版本有点老。

创建一个shell测试连接创建

#!/bin/bash

# MySQL数据库连接信息
DB_HOST="localhost"
DB_PORT="3306"
DB_USER="your_username"
DB_PASSWORD="your_password"
DB_NAME="your_database_name"

# 循环创建2500个连接
for ((i=1; i<=2500; i++))
do
    # 创建一个后台进程执行MySQL连接命令
    (
        # 连接MySQL数据库并执行一条简单的查询语句
        mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASSWORD $DB_NAME -e "SELECT sleep(1000);"

        # 输出连接成功信息
        echo "Connection $i created."
    ) &
done
# 等待所有连接创建完成
wait

echo "All connections created."

这里尝试创建2500个连接,然后sleep 1000秒,会话保持。我们再从processlist数据库中检查连接。 以上脚本用chargpt一秒生成。 注意这里的IP我们使用HAPROXY中的VIP和直连数据库Listen的IP方式,对比问题是在MYSQL还是HAProxy.

测试结果

1, 使用haproxy连接的脚本,创建到2000后,仿佛出现等待,不再创建,数据库查看仅保持在2000的进程
2, 使用MySQL直接连接的脚本,可以创建完所有连接,突破2000进程限制。

这意味着,问题没有在测试的client,也没有在db server,而是在HAProxy端。

操作系统可能影响
1,nopfile限制

# su - mysql
There was 1 failed login attempt since the last successful login.
su: cannot open session: Permission denied

# vi /etc/security/limits.conf
mysql soft nofile 65535
mysql hard nofile 65535

2, nproc限制

如测试节点打开的进程过多,会提示 fork failed: Resource temporarily unavailable

# ps --no-headers auxwwwm | cut -f1 -d' ' | sort | uniq -c | sort -n
比较 /etc/security/limits.conf or /etc/security/limits.d/* 中配置的nproc参数 

# ps -eLf | wc -l
比较  kernel.pid_max 参数值

# vi /etc/security/limits.conf

mysql soft nproc 65535
mysql hard nproc 65535

echo 65535 > /proc/sys/kernel/pid_max

su - xx
ulimit -Hn

Note:
我们把haproxy,db server的相关参数都有检查和调整后,重启进程,问题依旧。

MySQL 最大进程

我们开始有提到当前Mysql的最大进程数,当前是10000, 当然这并不是一个随便想配置多大的参数,依赖于硬件资源。 
MYSQL> show variables like 'max_connections';

默认在5.7版本为151, 计算MAX_CONNECTIONS参数的建议是.
max_connections=(可用物理内存 - Global buffer)/ thread buffer

Global buffer=inndb_buffer_pool_size+ innodb_log_buffer_size+query_cache_size+key_buffer_size+temp_table_size

# 建议max connections值
mysql> SELECT ROUND(([可用内存大小MB]- (ROUND((@@innodb_buffer_pool_size + @@innodb_log_buffer_size + @@query_cache_size + @@tmp_table_size + @@key_buffer_size) / 1024 / 1024))) / (ROUND(@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@thread_stack + @@join_buffer_size + @@binlog_cache_size) / 1024 / 1024)) AS 'Possible Max Connections';

Note:
该参数是动态参数,如果超过限制会提示“Too many connections” error

HAProxy 最大连接
HAProxy参数

maxconn <number>

maxconn将每个进程的最大并发连接数设置为 <number>。 它相当于命令行ulimit参数“-n”。 当达到此限制时,代理将停止接受连接。 “ulimit-n”参数会根据该值自动调整。cat /proc/ID/limits。

nbproc <number>

当进入守护进程时创建 个进程。 这需要“守护进程”模式。 默认情况下,只创建一个进程,这是推荐的操作模式。 对于每个进程只能使用少量文件描述符的系统,可能需要分叉多个守护进程。

haproxy的配置文件

$ ps -ef|grep haproxy  
/etc/haproxy/haproxy.cfg 
$ vi xxx.cfg

global
    ...
    maxconn 2000 #[a]
    ...
defaults
    ...
    maxconn 3 #[b]
    ...
listen mysql_3307
    ...
    maxconn 12 #[c]     -- --[c]= db server 3 * [d]
    balance leastconn
    default-server port 9200 maxqueue 10 weight 10 maxconn 4 #[d]
    server db1 192.168.55.171 check
    server db2 192.168.55.172 check
    server db3 192.168.55.173 check   
listen mysql_3308
    ...
    default-server port 9200 maxqueue 10 weight 10 maxconn 5 #[e]
    server db1 192.168.55.171 check
    server db2 192.168.55.172 check backup #[f]

frontend mysg1-backend-3306
    bind xxx.xxx.xxx.xxx:3306
    default_backend mysg1-backend-3306

backend mysg1-backend-3306
   default-server port 9200 maxqueue 10 weight 10 maxconn 5 #[g]

Note:
HAProxy 有 3 种类型的最大连接数 (maxconn) – 全局、默认/侦听和默认server。 从上面的配置样例可以看到有多处配置了maxconn.
1, Global.maxconn [a] 允许连接到此 HAProxy 实例的并发连接总数。
2, defaults.maxconn [b]默认所有侦听器的最大连接值。如果此值高于 global.maxconn,则没有意义。
3, listen.maxconn [c] 相应侦听器允许的最大连接数。如果指定,侦听器优先于 defaults.maxconn。如果此值高于 global.maxconn,则没有意义。
4, listen.default-server.maxconn [d][e][g] 这是每个后端服务器一次可以接收的最大连接数。如果此值高于 listen.maxconn 或 defaults.maxconn,则没有意义。此值应小于或等于 MySQL 的max_connections变量。否则,您可能会耗尽与后端MySQL服务器的连接,尤其是当MySQL的超时变量配置低于HAProxy的超时时。

通过HAProxy stats page 图形界面监控HAProxy的连接使用情况,  这个案例就是我们在defalut和backend default server指定了maxconn 20000, 但依旧是只能创建2000个session ,在haproxy社区也有一个相同的问题Connections stopping after 2,000 connections, 这是我们就怀疑HAProxy对单个进程限制,如果突破这限制,可以增加多进程模式。


HAProxy多进程或多线程

有两种可能的方法可以让 HAProxy 在多个 CPU 内核上运行:
通过使用多进程模型,其中 HAProxy 自动启动多个单独的系统进程(方法自 HAProxy 版本 1.1.7 起可用)
通过使用多线程模型,其中 HAProxy 在单个进程中自动启动多个线程(方法自 HAProxy 版本 1.8 起可用)
传统的多进程方法目前实现了更好的性能,但新的多线程模型解决了通常与多进程配置相关的所有限制,对于喜欢易于管理而不是最大性能的早期采用者来说,肯定会很有趣。

nbproc
Creates processes when going daemon. This requires the "daemon"mode. By default, only one process is created, which is the recommended mode
of operation. For systems limited to small sets of file descriptors per process, it may be needed to fork multiple daemons. USING MULTIPLE PROCESSES
IS HARDER TO DEBUG AND IS REALLY DISCOURAGED. See also "daemon" and "nbthread".

nbthread
This setting is only available when support for threads was built in. It creates threads for each created processes. It means if HAProxy is
started in foreground, it only creates threads for the first process. See also "nbproc".

注:nbproc 指令已在 HAProxy 版本 2.5 中弃用并删除。
如果配置会日志提示

nbproc is not supported any more since HAProxy 2.5. Threads will automatically be used on multi-processor machines if available.

检查是多进程还是多线程
要检查 HAProxy 中的多线程支持,请运行 “haproxy -vv”。如果启用了多线程,您将在输出中看到”Built with multithreading support.”

对于多进程或多线程,On Linux 2.6 以后的内核,可以使用cpu-map,绑定到指定的CPU core上。更多 online doc, 但是注意多进程与多线程只能是二选一,不可以同时指定,否则也会提示
config : cannot enable multiple processes if multiple threads are configured. Please use either nbproc or nbthread but not both.

如下样例

global
nbproc 2
maxconn 150000
user root # haproxy
group root # haproxy
daemon
stats socket /var/run/haproxy.sock group haproxy mode 775

defaults
mode tcp
timeout connect 5000ms
timeout client 130s
timeout server 130s

frontend http-in
bind-process 2
bind *:80
mode http
maxconn 40000

经过我们多次测试发现每增加nbproc可以允许增加2000的session数,所在当配置nbproc为6后,通过haproxy可以创建mysql的连接数达到10000.

但是如上参数在haproxy 切换后参数文件会重置,导致nbproc参数丢失,可以使用下面的方法,增加到systemd 服务的启动参数中.

[root@haproxy_anbob ~]# haproxy -vv
HA-Proxy version 1.5.18 2016/05/10
Copyright 2000-2016 Willy Tarreau willy@haproxy.org

Build options :
TARGET = linux2628
CPU = generic
CC = gcc
CFLAGS = -O2 -g -fno-strict-aliasing -DTCP_USER_TIMEOUT=18
OPTIONS = USE_LINUX_TPROXY=1 USE_GETADDRINFO=1 USE_ZLIB=1 USE_REGPARM=1 USE_OPENSSL=1 USE_PCRE=1

Default settings :
maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200

Encrypted password support via crypt(3): yes
Built with zlib version : 1.2.7
Compression algorithms supported : identity, deflate, gzip
Built with OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
Running on OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports prefer-server-ciphers : yes
Built with PCRE version : 8.32 2012-11-30
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND

Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.

[root@haproxy_anbob ~]# systemctl status haproxy
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Thu xxxx 12:28:55 UTC; 27s ago
Process: 142 ExecStart=/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid $OPTIONS (code=exited, status=1/FAILURE)
Main PID: 142 (code=exited, status=1/FAILURE)
...


[root@haproxy_anbob ~]# cat /usr/lib/systemd/system/haproxy.service
修改 增加-N -n参数 [ -n <maxconn> ] [ -N <maxpconn> ]
Execstart=/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy/haproxy.pid  -N 20000 -n 20000 

[root@haproxy_anbob ~]# systemctl daemon-reload
[root@haproxy_anbob ~]# systemctl restart haproxy

总结:
对于haproxy 代理mysql的环境,注意haproxy与mysql的最大连接数据配置的结合, 及haproxy单进程限制,注意配置多进程,在新版本haproxy中nbproc已废弃, 可以使用多线程模式弥补一些多进程模式的限制。 对于参数文件被覆盖问题,通过配置到systemd service中增加参数解决。

Reference
https://severalnines.com/blog/haproxy-connections-vs-mysql-connections-what-you-should-know/

打赏

, , ,

对不起,这篇文章暂时关闭评论。