40

通过ProxySQL提升PHP/MySQL的性能

 5 years ago
source link: https://huoding.com/2018/07/09/678?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前些天我介绍了如何通过 Twemproxy 实现 Redis 连接池,进而提升 PHP/Redis 的性能。今天我要介绍一下 ProxySQL ,通过它可以实现 MySQL 连接池,进而提升 PHP/MySQL 的性能,实际上原理是差不多的,本来没必要再写一篇文章赘述,不过我在配置使用 ProxySQL 的过程中,遇到了一些小问题,感觉还是应该记录一下。

关于安装过程,官方 Wiki 里有详细描述。主要看配置文件 /etc/proxysql.cnf :

datadir="/var/lib/proxysql"

admin_variables=
{
	admin_credentials="admin:admin"
	mysql_ifaces="0.0.0.0:6032"
}

mysql_variables=
{
	threads=4
	max_connections=2048
	default_query_delay=0
	default_query_timeout=36000000
	have_compress=true
	poll_timeout=2000
	interfaces="/var/run/proxysql.sock"
	default_schema="information_schema"
	stacksize=1048576
	server_version="5.5.30"
	connect_timeout_server=3000
	monitor_username="monitor"
	monitor_password="monitor"
	monitor_history=600000
	monitor_connect_interval=60000
	monitor_ping_interval=10000
	monitor_read_only_interval=1500
	monitor_read_only_timeout=500
	ping_interval_server_msec=120000
	ping_timeout_server=500
	commands_stats=true
	sessions_sort=true
	connect_retries_on_failure=10
}

mysql_servers =
(
	{
		address="..."
		port=3306
	}
)

mysql_users:
(
	{
		username = "..."
		password = "..."
	}
)

最应该注意的是:ProxySQL 使用 SQLite 来保存配置信息,配置文件只在第一次启动的时候有效,后续都是从 SQLite 获取配置。如果你想强制使用配置文件,需要使用 initial 命令。更多信息可以参考: ProxySQL之安装及配置详解

首先,注意 admin_variables 里的 admin_credentials,缺省值是「admin:admin」,表示缺省用户名和密码都是 admin,还有 mysql_ifaces,其缺省值是「0.0.0.0:6032」,表示监听所有网络接口的 6032 端口,设想你有一个外网能访问的网络接口,那么恶意用户将能使用缺省的用户名密码进入到你的 admin 系统,所以不要用缺省的用户名和密码,也不要缺省监听外网接口,切记!切记!切记!

其次,注意 mysql_variables 里的 interfaces,因为 PHP 要通过本地的 Unix Domain Socket 来请求 ProxySQL 的连接池,所以 interfaces 不要使用 ip:port 的形式,而是设置成本地Unix Domain Socket 的形式,本例中设置为 /var/run/proxysql.sock,需要提醒的是很多人喜欢把 Socket 文件放到 /tmp 路径下,这不是一个好习惯,毕竟 /tmp 从名字上看就不像是一个良家妇女,大家都想弄两下,搞不好谁 rm 了一下就糟了。

最后,注意 mysql_variables 里的 monitor_username 和 monitor_password,它设置了监控用户的相关信息,以便 ProxySQL 随时掌握后端 MySQL 服务器的状态,一定要记得提前在后端 MySQL 服务器上创建相应的帐号,我一开始就没创建监控帐号,结果 ProxySQL 运行一段时间就没响应了,这是因为当 ProxySQL 不断用配置里的监控帐号和密码尝试去访问后端服务器的时候,会生成很多「Access denied for user ‘monitor’@’…’」的错误,当达到一定阈值,就会导致「Host ‘…’ is blocked because of many connection errors」,此时 ProxySQL 就无法响应请求了,必须在 MySQL 上「mysqladmin flush-hosts」才行。相关的日志信息可以在「SELECT * FROM monitor.mysql_server_ping_log」里查看到。

下面让我们压测看看性能怎么样,测试脚本 test.php 如下:

<?php

$host = '...';
$user = '...';
$password = '...';
$database = '...';
$charset = 'utf8mb4';
$socket = '/var/run/proxysql.sock';

$dsn = "mysql:dbname={$database};charset={$charset}";

if (empty($_GET['proxysql'])) {
    $dsn .= ";host={$host}";
} else {
    $dsn .= ';unix_socket={$socket}';
}

$dbh = new PDO($dsn, $user, $password);

$sql = 'SELECT * FROM foo LIMIT 10';

$value = $dbh->query($sql);

foreach ($value as $v) {
    var_dump($v);
}

?>

通过 ab 模拟一个高并发的场景,压测看看性能有没有提升:

shell> ab -k -n 10000 -c 100 "http://path/test.php?proxysql=0"
shell> ab -k -n 10000 -c 100 "http://path/test.php?proxysql=1"

最终,我在一台一般配置的服务器上,不通过 ProxySQL 得到了大约 1500 的 RPS,通过 ProxySQL 得到了大约 2000 的 RPS,也就是说,ProxySQL 带来了 25% 的性能提升。

有兴趣的推荐继续阅读: Utilizing ProxySQL for Connection Pooling in PHP ,还有: ProxySQL之连接复用(multiplexing)以及相关问题说明


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK