ThinkPHP项目数据库连接池配置

wen PHP项目 4

本文目录导读:

ThinkPHP项目数据库连接池配置

  1. ThinkPHP 6.0+ 原生连接池配置
  2. 使用 Swoole 实现连接池
  3. Swoole 协程连接池配置
  4. 多数据库连接池配置
  5. 使用示例
  6. 注意事项
  7. 性能优化建议

在ThinkPHP中配置数据库连接池需要根据不同的使用场景来选择方案,以下是详细的配置指南:

ThinkPHP 6.0+ 原生连接池配置

基础配置(config/database.php)

<?php
return [
    // 默认使用的数据库连接配置
    'default' => env('database.driver', 'mysql'),
    // 自定义时间查询规则
    'time_query_rule' => [],
    // 自动写入时间戳字段
    'auto_timestamp' => true,
    // 时间字段取出后的默认时间格式
    'datetime_format' => 'Y-m-d H:i:s',
    // 数据库连接配置信息
    'connections' => [
        'mysql' => [
            // 数据库类型
            'type' => 'mysql',
            // 服务器地址
            'hostname' => env('database.hostname', '127.0.0.1'),
            // 数据库名
            'database' => env('database.database', ''),
            // 用户名
            'username' => env('database.username', 'root'),
            // 密码
            'password' => env('database.password', ''),
            // 端口
            'hostport' => env('database.hostport', '3306'),
            // 数据库连接参数
            'params' => [
                // 连接超时时间
                \PDO::ATTR_TIMEOUT => 5,
                // 持久连接
                \PDO::ATTR_PERSISTENT => true,
                // 错误模式
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
            ],
            // 数据库编码默认采用utf8
            'charset' => 'utf8mb4',
            // 数据库表前缀
            'prefix' => '',
            // 断线重连
            'break_reconnect' => true,
            // 监听SQL
            'trigger_sql' => env('app_debug', false),
            // 开启字段缓存
            'fields_cache' => false,
        ],
    ],
];

使用 Swoole 实现连接池

安装扩展

composer require swoole/think-helper

配置 Swoole 连接池

创建 app/swoole/ConnectionPool.php:

<?php
namespace app\swoole;
use Swoole\Coroutine\Channel;
use think\db\ConnectionInterface;
class ConnectionPool
{
    protected $pool;
    protected $config;
    protected $maxConnections;
    protected $minConnections;
    public function __construct($config)
    {
        $this->config = $config;
        $this->maxConnections = $config['pool']['max_connections'] ?? 100;
        $this->minConnections = $config['pool']['min_connections'] ?? 10;
        $this->pool = new Channel($this->maxConnections);
        // 初始化连接池
        $this->initPool();
    }
    protected function initPool()
    {
        for ($i = 0; $i < $this->minConnections; $i++) {
            $this->pool->push($this->createConnection());
        }
    }
    protected function createConnection()
    {
        try {
            $pdo = new \PDO(
                "mysql:host={$this->config['hostname']};dbname={$this->config['database']};port={$this->config['hostport']}",
                $this->config['username'],
                $this->config['password'],
                [
                    \PDO::ATTR_PERSISTENT => true,
                    \PDO::ATTR_TIMEOUT => 5
                ]
            );
            return $pdo;
        } catch (\Exception $e) {
            throw new \Exception("数据库连接失败: " . $e->getMessage());
        }
    }
    public function getConnection()
    {
        if ($this->pool->isEmpty()) {
            if ($this->pool->length() < $this->maxConnections) {
                return $this->createConnection();
            }
            // 等待空闲连接
            return $this->pool->pop(10);
        }
        return $this->pool->pop(10);
    }
    public function releaseConnection($connection)
    {
        if ($connection !== null) {
            $this->pool->push($connection);
        }
    }
}

连接池管理器

创建 app/swoole/PoolManager.php:

<?php
namespace app\swoole;
class PoolManager
{
    protected static $instances = [];
    public static function getInstance($name = 'default')
    {
        if (!isset(self::$instances[$name])) {
            $config = config('database.connections.mysql');
            self::$instances[$name] = new ConnectionPool($config);
        }
        return self::$instances[$name];
    }
}

使用中间件

创建 app/middleware/ConnectionPoolMiddleware.php:

<?php
namespace app\middleware;
use app\swoole\PoolManager;
class ConnectionPoolMiddleware
{
    public function handle($request, \Closure $next)
    {
        // 获取连接
        $pool = PoolManager::getInstance();
        $connection = $pool->getConnection();
        // 保存到请求上下文
        app()->instance('db_connection', $connection);
        try {
            $response = $next($request);
            return $response;
        } finally {
            // 释放连接
            $pool->releaseConnection($connection);
        }
    }
}

Swoole 协程连接池配置

修改 config/swoole.php:

<?php
return [
    // Swoole 服务器设置
    'server' => [
        'host' => '0.0.0.0',
        'port' => 9501,
        'mode' => SWOOLE_PROCESS,
        'sock_type' => SWOOLE_SOCK_TCP,
    ],
    // 协程设置
    'coroutine' => [
        'enable' => true,
        'preload' => [],
    ],
    // 连接池设置
    'pool' => [
        'default' => [
            'type' => 'mysql',
            'max_connections' => 100,     // 最大连接数
            'min_connections' => 10,      // 最小连接数
            'wait_timeout' => 3,          // 获取连接等待时间(秒)
            'max_idle_time' => 3600,      // 最大空闲时间(秒)
            'idle_check_interval' => 60,  // 空闲检查间隔(秒)
        ],
    ],
];

多数据库连接池配置

<?php
return [
    'connections' => [
        'mysql' => [
            'type' => 'mysql',
            'hostname' => '127.0.0.1',
            'database' => 'test',
            'username' => 'root',
            'password' => '',
            'hostport' => '3306',
            'params' => [
                \PDO::ATTR_PERSISTENT => true,
            ],
            'prefix' => '',
            // 连接池配置
            'pool' => [
                'max_connections' => 50,
                'min_connections' => 5,
                'wait_timeout' => 3,
                'max_idle_time' => 600,
            ],
        ],
        'mysql_read' => [
            'type' => 'mysql',
            'hostname' => '127.0.0.1',
            'database' => 'test_read',
            'username' => 'root',
            'password' => '',
            'hostport' => '3306',
            'params' => [
                \PDO::ATTR_PERSISTENT => true,
            ],
            'prefix' => '',
            'pool' => [
                'max_connections' => 30,
                'min_connections' => 3,
                'wait_timeout' => 3,
                'max_idle_time' => 600,
            ],
        ],
    ],
];

使用示例

控制器中使用连接池

<?php
namespace app\controller;
use app\swoole\PoolManager;
use think\facade\Db;
class UserController
{
    public function getUsers()
    {
        // 使用连接池获取连接
        $pool = PoolManager::getInstance();
        $connection = $pool->getConnection();
        try {
            // 使用PDO连接执行查询
            $stmt = $connection->prepare("SELECT * FROM users WHERE status = ?");
            $stmt->execute([1]);
            $users = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            return json($users);
        } finally {
            // 释放连接回池
            $pool->releaseConnection($connection);
        }
    }
    public function normalQuery()
    {
        // 普通查询(自动使用连接池)
        $users = Db::name('users')
            ->where('status', 1)
            ->select();
        return json($users);
    }
}

命令行添加测试数据

<?php
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\swoole\PoolManager;
class PoolTest extends Command
{
    protected function configure()
    {
        $this->setName('pool:test')->setDescription('测试连接池');
    }
    protected function execute(Input $input, Output $output)
    {
        $pool = PoolManager::getInstance();
        // 并发测试
        $coroutines = [];
        for ($i = 0; $i < 100; $i++) {
            $coroutines[] = \Swoole\Coroutine::create(function () use ($pool, $i) {
                $connection = $pool->getConnection();
                try {
                    $stmt = $connection->query("SELECT SLEEP(0.1)");
                    $output->writeln("Coroutine {$i} completed");
                } finally {
                    $pool->releaseConnection($connection);
                }
            });
        }
        $output->writeln("测试完成");
    }
}

注意事项

  1. 连接池大小:根据服务器性能和应用负载合理设置
  2. 超时设置:合理设置获取连接的等待时间
  3. 错误处理:连接异常时要及时处理并重新创建
  4. 监控统计:建议添加连接池使用情况的监控

性能优化建议

  • 在高并发场景下,使用 Swoole 连接池效果最明显
  • 根据业务特点设置合理的连接池大小
  • 定期检查连接池的健康状态
  • 使用 Redis 缓存减少数据库压力

这样的配置可以显著提升数据库操作的性能,特别是在高并发场景下。

抱歉,评论功能暂时关闭!