getawaywoker的onMessage中写入post请求isOnline判断出现错误

wolegequ1993

设备连接后即立即判断是否在线

public static function onConnect($client_id) {
    $is_online = Gateway::isOnline($client_id);
     file_put_contents("log11.txt", "tcp notice    client_id=>" . $client_id."与服务器建立连接\r\n是否在线".$is_online."时间为".date('Y-m-d H:i:s',time())."\r\n", FILE_APPEND);
}```
当onMessage中不发送请求时   均判断正常
![图片](//www.workerman.net/upload/questions/20181220/990d220515c93d8413c12e64cad88000.jpg)
当onMessage中打开post请求代码 则出现刚刚 登录设备即不在线情况,   在onClosez中记录日志发现设备并未离线
```php
    /**
     * 当客户端发来消息时触发
     * @param int $client_id 连接id
     * @param mixed $message 具体消息
     */
    public static function onMessage($client_id, $message) {
        $message = bin2hex($message);
        $match = str_split($message,2);
        $message =  implode(' ', $match);
        $uid = str_replace('.', "_",$_SERVER).'_'.$_SERVER; 
        $order_info = array(
            'ip'=>$uid,
            'data'=>$message,
        );
        // $result = 
self::http_post('xxx.xxx.cn/WXAPI/Workerman/Charge_api',$order_info);
    }

     /**
   * 模拟post进行url请求
   * @param string $url
   * @param array $post_data
   */
  public static function http_post($url = '', $post_data = array()) {
      if (empty($url) || empty($post_data)) {
          return false;
      }

      $o = "";
      foreach ( $post_data as $k => $v ) 
      { 
          $o.= "$k=" . urlencode( $v ). "&" ;
      }
      $post_data = substr($o,0,-1);

      $postUrl = $url;
      $curlPost = $post_data;
      $ch = curl_init();//初始化curl
      curl_setopt($ch, CURLOPT_URL,$postUrl);//抓取指定网页
      curl_setopt($ch, CURLOPT_HEADER, 0);//设置header
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
      curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
      curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
      $data = curl_exec($ch);//运行curl
      curl_close($ch);

      return $data;
  }

图片

2961 4 0
4个回答

wolegequ1993

运行一会后则判断所有进入的连接都为不在线

  • 暂无评论
blogdaren

代码看上去似乎没有问题,建议你抓包看下是谁主动关闭了连接。

  • 暂无评论
walkor

linux服务器?阿里云?是否有加负载均衡?
onClose里记录日志到 log11.txt,有问题后再截图log11.txt内容。

  • wolegequ1993 2018-12-21

    windows服务器.........
    您的意思是被阻塞了么?
    我有单独记录连接和断开的日志 马上贴上来

wolegequ1993

[attach]1573[/attach]
 

  • wolegequ1993 2018-12-21

    如上 当刚刚建立连接时即判断为不在线,但是onclose事件在几十秒后才被触发

  • walkor 2018-12-21

    看起来应该是业务阻塞了,导致进程处理onConnect onClose事件延迟了。实际上连接确实断开了

  • wolegequ1993 2018-12-21

    @614:我的这个onclose时间不是业务阻塞引起的 是设备在N次未接到参数后即自动断开连接

  • blogdaren 2018-12-21

    @4902: 自动断开? 在N次没有接收到消息后,是服务端主动关闭设备连接还是客户端主动关闭了设备连接?

  • wolegequ1993 2018-12-23

    @614:客户端

  • blogdaren 2018-12-23

    @4902:
    1、问题原因找到了吗或者解决了吗?
    2、我模拟了针对API的各种超时以及业务阻塞的场景,均未能重现你说的这种情况。
    3、根据老大说的原因,onConnect、onClose事件可能延迟了,进程在此之前有大量的业务逻辑阻塞?
    4、建议你抓下包看下具体发生了什么,调试下 isOnline() 代码也可以。

  • wolegequ1993 2018-12-23

    我是php的初级工作者 可能有一些理解和描述并不正确,然后我跟您描述一下
    1.我们这是一个物联网项目,可类似理解为共享单车,设备(以下类比简称为车)会不间断的发送各种消息过来,包括登录签到,心跳,订单数据等,服务器需要回复这些请求.当登录签到或者心跳有三次没有回复时,车自动断开连接,重连
    2.因为按照gatewaywoker文档要求分离部署mvc和wokerman,而车是通过tcp方式连接,无法通过访问url下接口的方式发送数据给MVC,我在onmessage中使用curl将数据post将数据发送到MVC中等待返回数据,然后再将数据返回给车
    3.在发送给MVC的数据中有一些数据处理比较复杂,大概需要2-3秒的时间才能返回数据,当有一个请求post 出去等待返回数据的时候,其他的消息被阻塞了,比如车在第10秒发送了心跳的消息,而第30秒才轮到这个消息post到mvc中,当返回消息时车已经发送了3次心跳断开了连接,以此类推服务运行的时间越长,接到的数据就越延迟,而至于为什么onconnect接收消息也发生了延迟我就不太特别清楚了
    4.我在windows环境下跑的当时看了文档想通过start.php status看看什么情况的 结果只能linux下看好像,也可能是我不会用,最后我们起了一个java的服务接收数据发送给mvc解决了这个
    以上

  • wolegequ1993 2018-12-23

    @614:另外当时我做了一下尝试
    1.将数据放到redis中,然后循环读取队列消息发送到MVC中,onconnect中与onclose中连接与断开恢复正常,但是依然在post数据时因为阻塞的原因消息回复出现延迟,设备无法保持连接.
    2.使用了AsyncTcpConnection类进行异步请求,但是文档范例中并没有写怎么携带参数,可能我比较菜.......我通过拼接url的方式进行了get请求格式如下(www.xxx.com/Index/xxx?ip=xxxxx&data=xxxx),但是好像连AsyncTcpConnection的onConnect 都无法进入,具体什么情况忘记了
    3.使用了文档中http-client如上拼接url进行异步请求,一部分可以请求成功,有一部分数据进入到error区间,记录了$e但是看不懂...也放弃了
    然后项目确实着急就让同事搭了java的一套TCP
    今天其实又找了一段异步请求的代码,但是因为测试的车都连到了现在的JAVA上面赶项目也没办法进行测试,不过好像没办法这个没办法接到返回值,打算再用一下朋友推荐的Guzzle,虽然java的同事搞定了这部分,但是自己的问题其实没解决有点心里抓的慌.......
    以上

  • blogdaren 2018-12-24

    @4902:
    1、看了一下,明显的第3条这里就是业务阻塞的场景,正是因为阻塞,导致你说的服务端回复延迟,所以有些客户端事实上在此之前已经断开了。
    2、要是我的话,果断选择典型异步任务模型来搞,即使用 AsyncTcpConnection()将这些耗时的任务转发给后端的集群任务进程来处理。
    3、使用 AsyncTcpConnection 可以发送任何协议支持的数据,这个数据即send()函数的参数,自己拼接就行。

  • wolegequ1993 2018-12-24

    @614:大佬是否可以提供一个发送http post数据的AsyncTcpConnection简单例子代码呢? 我不太懂看了看也没拼出来

  • blogdaren 2018-12-25

    @4902: 这个官方就有现成的例子代码:http://doc.workerman.net/faq/async-task.html, 你要做的基于http post 的,只需启动一个 http woker即可,比如例子中 "任务进程服务端" 保持不变【除非你换用其他的协议】,将调用端的websocket woker 改为 http worker即可, 这样设备就可以: http post ---> http worker ---> proxy async ---> task worker

年代过于久远,无法发表回答
🔝