Swoole 协程Http使用
自己对照文档还有其他老哥的博客捣鼓了一些案例(游戏中的消息提示,任务完成等提示需要红点标明)
一、前期准备
使用docker,下载镜像,运行容器
#下载镜像 docker images phpswoole/swoole #运行容器 docker run -it -p 9501:9501 -p 9502:9502 -p 9503:9503 -v <本地目录绝对路径>:<docker路径> <docker image> /bin/bash
二、编写代码
Mysql连接池
<?php require_once "MysqlDB.php"; class MysqlPool { private static $instance; private $pool; private $config; private $pool_get_timeout; /** * 获取mysql进程池单例 * @param null $config * @return MysqlPool */ public static function getInstance($config = null) { if (empty(self::$instance)) { if (empty($config)) { throw new RuntimeException("mysql config is empty"); } self::$instance = new static($config); } return self::$instance; } public function __construct($config) { if (empty($this->pool)) { $this->config = $config; $this->pool = new \Swoole\Coroutine\Channel($config['pool_size']); for ($i = 0; $i < $config['pool_size']; $i++) { \go(function () use ($config) { $mysql = new MysqlDB(); $res = $mysql->connect($config['mysql']); if ($res === false) { throw new RuntimeException("Failed to connect mysql server"); } else { $this->pool->push($mysql); } }); } } } public function get() { if ($this->pool->length() > 0) { $mysql = $this->pool->pop($this->config['pool_get_timeout']); if (false === $mysql) { throw new RuntimeException("Pop mysql timeout"); } return $mysql; } else { throw new RuntimeException("Pool length <= 0"); } } public function recycle(MysqlDB $mysql) { $this->pool->push($mysql); } /** * 获取连接池长度 * @return mixed */ public function getPoolSize() { return $this->pool->length(); } }
MysqlDB.sql
<?php class MysqlDB{ private $connection; public function connect($config) { $connection = new \Swoole\Coroutine\MySQL(); $res = $connection->connect($config); if ($res === false) { throw new RuntimeException($connection->connect_error, $connection->errno); } else { $this->connection = $connection; } return $res; } public function query($sql){ $result = $this->connection->query($sql); return $result; }}
协程风格的Http服务
<?php require_once "MysqlPool.php"; require_once "FacilityService.php"; require_once "TaskServer.php"; require_once "common.php"; \Co\run(function () { $server = new \Co\Http\Server("0.0.0.0", 9090, false); $pool = MysqlPool::getInstance([ 'pool_size' => 5, 'pool_get_timeout' => 1, 'timeout' => 1, 'charset' => 'utf8', 'strict_type' => false, 'fetch_mode' => true, 'mysql' => [ 'host' => '127.0.0.1', 'port' => '3306', 'user' => 'root', 'password' => 'root', 'database' => 'test', ] ]); $server->handle('/', function ($request, $response) use ($pool) { $mysql = $pool->get(); $a = FacilityService::coopConfig(1, $mysql); // $res = $mysql->query("select * from user limit 1"); // var_dump($a); $pool->recycle($mysql); $response->end("<h1>Test</h1>"); }); $server->handle('/test', function ($request, $response) use ($pool) { $user_id = $request->post['user_id']; //集市---买 $channel_market = new \Swoole\Coroutine\Channel(1); go(function () use ($user_id, $pool, $channel_market) { $mysql = $pool->get(); //集市---买 $buy_data = $mysql->query("select * from `market_system` where user_id={$user_id} and is_view = 0 limit 1"); $channel_market->push(['buy_page' => empty($buy_data) ? 0 : 1]); //归还线程 $pool->recycle($mysql); }); $buy_page = $channel_market->pop(); //任务---任务 $channel = new \Swoole\Coroutine\Channel(1); go(function () use ($user_id, $pool, $channel) { $mysql = $pool->get(); $task_list = $mysql->query("SELECT `ut`.`id`,`ut`.`task_id`,`t`.`type`,`t`.`need_value`,`t`.`name`,`t`.`award_type`,`t`.`award`,`ut`.`status` FROM `user_tasks` `ut` LEFT JOIN .tasks `t` ON `ut`.`task_id`=t.id and t.is_shelf = 1 WHERE `ut`.`status` IN (1,2) AND `ut`.`user_id` = {$user_id} ORDER BY `ut`.`id` ASC"); foreach ($task_list as $v) { if ($v['status'] == 2) { $channel->push(['task_page' => 1]); break; } elseif ($v['status'] == 1) {//未完成 检查状态 $status = TaskServer::checkTaskFinish($this->_userId, $v, $mysql); if ($status) { $mysql->query("Update `user_tasks` set status=2 where id={$v['id']}"); if (!$channel->isEmpty()) { $channel->push(['task_page' => 1]); } } } } //归还线程 $pool->recycle($mysql); }); $task_page = $channel->pop(); //任务---成就 $channel_achievement = new \Swoole\Coroutine\Channel(1); go(function () use ($pool, $user_id, $channel_achievement) { $mysql = $pool->get(); $achievement_list = $mysql->query("SELECT * FROM `user_achievement` `u` INNER JOIN .achievement `a` ON `u`.`achievement_id`=a.id and a.is_shelf = 1 WHERE `u`.`user_id` = {$user_id} AND `u`.`status` = 2 LIMIT 1"); $channel_achievement->push(['achievement_page' => empty($achievement_list) ? 0 : 1]); //归还线程 $pool->recycle($mysql); }); $achievement_page = $channel_achievement->pop(); //图鉴 $channel_map = new \Swoole\Coroutine\Channel(1); go(function () use ($pool, $user_id, $channel_map) { $mysql = $pool->get(); $map_list = $mysql->query("SELECT * FROM `user_chicken_varieties` WHERE `user_id`={$user_id} AND `is_get` = 1 limit 1"); $channel_map->push(['map_page' => empty($map_list) ? 0 : 1]); //归还线程 $pool->recycle($mysql); }); $channel_page = $channel_map->pop(); //设施---鸡窝 $channel_coop = new \Swoole\Coroutine\Channel(1); go(function () use ($pool, $user_id, $channel_coop) { $mysql = $pool->get(); $user_wallet = $mysql->query("SELECT * FROM `user_data` WHERE `user_id` = {$user_id} limit 1"); $chicken_coop = $mysql->query("SELECT * FROM `chicken_coop` WHERE `user_id` = {$user_id}"); $chicken_coop = reformArr($chicken_coop, 'position'); for ($x = 1; $x <= 8; $x++) { //未建造 if (!isset($chicken_coop[$x])) { if (count($chicken_coop) + 1 == $x && (count($chicken_coop) == 0 || $chicken_coop[$x - 1]['status'] != 6)) { $coop_config = FacilityService::coopConfig($x, $mysql); if ($user_wallet && $user_wallet[0]['gold'] >= $coop_config['unlock_gold']) { //有可解锁 $channel_coop->push(['coop_page' => empty($coop_page) ? 0 : 1]); break; } } } } //归还线程 $pool->recycle($mysql); }); $channel_coop = $channel_coop->pop(); $return = [ 'market' => [ 'buy_page' => $buy_page['buy_page'] ?? 0, 'sell_page' => 0, ], 'task' => [ 'task_page' => $task_page ?: 0, 'achievement_page' => $achievement_page['achievement_page'] ?? 0, ], 'facility' => [ 'coop_page' => $channel_coop['coop_page'] ?? 0, 'other_page' => 0, ], 'map' => [ 'map_page' => $channel_page['map_page'] ?? 0, ], ]; $response->end(json_encode($return)); }); $server->handle('/stop', function ($request, $response) use ($server) { $response->end("<h1>Stop</h1>"); $server->shutdown(); }); $server->start(); });
协程风格的Websocket客户端
<?php use Swoole\Coroutine; use Swoole\Coroutine\Http\Client; use function Swoole\Coroutine\run; run(function () { $client = new Client('127.0.0.1', 8081); $ret = $client->upgrade('/websocket'); if ($ret) { while(true) { fwrite(STDOUT,'请输入用户id:'); $param = fgets(STDIN); $client->push($param); var_dump($client->recv()); Coroutine::sleep(0.1); } } });
__EOF__

本文作者:Blizzard
本文链接:https://www.cnblogs.com/obeigong/p/16615461.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/obeigong/p/16615461.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)