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 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   bilzzard  阅读(95)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示