You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP通过SSH连接MySQL的实现方案及相关问题咨询

问题解答

问题1:PHP连接字符串写法与每次建立SSH隧道的问题

1.1 PHP连接字符串实现方式

由于服务器B仅开放22端口,MySQL的3306端口无法直接访问,需先建立SSH隧道,再通过本地转发端口连接MySQL,以下是两种常见实现:

方式一:用exec临时建隧道(适合低并发场景)

先在服务器A执行端口转发命令,再用PHP连接本地端口:

// 建立SSH隧道:将本地3307端口转发到服务器B的3306端口
exec('ssh -f -N -L 3307:127.0.0.1:3306 usera@192.168.0.102');

// PDO连接MySQL示例
try {
    $pdo = new PDO(
        'mysql:host=127.0.0.1;port=3307;dbname=DBtest;charset=utf8mb4',
        'usera',
        '123456',
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
    // 执行查询逻辑
    $stmt = $pdo->query('SELECT * FROM your_table');
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    die('连接或查询失败: ' . $e->getMessage());
}

方式二:用proc_open管理隧道进程(更可控)

直接在PHP中管理SSH进程,避免残留僵尸进程:

// 定义SSH隧道命令
$cmd = 'ssh -N -L 3307:127.0.0.1:3306 usera@192.168.0.102';
$descriptorspec = [
    0 => ['pipe', 'r'], // 标准输入
    1 => ['pipe', 'w'], // 标准输出
    2 => ['pipe', 'w']  // 标准错误
];
// 启动SSH进程
$process = proc_open($cmd, $descriptorspec, $pipes);

if (is_resource($process)) {
    // 连接MySQL
    $pdo = new PDO(
        'mysql:host=127.0.0.1;port=3307;dbname=DBtest;charset=utf8mb4',
        'usera',
        '123456'
    );
    // 业务逻辑...
    
    // 关闭隧道进程
    proc_close($process);
} else {
    die('SSH隧道建立失败');
}

1.2 每次建立SSH隧道的问题

  • 性能开销大:每次连接都要完成SSH握手(密钥交换、身份验证等),会显著增加数据库操作的响应时间,高并发场景下延迟会被放大。
  • 资源占用过高:每个隧道对应一个SSH进程,高并发时会产生大量进程,消耗服务器A的CPU、内存资源,甚至触发服务器B的SSH连接数限制。
  • 稳定性差:PHP脚本异常退出时,可能残留僵尸SSH进程,长期积累会占用大量系统资源。

问题2:持久SSH连接的实现与断开重连

2.1 建立持久SSH连接的可行性

完全可以通过autossh工具在两台服务器间建立持久化SSH端口转发,PHP只需连接本地转发端口即可,无需每次建隧道。

配置步骤:

  1. 在服务器A配置SSH免密登录到服务器B:
# 生成密钥对(一路回车即可)
ssh-keygen -t rsa
# 将公钥复制到服务器B
ssh-copy-id usera@192.168.0.102
  1. 安装autossh(以CentOS为例):
yum install autossh -y
  1. 启动持久化SSH隧道:
# 将服务器A的3307端口持久转发到服务器B的3306端口
autossh -M 20000 -f -N -L 3307:127.0.0.1:3306 usera@192.168.0.102

参数说明:

  • -M 20000:指定autossh的监控端口,用于检测连接状态
  • -f:后台运行
  • -N:仅做端口转发,不执行远程命令
  1. 设置开机自启(可选):
    编辑/etc/rc.local,添加上述autossh命令,确保服务器重启后自动建立隧道。

2.2 PHP的简化连接字符串

此时PHP连接逻辑和连接本地MySQL完全一致:

try {
    $pdo = new PDO(
        'mysql:host=127.0.0.1;port=3307;dbname=DBtest;charset=utf8mb4',
        'usera',
        '123456',
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
    // 业务逻辑...
} catch (PDOException $e) {
    die('连接失败: ' . $e->getMessage());
}

2.3 意外断开的自动重连

autossh本身具备连接监控和自动重连机制:

  • 通过-M端口定期检测SSH连接状态,发现断开会自动重建隧道。
  • 可配合SSH存活检测参数增强稳定性,编辑服务器A的~/.ssh/config文件:
Host 192.168.0.102
    ServerAliveInterval 30
    ServerAliveCountMax 3

参数说明:

  • ServerAliveInterval 30:每30秒向服务器B发送一次存活检测包
  • ServerAliveCountMax 3:连续3次检测无响应则断开连接,触发autossh重连

网络波动导致连接断开时,autossh会自动恢复隧道,PHP无需额外修改,正常连接本地转发端口即可。


内容的提问来源于stack exchange,提问作者TMCHAN2020

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:02:23