[attach]1348[/attach]
问题一、如上图,本地服务器 B需要接收来自客户端client A的数据,然后将数据处理以后再发送给云服务器 C,C端处理数据以后再将处理的数据发送给B,B通过可以再次处理,发送给一个或者多个A端,
这三点直接都是长连接,请问使用gateway可以做到么,如果可以做到需要怎么配置,C端使用gateway没有问题,就是B端的gateway应该怎么使用,
问题二、B端使用两个服务器做分布式部署,请问可以在两个服务器中运行register,gateWay以及businessWorker,当一个服务器出现问题的时候,另一个服务器可以立即顶上,请问这种可是实施么,如果可以,怎么实施
谢谢大神
问题1,在B上可以利用asyncTcpConnection发起连接连到C,可以asyncTcpConnection发起连接然后可以send数据,asyncTcpConnection的onMessage里处理C的返回。
问题2、分布式部署故障迁移一般只需要考虑客户端到gateway部分,businessworker服务器故障了会自动下线,不影响业务。但是gateway前面最好加一层负载均衡,比如lvs
好的,我现在试一下,谢谢大神@1
在$con->onMessage方法中调用Gateway::sendToClient()方法没有作用。请问大神这样使用有什么特殊的地方要规避的么?谢谢大神
Gateway框架的Events.php为何不能如下使用:
在$con->onMessage方法中调用Gateway::sendToClient()方法没有作用。请问大神这样使用有什么特殊的地方要规避的么?谢谢大神
你要自己打日志,看下运行到哪里了,没有现场环境很难定位哪里问题的。
比如$con->onMessage可能根本就没运行,自然就发不出去。另外gateway不用初始化,看下手册用法
$con->onMessage是运行了的,我在这个方法中打印数据是打印出来了的,但是调用Gateway::sendToClient(),A客户端没有反应
[attach]1358[/attach]
下面是输出图
[attach]1359[/attach]
你这个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导致以为没有发出去
谢谢大神的指教,这个问题解决了,原因可能是使用全局的时候,$client_id再下次触发onMessage的时候为NULL了,解决方法就是在使用的时候不需要全局,写这个方法的时候use($client_id)就没问题了,麻烦大神了。我把可以使用的代码写在最后面,以供其他人使用。
在打印Gateway类库中发现$address的地址为0.0.0.0:,发送的数据$gateway_data中的connection_id会变成null,如下图所示。
[attach]1360[/attach]
作为客户端,ip地址不能为0.0.0.0
下面的代码是B端的代码,C端的代码无需太大改变<?php
/**
*/
/**
*/
//declare(ticks=1);
use \GatewayWorker\Lib\Gateway;
use \Workerman\Connection\AsyncTcpConnection;
/**
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');
}
}
/**
*/
public static function onConnect($client_id)
{
// 向当前client_id发送数据
Gateway::sendToClient($client_id, "Hello $client_id\r\n");
// 向所有人发送
Gateway::sendToAll("$client_id login\r\n");
}
/**
*/
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();
}
/**
*/
public static function onClose($client_id)
{
// 向所有人发送
GateWay::sendToAll("$client_id logout\r\n");
}
}
不对,你这样是$con是一个全局的类,但是每次有请求就重置了$con->onMessage逻辑里的$client_id,最终发送会发送给最后一个,也达不到你要的效果。
保持长连接后要每个消息都传递属于哪个client_id的处理结果,否则会混乱
<?php
/**
*/
/**
*/
//declare(ticks=1);
use \GatewayWorker\Lib\Gateway;
use \Workerman\Connection\AsyncTcpConnection;
/**
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();
}
}
/**
*/
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 mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
$con = self::getCon();
$con->send(json_encode());
}
/**
*/
public static function onClose($client_id)
{
// 向所有人发送
GateWay::sendToAll("$client_id logout\r\n");
}
}
我又增加一台服务器当作A客户端,测试了以下,发现没有出现您说的这个问题,两个客户端都可以正确的接收到各个不同的传递过来的数据。谢谢大神给了另一种思路。我换您这个思路试一下。