传统的nginx+FPM模式的PHP程序而言,每次请求FPM的worker都会连接一次mysql,然后请求结束便会断开连接。对于并发小的应用来说这不会有什么问题,但是对于高并发的应用来说,频繁建立连接Connect和销毁连接Close,数据库便会成为瓶颈,相信不少人也遇到过to many connection的mysql报错吧。
连接池采用的是长连接模式,会一直保持与MySQL的连接,用完后会重新放回连接池,从而节省了建立连接和断开连接的消耗,大大降低了系统IO的消耗,一定程度上提高了程序的并发性能。如果连接池空闲,就从连接池分配一个连接,否则,请求将被加入到等待队列中。
目前的laravel+swoole中使用连接池,只能使用原生的sql语句,查询构建器会失效
连接池仅在超大型应用中才有价值,连接池并没有提高sql的查询速度,连接池是用来保护数据库的,限制连接数,为了避免连接过多导致数据库崩溃,不是用来提升性能的
├─Provider --------- 服务提供者
│ ├─AppServiceProvider.php ------ 注册服务提供者
├─pool --------- 主目录
│ ├─Core
│ │ ├─MySQLPool.php ------ mysql操作类
│ ├─Database
│ │ ├─DBPool.php ------- DB连接池封装类
│ ├─DB.php ---------------- swoole一键协程封装
use App\pool\Core\MySQLPool;
use App\pool\Database\DbPool;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->bind('mysql_pool',function (){
return new MySQL(new DbPool($this->app));
});
}
<?php
namespace App\pool\Core;
class MySQLPool
{
/**
* @var
* 在实例化时获取到的连接池对象
*/
protected $pool;
public function __construct($pool)
{
$this->pool = $pool;
}
/**
* @return mixed
* 从连接池中获取连接
*/
public function connection()
{
return $this->pool->get();
}
/**
* 归还连接池
* @param $pdo
*/
public function put($pdo)
{
$this->pool->put($pdo);
}
/**
* 执行语句查询
* @param $sql
* @return string
*/
public function query($sql)
{
try{
$pdo = $this->connection();
$return = $pdo->query($sql)->fetch();
$this->put($pdo);
return $return;
}catch (\PDOException $e){
$this->put($pdo);
return $e->getMessage();
}
}
/**
* 执行语句操作
* @param $sql
* @return bool|string
*/
public function execute($sql)
{
try{
$pdo = $this->connection();
$pdo->exec($sql);
$this->put($pdo);
return true;
}catch (\PDOException $e){
$this->put($pdo);
return $e->getMessage();
}
}
}
<?php
namespace App\pool\Database;
use Illuminate\Foundation\Application;
use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;
class DbPool
{
protected $app;
protected $pool;
public function __construct(Application $app)
{
$this->app = $app;
$this->init();
}
public function init()
{
$cofig = (new PDOConfig)
->withHost(env('DB_HOST'))
->withPort(env('DB_PORT'))
->withDbname(env('DB_DATABASE'))
->withUsername(env('DB_USERNAME'))
->withPassword(env('DB_PASSWORD'));
$this->pool = new PDOPool($cofig,env('DB_SIZE'));
}
public function get($schema)
{
return $this->pool->get();
}
public function put($pdo,$schema)
{
$this->pool->put($pdo);
}
}
<?php
namespace App\pool;
use Swoole\Runtime;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
class DB
{
public static function getDriver()
{
return app('mysql_pool');
}
public static function __callStatic($name, $arguments)
{
//一键协程化
Runtime::enableCoroutine();
//设置一个容量为1的通道
$chan = new Channel(1);
创建一个新的协程
Coroutine::create(function () use ($chan,$name,$arguments){
$pdo = self::getDriver();
//执行mysql相关 操作
$return = $pdo->$name(...$arguments);
$chan->push($return);
});
return $chan->pop();
}
}
<?php
namespace App\Http\Controllers;
use App\pool\DB;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index(Request $request){
$sql = "insert into orders(id,user_id) values (64,3)";
#执行操作
$result = DB::execute($sql);
$sql = "select * from t where id = 1","users";
//执行查询
$data = DB::query($sql);
return response()->json($data);
}
}