【问题标题】:How to handle multiple requests in PHP?如何在 PHP 中处理多个请求?
【发布时间】:2016-03-23 21:42:53
【问题描述】:

我正在使用下面的代码在 php 中制作一个简单的电报机器人:

$message = json_decode(file_get_contents('php://input'), true);
// if it's not a valid JSON return
if(is_null($message)) return;
$endpoint = "https://api.telegram.org/bot<token>/";

// make sure if text and chat_id is set into the payload
if(!isset($message["message"]["text"]) || !isset($message["message"]["chat"]["id"])) return;

// remove special characters, needed for the interpreter apparently
$text = $message["message"]["text"];
//$text = str_replace(["\r", "\n", "\t"], ' ', $text);
// saving chat_id for convenience
$chat_id = $message["message"]["chat"]["id"];

// show to the client that the bot is typing 
file_get_contents($endpoint."sendChatAction?chat_id=".$chat_id."&action=typing");
file_get_contents($endpoint."sendMessage?chat_id=".$chat_id."&text=hi");

但问题是同时响应多个请求。用户未实时收到响应(延迟)。 我确定最后一行会导致延迟并等待电报服务器的响应。 我怎么知道呢?

更新 我找到了这段代码,但它仍然有延迟:

$ch = curl_init();
    $curlConfig = array(
        CURLOPT_URL => 'https://api.telegram.org/bot<token>/sendMessage',
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true); 
    $curlConfig[CURLOPT_POSTFIELDS] = "chat_id=".$chat_id."&text='hi'";
    curl_setopt_array($ch, $curlConfig);
    $result = curl_exec($ch);
    curl_close($ch);

问题出在哪里?

【问题讨论】:

  • 按每一步计时。您只需在每个命令后记录一个时间戳。
  • @arkascha 谢谢。您能否进一步解释或给我一个 php 手册中的链接? :)
  • file_get_contents() 是一个阻塞调用。您正在编写同步代码。知道这对你来说可能是一个有用的开始:-)
  • @jimbo 谢谢。其实这不是我自己的代码。我在网上找到的;)

标签: php telegram-bot


【解决方案1】:

正如在 cmets 中所说,您可以使用简单的打印语句在每个命令之后输出(记录)时间戳。通过查看差异,您可以了解每个命令花费了多长时间。这应该足以识别简单函数中耗时的步骤。

另一种方法是使用分析器。 XDebug 有一个内置的。但你必须设置它,我怀疑这是否合理只是为了找出哪个步骤需要这么长时间......

然而在我看来最优雅的想法是在 php 中使用一个鲜为人知的功能:ticks ;-)

这允许注册一个“tick”函数一次,并在每个命令执行时自动输出一个tick。这使您不必弄乱您的代码。文档给出了一个很好的例子。

【讨论】:

    【解决方案2】:

    电报机器人以两种不同的方式工作:

    • 直接 https 请求(您必须设置 ssl 证书);
    • 长时间轮询请求(您的脚本会继续搜索更新)。

    在前一种情况下,您设置了一个 webhook,在后一种情况下,您不需要它,只需使用 getUpdates API 方法进行轮询。 好吧,您正在获取输入流,所以我猜您正在使用第一个推荐的方法,这比轮询更快,因为您收到实时请求并且您能够即时管理它。 Telegram 会向您发送带有一个或多个元素的 JSON,您必须在同一请求期间处理这些元素,以避免更多连续消息之间的延迟:

    // receives the request from telegram server
    $message = json_decode(file_get_contents('php://input'), true);
    
    // if it's not a valid JSON return
    if(is_null($message)) return;
    
    // check if data received doesn't contain telegram-side errors
    if (!$message["ok"]) { return; }
    
    // define remote endpoint
    $endpoint = "https://api.telegram.org/bot<token>/";
    
    // process each message contained in JSON request 
    foreach ($message["result"] as $request) {
    
        // make sure if text and chat_id is set into the payload
        if(!isset($request["message"]["text"]) || !isset($request["message"]["chat"]["id"])) return;
    
        // remove special characters, needed for the interpreter apparently
        $text = $request["message"]["text"];
        //$text = str_replace(["\r", "\n", "\t"], ' ', $text);
        // saving chat_id for convenience
        $chat_id = $request["message"]["chat"]["id"];
    
        // show to the client that the bot is typing 
        file_get_contents($endpoint."sendChatAction?chat_id=".$chat_id."&action=typing");
        file_get_contents($endpoint."sendMessage?chat_id=".$chat_id."&text=hi");
    
    }
    

    如果这样可以减少延迟,请告诉我,开发者愉快! :)

    【讨论】:

    • 感谢您提供详细信息;)我会对其进行测试并通知您。
    • 不知道为什么失败了。
    • 好的,我看到你的代码应该可以正常运行,那天 Telegram 很慢……现在问题解决了吗?
    • 是的。我正在使用 curl,它比 file_get 快得多;)非常感谢
    猜你喜欢
    • 2021-03-10
    • 1970-01-01
    • 2018-08-19
    • 2013-01-12
    • 2013-01-31
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多