phpwebsocket性能,消息服务器websocket⾼并发分布式
swoole架构思路
消息服务器使⽤socket,为避免服务器过载,单台只允许500个socket连接,当⼀台不够的时候,扩充消息服务器是必然,问题来了,如何让链接在不同消息服务器上的⽤户可以实现消息发送呢?
要实现消息互通就必须要让这些消息服务器本⾝能互通,想了两个⽅式,⼀种是消息服务器之间交叉链接,另⼀种是增加⼀个特殊的消息服务器,这个消息服务器不对外开放,只负责消息转发和推送。
下列测试不考虑防⽕墙等。仅测试可⾏性和效率。
测试环境
消息服务器
192.168.0.201 9501 192.168.0.202 9501
转发服务器
192.168.0.203 9501
公共缓存
Redis 192.168.0.231 6379
软件环境
centos 6.5 mini swoole php
流程说明:
client1可向client2或者其他client发送消息,并接收其他client发送的消息.
Redis中保存client连接的信息,给每个⽤户分配唯⼀的key,包括链接的哪台服务器,转发服务器定时检测消息服务器,如消息服务器挂掉,由转发服务器清理掉Redis已经挂掉的所有链接。
完整的流程:
1.Client1给Client2发送⼀条消息
2.Socket1接收到消息,根据key从Redis取出Client2的连接信息,连接在本机,直接推送给Client2,流程结束。
3.如果连接不在本机,把消息推送到转发服务器,由转发服务器把该消息推送给连接所在消息服务器,消息服务器接收消息,推送给
Client2。
4.消息发送结束。
编码实现
【1】socket
服务器上创建⼀个server.php,内容如下:
$serv = new swoole_server("0.0.0.0", 9501);
//redis
$redis = new \Redis();
$redis->connect("192.168.0.231", 6379);
//client
$proxy = new swoole_client(SWOOLE_TCP | SWOOLE_KEEP);
$proxy->connect("192.168.0.203", 9501);
$serv->on('start', function($serv) {
echo "";
websocket和socket});
$serv->on('connect', function ($serv, $fd) {
});
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
global $redis;
$data = (array) json_decode($data);
$cmd = $data['cmd'];
switch ($cmd) {
case "login"://登陆
//保存连接信息
$save = array(
'fd' => $fd,
'socket_ip' => "192.168.0.201"
);
$redis->set($data['name'], serialize($save));
break;
case "chat":
$recv = unserialize($redis->get($data['recv']));
if ($recv['socket_ip'] != "192.168.0.201") {
//需要转发
$data['cmd'] = 'forward';
$data['recv_ip'] = $recv['socket_ip'];
$serv->task(json_encode($data));
} else {
//直接发送
$serv->send($recv['fd'], "{$data['send']}给您发了消息:{$data['content']}"); }
break;
case "forward"://接收转发消息
$recv = unserialize($redis->get($data['recv']));
$serv->send($recv['fd'], "{$data['send']}给您发了消息:{$data['content']}");
break;
}
//$serv->send($fd, 'Swoole: ' . $data);
});
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
global $proxy;
$proxy->send($data);
});
$serv->on('finish', function ($serv, $task_id, $data) {
});
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
$serv->set(array('task_worker_num' => 4));
$serv->start();
【2】socket
上只需把ip变更⼀下即可。192.168.0.201变更为192.168.0.202.
【主控制分发服务器】Proxy
在转发服务器上建⽴脚本proxy.php,内容如下:
$serv = new swoole_server("0.0.0.0", 9501); //服务端
$serv->on('start', function($serv) {
echo "";
});
$serv->on('connect', function ($serv, $fd) {
});
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
global $redis;
$serv->task($data);
});
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
$forward = (array) json_decode($data);
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); $client->connect($forward['recv_ip'], 9501);
unset($forward['recv_ip']);
$client->send(json_encode($forward));
$client->close();
});
$serv->on('finish', function ($serv, $task_id, $data) {
});
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
$serv->set(array('task_worker_num' => 4));
$serv->start();
测试
注意开启顺序
1.开启转发服务器php proxy.php
2.分别开启socket服务器php server.php
可以在转发服务器上看到两个消息服务器已经连接
3.开始测试,分别打开两个telnet,连接两个消息服务器,发送消息测试:
登陆
基于强⼤的swoole扩展,让php⾼效的实现这些成为可能,⽬前消息服务器到转发服务器是长连接,转发服务器到消息服务器是短连接,存在性能瓶颈,也浪费了连接资源。下⼀步改造成长连接,消息服务器的client使⽤异步。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论