Swoole 初学者第一问:这样使用 go 函数对吗?

新手上路,请多包涵

题目描述

系统中有一批活动,本程序的目的是获取活动的缓存,然后判断缓存格式是否正确。

题目来源及自己的思路

所有功能都是基于现有的 API 接口来实现的,基本思路:

  1. 先登录,获取 Token,后面的接口都需要使用,使用的是 Guzzle 客户端,同步的方式
  2. 获取活动总数,因为获取活动记录的接口是分页的,没有办法一次获取到全部的活动信息,根据总数进行分页查询
  3. 分页获取活动记录,每页 10 条记录,大概几百页
  4. 循环获取每个活动的缓存,并判断和缓存规则是否一致,如果不一致则发送钉钉群通知;

如果按照普通 PHP 程序的写法,就按照上面的逻辑写就可以了,问题就是进行一次完整的检测时间比较长,例如有 1000 个活动,分页请求活动数据需要 100 次请求,请求缓存又需要 1000 次请求,总共 1100 次,如果每次请求 500ms,也需要 550 秒。

使用 Swoole 的协程模式,我的思路是先通过同步的方式获取到 Tokne 和活动总数,然后开启协程分页请求活动数据,然后循环每次请求的活动数据,再在协程中请求缓存数据。

相关代码

<?php

require 'vendor/autoload.php';

require 'PromotionRecords.php';
require 'PromotionTotal.php';
require 'PromotionCache.php';
require 'Code.php';
require 'Login.php';
require 'Ding.php';

const SERVER = 'http://promotion.abc.com';

// 登录,获取 Token
$login = new Login();
$token = $login->getToken();

if (empty($token)) { // 登录失败
    var_dump('Login Failed.');

    exit();
}

// 获取活动总数
$promotionTotal  = new PromotionTotal($token);
$promotion_total = $promotionTotal->getPromotionTotal();
// 分页获取活动记录
// 总页数
$page_total = ceil($promotion_total / Code::PAGE_COUNT);

for ($page = 1; $page <= $page_total; $page++) {
    go(function () use ($token, $page) {
        $promotionRecords  = new PromotionRecords($token);
        $promotion_records = $promotionRecords->getPromotionRecords($page, Code::PAGE_COUNT);

        // 循环活动验证缓存格式是否正确
        foreach ($promotion_records as $promotion_record) {
            $promotion_record_id      = $promotion_record['promotion_id'];
            $promotion_record_type_id = $promotion_record['promotion_type_id'];

            go(function () use ($token, $promotion_record_id, $promotion_record_type_id) {
                $promotion_cache = new PromotionCache($token);
                $error = $promotion_cache->verify($promotion_record_id, $promotion_record_type_id);
                if (! empty($error)) {
                    // 初始化钉钉消息发送类
                    $ding = new Ding();
                    $ding->send($promotion_record_id, $error);
                }
            });
        }
    });
}

你期待的结果是什么?实际看到的错误信息又是什么?

我想知道这种思路是否正确,还有更好的方法吗?

阅读 4.2k
2 个回答

把go当成 新开一个线程理解

用的是同步的guzzle的话, 开协程也是没有用的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题