众所周知,PHP的特点是开发效率高,适应当下多变的节奏,但是缺点也明显,就是不能常驻内存,跟数据库无法建立长连接,I/O开销和频繁实例化成为PHP性能的瓶颈。
Swoole是C语言编写的高性能网络通信引擎,诞生之初就是来解决PHP的性能问题,提供了异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。
Swoole
2.0版本增加了对协程(Coroutine)的支持,可以已同步的方式编写代码,底层自动进行协程调度,转变为异步IO。解决了传统异步编程嵌套回调的问题。
不过因为PHP默认在程序结束时销毁内存,一些扩展就没有清理,同时安装Swoole会导致内存泄漏和一些其他兼容性问题。
一 安装
下载源代码包,在虚拟机进入目录,执行命令进行编译和安装,注意要php-5.3.10以上版本。
wget https://github.com/swoole/swoole-src/archive/v4.5.2.tar.gz
tar -zxvf swoole-src-4.5.2.tar.gz
cd swoole-src-4.5.2
phpize
./configure
make && make install
在/etc/php.d/新建文件swoole.ini,写入extension=swoole.so
重启apache
二 基类
<?php
namespace Kcloze\Jobs\Command;
use Symfony\Component\Console\Input\InputArgument;
use Kcloze\Jobs\Utils;
use Kcloze\Jobs\Process;
class AppCommand extends Command
{
protected static $defaultName = 'app';
public function __construct(array $config)
{
parent::__construct($config);
}
protected function configure()
{
$this->setDescription('manager swoole-jobs ');
$this->addArgument('name', InputArgument::REQUIRED, 'Who do you want to start swoole-jobs?');
}
protected function start($work)
{
Utils::log(['subtype' => 'running','param'=>['work'=>$work], 'message' => 'swoole-jobs is starting...']);
$this->output->writeln('swoole-jobs is starting...');
$process = new Process($work);
$process->start();
}
protected function restart($work)
{
Utils::log(['subtype' => 'running','param'=>['work'=>$work], 'message' => 'swoole-jobs is restarting...']);
$this->output->writeln('swoole-jobs is restarting...');
$this->stop($work);
sleep(3);
$this->start($work);
}
protected function stop($work)
{
Utils::log(['subtype' => 'running','param'=>['work'=>$work], 'message' => 'swoole-jobs is stopping...']);
$this->output->writeln('swoole-jobs is stopping...');
$this->sendSignal(SIGUSR1,$work);
}
protected function status($work)
{
$this->sendSignal(SIGUSR2,$work);
}
protected function exit($work)
{
Utils::log(['subtype' => 'running','param'=>['work'=>$work], 'message' => 'swoole-jobs is exiting...']);
$this->output->writeln('swoole-jobs is exiting...');
$this->sendSignal(SIGTERM,$work);
}
}
三 使用
<?php
namespace Kcloze\Jobs\Jobs\coupon;
use lib\Log;
use bll\coupon\CouponBll;
class CouponDeal
{
private static $bllObj;
/**
* 获取BLL对象单例
* @param $bllName
* @return object
*/
private static function getInstance($bllName)
{
if(empty(self::$bllObj[$bllName]) || !(self::$bllObj[$bllName] instanceof $bllName))
{
self::$bllObj[$bllName] = new $bllName();
}
return self::$bllObj[$bllName];
}
/**
* @brief 回调方法
* @param $data 消息
* @return mixed
*/
public function dealCoupon($data)
{
$aRes = ['status'=>0];
$oCouponBll = self::getInstance('bll\newbll\coupon\CouponBll');
//TODO 处理优惠券,考虑后面会有多种类型的优惠券
switch($data['type']){
case '100':
$aRes = $oCouponBll->dealAutoCoupon($data);
break;
}
//日志
Log::info([
'type' => 'coupon_deal',
'call_file' => __FILE__,
'call_function' => __FUNCTION__,
'param' => $data,
'return' => $aRes,
'message' => 'deal coupon'
]);
$msg = 'consume auto coupon mq message fail';
return $aRes;
}
}
四 设置定时任务
. /etc/profile
umask 000
CURDIR=/www/lib/swoolejobs/bin
PHP=/usr/bin/php
cd $CURDIR
procNum=$(ps -ef | grep swoole-jobs.php | grep -v grep | wc -l)
if [ "$procNum" -lt "1" ];then
if [ $1 == "check" ];then
list="internal "
for i in $list;
do
master_num=$(ps -aux | grep swoole-jobs_${i}_master| grep -v grep | wc -l)
worker_num=$(ps -aux | grep swoole-jobs_${i}_worker| grep -v grep | wc -l)
if [ $master_num -eq 0 ];then
$PHP $CURDIR/swoole-jobs.php restart -w $i
$PHP $CURDIR/swoole-jobs.php restartlog $i
elif [ $worker_num -eq 0 ];then
$PHP $CURDIR/swoole-jobs.php exit -w $i
$PHP $CURDIR/swoole-jobs.php start -w $i
$PHP $CURDIR/swoole-jobs.php restartlog $i
fi
done
else
$PHP $CURDIR/swoole-jobs.php $1 -w $2
fi
fi
五 命令
在虚拟机开启:
sh swoolejobs.sh check
查看进程:
./swoolejobs.sh stop
停止进程:
ps axu | grep swoole
以上就是Swoole在工作中的应用。