介绍
laravel框架入门可参见(《laravel入门及技术指南》https://blog.youkuaiyun.com/yan_dk/article/details/117375890),laravel结合swoole,可以实现高性能Http服务,提升应用性能。hhxsv5/laravel-s是第三方的组件包,我们可以安装使用。可参见(《laravel之laravel-s组件技术指南》https://blog.youkuaiyun.com/yan_dk/article/details/117867961)
我们使用laravel-s组件,结合swoole,构建Redis连接池,在服务器并发请求redis压力增大是,利用连接池,缓存连接资源,避免频繁重新连接的资源消耗,减轻redis压力,提升Redis性能,避免服务器压力过大而缓慢或崩溃。
构建实现
环境配置
laravel框架及laravel-s的安装见介绍,不再多说。
我们需要安装redis,可以采用docker安装redis,配置环境文件.env,config/database.php
config/database.php中redis的连接池相关配置如下,红色的参数是扩展的,后面要用到
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'pool' => [
'size' => 10
],
'driver' => 'redis'
],
.env中配置redis的连接参数,不再细说。
建立连接池类
CoReis.php:redis连接池底层入口来,主要负责连接池初始化构造,还提供redis操作接口,抽象主控制类。需要在laravel框架的AppServiceProvider中注册引入。
<?php
namespace App\pool\Core;
class CoRedis
{
/*
* 池
*/
protected $pool;
/*
* Redis连接
*/
private $redis;
public function __construct($pool)
{
$this->pool = $pool;
}
/**
* @return mixed
* 从连接池中取得连接
*/
public function connection()
{
return $this->pool->get();
}
/*
* 从池中取得连接给到Redis属性
*/
public function getRedis()
{
return $this->redis = $this->connection();
}
public function __call($name, $arguments)
{
// TODO: Implement __call() method.
if (!method_exists($this,$name)){
throw new \RuntimeException("{$name} Method doesn't exist!");
}
call_user_func("getRedis");
call_user_func_array([$this,$name],$arguments);
}
...
/*****************redis 操作函数*******************/
}
RedisPool.php:Redis连接池的环境参数初始化,构建连接池实例,使用了Swoole组件提供的RedisConfig、RedisPool,与CoReis类关联的实现类。
<?php
namespace App\pool\Redis;
use Swoole\Database\RedisPool as Pool;
use Swoole\Database\RedisConfig;
use Illuminate\Foundation\Application;
class RedisPool
{
/**
* @var Application
* laravel的应用
*/
protected $app;
/*
*获取Redis的配置
*/
protected $config;
/**
* @var
* 池
*/
protected $pool;
public function __construct(Application $app)
{
$this->app = $app;
$this->config = $app->make("config");
$this->init();
}
public function init()
{
$config = (new RedisConfig())
->withHost($this->config->get('database.redis.default.host'))
->withPort($this->config->get('database.redis.default.port'))
->withAuth($this->config->get('database.redis.default.password'));
$this->pool = new Pool($config,$this->config->get('database.redis.default.pool.size'));
}
public function get()
{
return $this->pool->get();
}
public function put($redis)
{
return $this->pool->put($redis);
}
}
Redis.php:从Redis连接池中获得连接,这里使用Swoole的协程、通道,高性能稳定可靠。
<?php
namespace App\pool;
use Swoole\Runtime;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
class Redis
{
public static function getDriver()
{
return app(app('config')->get("database.redis.default.driver"));
}
public static function __callStatic($name, $arguments)
{
// TODO: Implement __callStatic() method.
Runtime::enableCoroutine();
$chan = new Channel(1);
Coroutine::create(function () use ($chan,$name,$arguments){
$redis = self::getDriver();
$return = $redis->{$name}(...$arguments);
$chan->push($return);
return $chan->pop();
});
}
}
注册Redis连接池服务
将上述连接池构建实例,注册成应用的服务,框架启动时,启动这个连接池服务。
<?php
namespace App\Providers;
use App\pool\Core\CoRedis;
use App\pool\Redis\RedisPool;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//注册redis连接池
$this->app->singleton('redis',function (){
return new CoRedis(new RedisPool($this->app));
});
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
建立测试控制器
我们采用dingo组件控制器及路由
# php artisan make:controller Api/V1/ProductController
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ProductController extends Controller
{
//连接池
public function pool() {
app('redis')->set("name","test222");
$result =app('redis')->get("name");
return $result;
}
}
建立路由
建立路由配置文件 routes/api.php
$api = app('Dingo\Api\Routing\Router');
$api->version('v1',[
'middleware' => ['bindings'],
'namespace' => "App\Http\Controllers\Api\V1"
],function ($api){
$api->post("pool","ProductController@pool")->name("product.pool");
});
测试
服务器启动后,访问相关路由,我们使用postman测试工具,发送请求,如下
这样实现了,成功构建了redis连接池。