基于SWOOLE的分布式SOCKET消息服务器架构
2016-06-16 00:00
645 查看
消息服务器使用socket,为避免服务器过载,单台只允许500个socket连接,当一台不够的时候,扩充消息服务器是必然,问题来了,如何让链接在不同消息服务器上的用户可以实现消息发送呢?
要实现消息互通就必须要让这些消息服务器本身能互通,想了两个方式,一种是消息服务器之间交叉链接,另一种是增加一个特殊的消息服务器,这个消息服务器不对外开放,只负责消息转发和推送。
下列测试不考虑防火墙等。仅测试可行性和效率。
测试环境
消息服务器
转发服务器
公共缓存
软件环境
流程图
整个流程图如下:
流程图说明:
client1可向client2或者其他client发送消息,并接收其他client发送的消息.
Redis中保存client连接的信息,给每个用户分配唯一的key,包括链接的哪台服务器,转发服务器定时检测消息服务器,如消息服务器挂掉,由转发服务器清理掉Redis已经挂掉的所有链接。
完整的流程:
1.Client1给Client2发送一条消息
2.Socket1接收到消息,根据key从Redis取出Client2的连接信息,连接在本机,直接推送给Client2,流程结束。
3.如果连接不在本机,把消息推送到转发服务器,由转发服务器把该消息推送给连接所在消息服务器,消息服务器接收消息,推送给Client2。
4.消息发送结束。
编码实现
Socket
在socket1上创建一个server.php,内容如下:
在socket2上只需把ip变更一下即可。192.168.0.201变更为192.168.0.202.
Proxy
在转发服务器上建立脚本proxy.php,内容如下:
测试
注意开启顺序
1.开启转发服务器php proxy.php
2.分别开启socket服务器php server.php
可以在转发服务器上看到两个消息服务器已经连接
3.开始测试,分别打开两个telnet,连接两个消息服务器,发送消息测试:
登陆
发送消息测试
消息成功接收。
基于强大的swoole扩展,让php高效的实现这些成为可能,目前消息服务器到转发服务器是长连接,转发服务器到消息服务器是短连接,存在性能瓶颈,也浪费了连接资源。下一步改造成长连接,消息服务器的client使用异步。
要实现消息互通就必须要让这些消息服务器本身能互通,想了两个方式,一种是消息服务器之间交叉链接,另一种是增加一个特殊的消息服务器,这个消息服务器不对外开放,只负责消息转发和推送。
下列测试不考虑防火墙等。仅测试可行性和效率。
测试环境
消息服务器
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.消息发送结束。
编码实现
Socket
在socket1上创建一个server.php,内容如下:
<?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 "Service:Start..."; }); $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();
在socket2上只需把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 "Service:Start..."; }); $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使用异步。
相关文章推荐
- Swoole-1.7.22 版本已发布,修复PHP7相关问题
- PHP+swoole实现简单多人在线聊天群发
- 使用php+swoole对client数据实时更新(一)
- PHP框架Swoole定时器Timer特性分析
- php异步多线程swoole用法实例
- PHP的swoole扩展安装方法详细教程
- 初识PHP中的Swoole
- 基于Swoole扩展开发异步高性能的MySQL代理服务器
- 看到有网友说Node.js是支持多线程的,我在这里解释一下
- 回复 《吐槽swoole》
- PHP的swoole扩展安装方法详细教程
- 初识PHP中的Swoole
- 基于SWOOLE的分布式SOCKET消息服务器架构
- swoole教程第一节:进程管理模块(Process)-中(消息队列)
- 基于Swoole做Socket服务器开发探索与实现PHP代码热更新机制
- Ubuntu编译swoole时制定--enable-async-mysql的笔记
- 100多行PHP代码实现socks5代理服务器
- mac下swoole安装步骤
- ASF 基于Swoole开发的PHP App Server框架
- ESP Elasticsearch代理 (PHP Swoole)