代码库 https://gitee.com/chenx885/swoole.git
具体的业务逻辑,要自己去实现(这里的swoole版本是用的1.9.8 不是很高,没有用到携程)
swoole 核心代码
<?php
require_once 'redis.php';
require_once 'Mysql.php';
class Server {
private $serv;
private $connection_num = 20;//连接数量
private $connection_obj = []; //mysql对象
private $avil_connection_num = 20;//可用连接
//构造redis
public function InstRedis(){
$redis = new RedisCus();
$redis->connect(array('host' => '127.0.0.1', 'port' => 6379, 'pwd' =>""));
$redis->select_db(8);
return $redis;
}
//构造MySQL
public function InstMysql(){
$configArr=array("host"=>"127.0.0.1","port"=>"3306","user"=>"leadcommon","passwd"=>"YncvnTGEmq","dbname"=>"waiqu");
return new MMysql($configArr);
}
public function __construct() {
$this->serv = new swoole_server ( "0.0.0.0", 9501 );
$this->serv->set ( array (
'worker_num' => 2,
'daemonize' => false,
'max_request' => 10000,
'dispatch_mode' => 2,
'debug_mode' => 1,
'task_worker_num'=>200,
'log_file'=>'./err.log'
) );
//创建链接池
if($this->connection_num>0){
for($i=0;$i<$this->connection_num;$i++){
$this->connection_obj[] = $this->InstMysql();
}
}
$this->serv->on ( 'Start', array ($this,'onStart'));
//开始一个进程【多个实例化redis和mysql】
$this->serv->on('WorkerStart', function (swoole_server $serv,$worker_id){
//创建redis
$serv->redis=$this->InstRedis();
//$serv->mysql=$this->InstMysql();
});
$this->serv->on ( 'Connect', array ($this,'onConnect'));
$this->serv->on ( 'Receive', array ($this,'onReceive'));
$this->serv->on('Task',array($this,'onTask'));
$this->serv->on('Finish',array($this,'onFinish'));
$this->serv->on ( 'Close', array ($this,'onClose' ));
$this->serv->start ();
}
public function onStart($serv) {
echo " on Start\n";
}
public function onConnect($serv, $fd, $from_id) {
$serv->send ($fd,"connect success, hi {$fd}!" );
}
//接收参数,逻辑处理
public function onReceive(swoole_server $serv, $fd, $from_id, $data) {
$request = json_decode(trim($data), true);
if (!is_array($request)) {
$json=json_encode(array('type'=>'-1','msg'=>'参数错误'));
return $serv->send($fd,$json);
}
//判断token是否错误
$request['fd']=$fd;
$task_id = $serv->task($request);
$serv->send($fd, "分发任务,任务id为$task_id\n");
}
//任务
public function onTask(swoole_server $serv, $task_id, $from_id,$data){
$cmd=$data['cmd'];
$fd=$data['fd'];
switch ($cmd) {
case 1://进入房间
$this->entryRoom($serv,$fd,$from_id,$data);
break;
case 2: //开始游戏
$this->beginPlay($serv,$fd,$from_id,$data);
break;
case 3: //退出房间
$this->breakRoom($serv,$fd,$from_id,$data);
break;
default:
$serv->send ($fd,"cmd参数错误" );
break;
}
$timer=swoole_timer_tick(20000, function() use ($serv,$task_id, $data){
echo " 任务=$task_id ||20秒触发 timeout\n".json_encode($data)."\n";
});
swoole_timer_after(50000, function() use($serv,$task_id,$timer) {
echo '50秒清除';
swoole_timer_clear($timer);
});
//不能清除其他进程的定时器,只用于当前进程
// swoole_timer_clear($timer);
echo "Tasker进程接收到数据".$timer."|";
echo "#{$serv->worker_id}\tonTask: [PID={$serv->worker_pid}]: task_id=$task_id, data_len=".count($data).".".PHP_EOL;
$serv->finish($data);
}
//任务完成触发
public function onFinish(swoole_server $serv, $task_id, $data){
echo "Task#$task_id finished, data_len=".count($data).PHP_EOL;
}
//关闭
public function onClose($serv, $fd, $from_id) {
echo "Client {$fd} close connection\n";
}
//进入房间
public function entryRoom($serv,$fd,$from_id,$data){
$pdo=$this->beginConn();
if(!empty($data['room_id'])){
$room_id =$data['room_id'];
}
$user_token =$pdo->field('user_id,nickname')->where(array('user_id' =>547723))->select('hl_user');
$user_token['avil_connection_num']=$this->avil_connection_num;
$this->closeConn($pdo);
$this->sendMsg($serv,$fd,$user_token);
}
//准备开始时间
public function beginPlay($serv,$fd,$from_id,$data){
}
//发送消息
public function sendMsg($serv,$fd,$message){
$msg=json_encode($message);
$serv->send($fd,$msg);
}
//开始使用链接池
public function beginConn(){
//链接数
$pdo = array_pop($this->connection_obj);
//数量大于小于1 链接不能ping上,重新实例mysql
if($this->avil_connection_num<1 || ($pdo->pdo_ping($pdo) != true)){
$pdo= $this->InstMysql();
}
//可用连接数减1
$this->avil_connection_num --;
return $pdo;
}
//关闭链接池
public function closeConn($pdo){
array_push($this->connection_obj,$pdo);
$this->avil_connection_num ++;
}
}
// 启动服务器
$server = new Server ();
这里多个房间,一个房间有多个定时任务,要根据业务代码,自己来加
swoole_timer_after(),这个定时器很重要,根据业务逻辑比方type=1 触发一个定时任务,type=2触发一个定时任务。就可以实现了。
这个具体的稳定性和并发。还要去探究一下。