如何使用gateway同时既做客户端又做服务端

0

图片
问题一、如上图,本地服务器 B需要接收来自客户端client  A的数据,然后将数据处理以后再发送给云服务器 C,C端处理数据以后再将处理的数据发送给B,B通过可以再次处理,发送给一个或者多个A端,
这三点直接都是长连接,请问使用gateway可以做到么,如果可以做到需要怎么配置,C端使用gateway没有问题,就是B端的gateway应该怎么使用,
问题二、B端使用两个服务器做分布式部署,请问可以在两个服务器中运行register,gateWay以及businessWorker,当一个服务器出现问题的时候,另一个服务器可以立即顶上,请问这种可是实施么,如果可以,怎么实施
谢谢大神
 

已邀请:

walkor

赞同来自:

问题1,在B上可以利用asyncTcpConnection发起连接连到C,可以asyncTcpConnection发起连接然后可以send数据,asyncTcpConnection的onMessage里处理C的返回。
问题2、分布式部署故障迁移一般只需要考虑客户端到gateway部分,businessworker服务器故障了会自动下线,不影响业务。但是gateway前面最好加一层负载均衡,比如lvs

wokerman - 90年代

赞同来自:

Gateway框架的Events.php为何不能如下使用:


    /**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
$gate = new Gateway();
$con = new AsyncTcpConnection('tcp://192.168.1.107:8282');
echo json_encode($con);
$con -> onConnect = function ()use($con){
$con->send('this is from BBB \r\n');
};
$con->onMessage = function ($con,$msg)use($gate){
global $client_id;
_**$gate::sendToClient($client_id, "this is from CCC said $msg\r\n");**_ };
$con->connect();
}

在$con->onMessage方法中调用Gateway::sendToClient()方法没有作用。请问大神这样使用有什么特殊的地方要规避的么?谢谢大神

walkor

赞同来自:

你要自己打日志,看下运行到哪里了,没有现场环境很难定位哪里问题的。
比如$con->onMessage可能根本就没运行,自然就发不出去。另外gateway不用初始化,看下手册用法
 

wokerman - 90年代

赞同来自:

图片
下面是输出图


图片
 

walkor

赞同来自:

你这个client_id放到全局变量里了,这个变量有可能会被其它请求更改,所以达不到你要的效果。
public static function onMessage($client_id, $message)
{
$con = new AsyncTcpConnection('tcp://192.168.1.107:8282');
echo json_encode($con);
$con -> onConnect = function ($con){
$con->send('this is from BBB \r\n');
};
$con->onMessage = function ($con,$msg)use($client_id){
echo "send to $client_id\n";
var_export(Gateway::isOnline($client_id));
Gateway::sendToClient($client_id, "this is from CCC said $msg\r\n");
$con->close();
};
$con->connect();

另外记得及时关闭连接(最好加个定时器关闭),否则触发多少请求就建立多少个连接,当超过服务器限制会导致服务异常。
Gateway::isOnline($client_id)能排查是不是客户端连接断开了,断开了就肯定无法发到了。
另外也可以抓包看下服务端到底发过去没,有可能是客户端bug导致以为没有发出去
 

wokerman - 90年代

赞同来自:

在打印Gateway类库中发现$address的地址为0.0.0.0:,发送的数据$gateway_data中的connection_id会变成null,如下图所示。


图片
 

walkor

赞同来自:

作为客户端,ip地址不能为0.0.0.0

wokerman - 90年代

赞同来自:

下面的代码是B端的代码,C端的代码无需太大改变<?php
/**



  • This file is part of workerman.



  • Licensed under The MIT License

  • For full copyright and license information, please see the MIT-LICENSE.txt

  • Redistributions of files must retain the above copyright notice.



  • @author walkor<walkor@workerman.net>

  • @copyright walkor<walkor@workerman.net>

  • @link http://www.workerman.net/

  • @license http://www.opensource.org/licenses/mit-license.php MIT License
    */


/**



  • 用于检测业务代码死循环或者长时间阻塞等问题

  • 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload

  • 然后观察一段时间workerman.log看是否有process_timeout异常
    */
    //declare(ticks=1);


use \GatewayWorker\Lib\Gateway;
use \Workerman\Connection\AsyncTcpConnection;


/**



  • 主逻辑

  • 主要是处理 onConnect onMessage onClose 三个方法


  • onConnect 和 onClose 如果不需要可以不用实现并删除
    */
    class Events
    {
    private static $con = null;
    public static function getCon()
    {
    if(self::$con){
    return self::$con;
    }else{
    return new AsyncTcpConnection('ws://192.168.1.107:8282');
    }
    }
    /**



    • 当客户端连接时触发

    • 如果业务不需此回调可以删除onConnect



    • @param int $client_id 连接id
      */
      public static function onConnect($client_id)
      {
      // 向当前client_id发送数据
      Gateway::sendToClient($client_id, "Hello $client_id\r\n");
      // 向所有人发送
      Gateway::sendToAll("$client_id login\r\n");
      }


    /**



    • 当客户端发来消息时触发

    • @param int $client_id 连接id

    • @param mixed $message 具体消息
      */
      public static function onMessage($client_id, $message)
      {
      $con = self::getCon();
      $con -> onConnect = function ()use($con){
      $con->send('this is from BBB \r\n');
      };
      $con->onMessage = function ($con,$msg)use($client_id){
      Gateway::sendToClient($client_id, "this is from CCC said $msg\r\n");
      };
      $con->connect();


    }


    /**



    • 当用户断开连接时触发

    • @param int $client_id 连接id
      */
      public static function onClose($client_id)
      {
      // 向所有人发送
      GateWay::sendToAll("$client_id logout\r\n");
      }
      }



walkor

赞同来自:

不对,你这样是$con是一个全局的类,但是每次有请求就重置了$con->onMessage逻辑里的$client_id,最终发送会发送给最后一个,也达不到你要的效果。
保持长连接后要每个消息都传递属于哪个client_id的处理结果,否则会混乱
 
<?php
/**



  • This file is part of workerman.



  • Licensed under The MIT License

  • For full copyright and license information, please see the MIT-LICENSE.txt

  • Redistributions of files must retain the above copyright notice.



  • @author walkor<walkor@workerman.net>

  • @copyright walkor<walkor@workerman.net>

  • @link http://www.workerman.net/

  • @license http://www.opensource.org/licenses/mit-license.php MIT License
    */


/**



  • 用于检测业务代码死循环或者长时间阻塞等问题

  • 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload

  • 然后观察一段时间workerman.log看是否有process_timeout异常
    */
    //declare(ticks=1);


use \GatewayWorker\Lib\Gateway;
use \Workerman\Connection\AsyncTcpConnection;


/**



  • 主逻辑

  • 主要是处理 onConnect onMessage onClose 三个方法


  • onConnect 和 onClose 如果不需要可以不用实现并删除
    */
    class Events
    {
    public static $con = null;
    public static function getCon()
    {
    if(self::$con){
    return self::$con;
    }else{
    $con = new AsyncTcpConnection('ws://192.168.1.107:8282');
    // 这里要求8282端口必须回传client_id,告诉Events这个是哪个client_id的结果
    $con->onMessage = function ($con,$msg){
    $data = json_decode($msg, true);
    $client_id = $data;
    Gateway::sendToClient($client_id, "this is from CCC said $msg\r\n");
    };
    // 连接关闭了要把Events::$con 置空,否则消息永远发不出去
    $con->close = function($con){
    Events::$con = null;
    };
    $con->connect();
    }
    }
    /**



    • 当客户端连接时触发

    • 如果业务不需此回调可以删除onConnect



    • @param int $client_id 连接id
      */
      public static function onConnect($client_id)
      {
      // 向当前client_id发送数据
      Gateway::sendToClient($client_id, "Hello $client_id\r\n");
      // 向所有人发送
      Gateway::sendToAll("$client_id login\r\n");
      }


    /**



    • 当客户端发来消息时触发

    • @param int $client_id 连接id


    • @param mixed $message 具体消息
      */
      public static function onMessage($client_id, $message)
      {
      $con = self::getCon();


      $con->send(json_encode());
      }




    /**



    • 当用户断开连接时触发

    • @param int $client_id 连接id
      */
      public static function onClose($client_id)
      {
      // 向所有人发送
      GateWay::sendToAll("$client_id logout\r\n");
      }
      }



要回复问题请先登录注册