前言:纯自己研究的简单结合方式,项目中单个的用过,没一起用过
大佬可以直接对我指指点点
有的自己写的,有的百度大佬们的贡献
交流学习做笔记的作用
客户端
// 抽奖 高并发客户端业务处理
public function ClientPush($request Request){
$uid = $request->post('uid'); // 用户ID
$activity_id = $request->post('activity_id'); // 活动ID
// 获取转盘活动 详情
$activityInfo = getActivityInfo::get($activity_id);
// redis 队列处理
$redis = New Redis();
$redis->connect('127.0.0.1',6397,30); // 服务器IP 端口号 连接时间
$activity_ranks = "activity_".$activity_id; // 使用结束记得释放掉对应健名
// 如果队列长度未超过限制数量 经行相应业务逻辑
if ($redis->llen($activity_ranks) < $activityInfo['num']) {
// 插入到列表的尾部
$redis->rPush($activity_ranks, $uid);
/**
* 则进行对应业务逻辑
* 抽奖结果,用户ID 传给服务端处理
* $activity_res // 抽奖结果
*/
self::ClientPs($activity_res,$uid);
}else{ // 如果队列长度大于限制数量
// 则经行对应业务逻辑
}
}
public static function ClientPs($activity_res,$uid){
//swoole客户端连接服务端,项目进程处理
//swoole客户端,通过TCP协议连接
$client=new \Swoole\Client(SWOOLE_SOCK_TCP);
//设置异步任务的工作进程数量
$client->set(array(
'buffer_output_size' => 128 * 1024 *1024, // 128m字节
));
$client->connect('127.0.0.1','9501',-1);
if(!$client->isConnected()){
//连接不成功
//echo "连接服务失败,错误类型为:".$client->errCode.PHP_EOL;
$data = array(
'result' => 'false',
'message' => "连接服务失败,错误类型为:".$client->errCode.PHP_EOL
);
echo json_encode($data);
die;
}
//发送数据 数据传输已通过队列
$data = [
'activity_res' => $activity_res,
'uid' => $uid,
];
$client->send(json_encode($data)); // 传输的数据,必须为字符串格式
//接收服务端的数据 服务端send发送的数据
$res = $client->recv();
$client->close(); // 关闭连 接
}
服务端
public function SwooleTcp(){
$serv = new \Swoole\Server("127.0.0.1", 9501); // TCP服务器
//设置异步任务的工作进程数量
$serv->set(array(
'worker_num' => 1, //一般设置为服务器CPU数的1-4倍
'daemonize' => 1, //以守护进程执行
'max_request' => 10000,//最大连接数
'dispatch_mode' => 2,
'task_worker_num' => 4, //task进程的数量
"task_ipc_mode " => 3, //使用消息队列通信,并设置为争抢模式
"log_file" => "/web/log/swoole.log" ,//所有的输出都会写到日志中
));
//此回调函数在worker进程中执行
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
//已经获取到数据,返回让客户端关闭连接
$serv->send($fd, 'true');
//因为TCP的连接一次传输的数据最大值默认为2M,可以提供修改,但是由于项目处理的数据非常大,
//所以这里使用redis的队列来进行传值;这里可以使用轮询队列数据方式,也可以通过客户端请求
//投递异步任务
$task_id = $serv->task($data); // 直接将数据添加到人物列表
});
//处理异步任务(此回调函数在task进程中执行)
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
//统一通过json字符串的形式进行传参
$datas = json_decode($data,true);
$activity_info = $datas['activity_ranks']; // 结果
$uid = $datas['uid']; // 用户ID
/**
* 执行数据库操作
* 我的想法是最好在经行库存修改的时候加个乐观锁
*/
//返回任务执行的结果
$serv->finish("OK");
});
//处理异步任务的结果(此回调函数在worker进程中执行)
$serv->on('finish', function ($serv, $task_id, $data) {
//当异步任务执行完毕后的操作,可以进行通知服务端,或是修改状态等
});
$serv->start();
}