[精选] 静态化API是什么?用Swoole如何去实现呢?
2022-07-25PHP
静态化API可以理解成把一些接口的数据存储在服务器本地。常用的是存成json文件,也可以是放在swoole的table中,总之是用户不从数据库直接读取数据,而是从本地加载的方式来大幅提高性能,因为很多系统的性能瓶颈是在数据库的位置。
原始的方法 – 读取mysql
public function lists0(){
$condition = [];
if(!empty($this->params['cat_id'])){
$condition['cat_id'] = intval($this->params['cat_id']);
}
try {
$videoModel = new VideoModel();
$data = $videoModel->getVideoData($condition, $this->params['page'], $this->params['size']);
} catch (\Exception $e) {
//$e->getMessage();
return $this->writeJson(Status::CODE_BAD_REQUEST,"服务异常");
}
if(!empty($data['lists'])){
foreach ($data['lists'] as &$list){
$list['create_time'] = date("Ymd H:i:s",$list['create_time']);
$list['video_duration'] = gmstrftime("%H:%M:%S",$list["video_duration"]);
}
}
return $this->writeJson(Status::CODE_OK,'OK',$data);
}
<?php
/**
* Created by bingxiong.
* Date: 12/23/19
* Time: 1:20 AM
* Description:
*/
namespace App\Model;
use EasySwoole\Core\Component\Di;
class Base
{
public $db = "";
public function __construct()
{
if(empty($this->tableName)){
throw new \Exception("table error");
}
$db = Di::getInstance()->get("MYSQL");
if($db instanceof \MysqliDb){
$this->db = $db;
}else{
throw new \Exception("db error");
}
}
public function add($data){
if(empty($data) || !is_array($data)){
return false;
}
return $this->db->insert($this->tableName,$data);
}
}
方案一、方案二 使用easySwoole定时器以及contab的生成静态化API
/**
* 第二套方法 - 直接读取静态化json数据
* @return bool
*/
public function lists(){
$catId = !empty($this->params['cat_id']) ? intval($this->params['cat_id']) : 0;
$videoFile = EASYSWOOLE_ROOT."/webroot/video/json/".$catId.".json";
$videoData = is_file($videoFile) ? file_get_contents($videoFile) : [];
var_dump($videoData);
$videoData = !empty($videoData) ? json_decode($videoData,true) : [];
$count = count($videoData);
// var_dump($videoData);
return $this->writeJson(Status::CODE_OK,'OK',$this->getPagingData($count,$videoData));
}
/**
* 获取分页信息
* @param $count
* @param $data
* @return array
*/
public function getPagingData($count, $data){
$totalPage = ceil($count / $this->params['size']);
$data = $data ?? [];
$data = array_slice($data, $this->params['from'], $this->params['size']);
return [
'total_page' => $totalPage,
'page_size' => $this->params['page'],
'count' => intval($count),
'list' => $data
];
}
$cacheVideoObj = new VideoCache();
// 使用cronTab处理定时任务
// 这里是闭包 要use $cacheVideoObj之后才能获取,实例化不放在function中是为了防止每次都实例化浪费资源
CronTab::getInstance()
->addRule("test_bing_crontab", '*/1 * * * *', function () use($cacheVideoObj) {
$cacheVideoObj->setIndexVideo();
});
// easySwoole自带定时器
$register->add(EventRegister::onWorkerStart,function (\swoole_server $server,$workerId)use($cacheVideoObj){
//让第一个进程去执行,否则每个进程都会执行
if($workerId == 0){
Timer::loop(1000*2,function ()use ($cacheVideoObj){
$cacheVideoObj->setIndexVideo();
});
}
});
方案三 Swoole table的解决方案
public function lists(){
$catId = !empty($this->params['cat_id']) ? intval($this->params['cat_id']) : 0;
$videoFile = EASYSWOOLE_ROOT."/webroot/video/json/".$catId.".json";
// 第三套方案 table
$videoData = Cache::getInstance()->get("index_video_data_cat_id".$catId);
$videoData = !empty($videoData) ? $videoData : [];
$count = count($videoData);;
return $this->writeJson(Status::CODE_OK,'OK',$this->getPagingData($count,$videoData));
}
<?php
/**
* Created by bingxiong.
* Date: 12/23/19
* Time: 10:13 PM
* Description:
*/
namespace App\Lib\Cache;
use App\Model\Video as VideoModel;
use EasySwoole\Config;
use EasySwoole\Core\Component\Cache\Cache;
class Video
{
public function setIndexVideo()
{
$catIds = array_keys(Config::getInstance()->getConf("category"));
array_unshift($catIds, 0);
$modelObj = new VideoModel();
foreach ($catIds as $catId) {
$condition = [];
if (!empty($catId)) {
$condition['cat_id'] = $catId;
}
try {
$data = $modelObj->getVideoCacheData($condition);
} catch (\Exception $e) {
// 短信报警
$data = [];
}
if (empty($data)) {
}
foreach ($data as &$list) {
$list['create_time'] = date("Ymd H:i:s", $list["create_time"]);
$list["video_duration"] = gmstrftime("%H:%M:%s", $list["video_duration"]);
}
// 由于table存在内存所以重启服务器时数据会丢失,要将配置中的PERSISTENT_TIME设置为1进行落盘操作
Cache::getInstance()->set("index_video_data_cat_id".$catId, $data);
}
}
}
'PERSISTENT_TIME'=>1//如果需要定时数据落地,请设置对应的时间周期,单位为秒
否则会在重启服务的时候没有数据,因为每次启动的时候swoole table会清空,要等到定时去set table的时候才会有数据,因此要开启数据落盘,这样会生成两个文件:
Screen-Shot-2018-12-24-at-3.57.35-PM-1024x487.png
方案四 Redis
/**
* 重写set方法 处理一下失效时间以及数组转json
* @param $key
* @param $value
* @param $time
* @return bool|string
*/
public function set($key, $value, $time){
if(empty($key)){
return '';
}
if(is_array($value)){
$value = json_encode($value);
}
if(!$time){
return $this->redis->set($key,$value);
}
return $this->redis->setex($key, $time, $value);
}
Di::getInstance()->get("REDIS")->set("index_video_data_cat_id".$catId, $data);
public function lists(){
$catId = !empty($this->params['cat_id']) ? intval($this->params['cat_id']) : 0;
//redis
$videoData = Di::getInstance()->get("REDIS")->get("index_video_data_cat_id".$catId);
$videoData = !empty($videoData) ? json_decode($videoData,true) : [];
$count = count($videoData);
return $this->writeJson(Status::CODE_OK,'OK',$this->getPagingData($count,$videoData));
}
<?php
/**
* Created by bingxiong.
* Date: 12/23/19
* Time: 10:13 PM
* Description:
*/
namespace App\Lib\Cache;
use App\Model\Video as VideoModel;
use EasySwoole\Config;
use EasySwoole\Core\Component\Cache\Cache;
use EasySwoole\Core\Component\Di;
use EasySwoole\Core\Http\Message\Status;
class Video
{
/**
* 设置静态API的方法
* @throws \Exception
*/
public function setIndexVideo()
{
$catIds = array_keys(Config::getInstance()->getConf("category"));
array_unshift($catIds, 0);
// 获取配置
try {
$cacheType = Config::getInstance()->getConf("base.indexCacheType");
} catch (\Exception $e) {
return $this->writeJson(Status::CODE_BAD_REQUEST,"请求失败");
}
$modelObj = new VideoModel();
foreach ($catIds as $catId) {
$condition = [];
if (!empty($catId)) {
$condition['cat_id'] = $catId;
}
try {
$data = $modelObj->getVideoCacheData($condition);
} catch (\Exception $e) {
// 短信报警
$data = [];
}
if (empty($data)) {
}
foreach ($data as &$list) {
$list['create_time'] = date("Ymd H:i:s", $list["create_time"]);
$list["video_duration"] = gmstrftime("%H:%M:%s", $list["video_duration"]);
}
switch ($cacheType) {
case 'file':
$res = file_put_contents($this->getVideoCatIdFile($catId), json_encode($data));
break;
case 'table':
$res = Cache::getInstance()->set($this->getCatKey($catId), $data);
break;
case 'redis':
$res = Di::getInstance()->get("REDIS")->set($this->getCatKey($catId), $data);
break;
default:
throw new \Exception("请求不合法");
break;
}
if(empty($res)){
// 记录日志
// 报警
}
}
}
/**
* 获取数据的方法
* @param $catId
* @return array|bool|mixed|null|string
* @throws \Exception
*/
public function getCache($catId){
$cacheType = Config::getInstance()->getConf("base.indexCacheType");
switch ($cacheType){
case 'file':
$videoFile = $this->getVideoCatIdFile($catId);
$videoData = is_file($videoFile) ? file_get_contents($videoFile) : [];
$videoData = !empty($videoData) ? json_decode($videoData,true) : [];
break;
case 'table':
$videoData = Cache::getInstance()->get($this->getCatKey($catId));
$videoData = !empty($videoData) ? $videoData : [];
break;
case 'redis':
$videoData = Di::getInstance()->get("REDIS")->get($this->getCatKey($catId));
$videoData = !empty($videoData) ? json_decode($videoData,true) : [];
break;
default:
throw new \Exception("请求不合法");
break;
}
return $videoData;
}
public function getVideoCatIdFile($catId = 0){
return EASYSWOOLE_ROOT . "/webroot/video/json/" . $catId . ".json";
}
public function getCatKey($catId = 0){
return "index_video_data_cat_id".$catId;
}
}
<?php
/**
* Created by bingxiong.
* Date: 12/24/19
* Time: 5:12 PM
* Description:
*/
return [
"indexCacheType" => "redis" // redis file table
];
public function lists(){
$catId = !empty($this->params['cat_id']) ? intval($this->params['cat_id']) : 0;
$videoData = (new VideoCache())->getCache($catId);
$count = count($videoData);
return $this->writeJson(Status::CODE_OK,'OK',$this->getPagingData($count,$videoData));
}
很赞哦! ()