当前位置:网站首页>swoole TCP 分布式实现
swoole TCP 分布式实现
2022-06-29 15:28:00 【倾听岁月】
消息服务器使用socket,为避免服务器过载,单台只允许500个socket连接,当一台不够的时候,扩充消息服务器是必然,问题来了,如何让链接在不同消息服务器上的用户可以实现消息发送呢?
要实现消息互通就必须要让这些消息服务器本身能互通,想了两个方式,一种是消息服务器之间交叉链接,另一种是增加一个特殊的消息服务器,这个消息服务器不对外开放,只负责消息转发和推送。
下列测试不考虑防火墙等。仅测试可行性和效率。
测试环境
消息服务器
ip地址:192.168.0.201 端口:9501
ip地址:192.168.0.202 端口:9501
转发服务器
ip地址:192.168.0.203 端口:9501
公共缓存(redis)
ip地址:192.168.0.231 端口:6379
软件环境
centos 6.5 mini swoole php
流程说明
- client1(服务器1 - 用户user)可向client2(服务器2 - 用户user)或者其他client(服务器 - 用户user)发送消息,并接收其他client(服务器 - 用户user)发送的消息。
- Redis中保存client(服务器 - 用户user)连接的信息,给每个用户分配唯一的key,包括链接的哪台服务器,转发服务器定时检测消息服务器,如消息服务器挂掉,由转发服务器清理掉Redis已经挂掉的所有链接。
完整流程
- Client1给Client2发送一条消息
- Socket1接收到消息,根据key从Redis取出Client2的连接信息,连接在本机,直接推送给Client2,流程结束。
- 如果连接不在本机,把消息推送到转发服务器,由转发服务器把该消息推送给连接所在消息服务器,消息服务器接收消息,推送给Client2。
- 消息发送结束。
编程实现
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();
测试
注意开启顺序
- 开启转发服务器php proxy.php
- 分别开启socket服务器php server.php
- 开始测试,分别打开两个telnet,连接两个消息服务器,发送消息测试:
登陆
可以在转发服务器上看到两个消息服务器已经连接
基于强大的swoole扩展,让php高效的实现这些成为可能,目前消息服务器到转发服务器是长连接,转发服务器到消息服务器是短连接,存在性能瓶颈,也浪费了连接资源。下一步改造成长连接,消息服务器的client使用异步。
边栏推荐
- 服务器的数据库连不上了【服务已起、防火墙已关、端口已开、netlent 端口不通】
- 深入理解 Promise 之手把手教你写一版
- stlink故障修复
- postgresql源码学习(23)—— 事务日志④-日志组装
- Google 软件版本经历周期
- cmake学习-2
- LeetCode-234-回文链表
- Why MySQL chooses b+ tree to store indexes
- Abnormal logic reasoning problem of Huawei software test written test [2] Huawei hot interview problem
- 11.应用层数据传输格式/端口号-bite
猜你喜欢

12.UDP协议-bite

LeetCode-234-回文链表

明德扬XILINX-K7-325T/410T核心板数据手册

GWD:基于高斯Wasserstein距离的旋转目标检测 | ICML 2021

Unity C # basic review 26 - first acquaintance Commission (p447)

cmake学习-2

89.(cesium篇)cesium聚合图(自定义图片)

Unity C basic review 28 - delegation with return (p449)

Lumiprobe reactive dye - amino dye: cyanine 5 amine

分页sql(rownum、row_number、dense_rank、rank)
随机推荐
高分三号卫星(GF-3)简介
. Net program configuration file operation (INI, CFG, config)
Uncover the practice of Baidu intelligent test in the field of automatic test execution
three.js和高德地图结合引入obj格式模型-效果演示
Development and application of NFT chain Games: Six noteworthy NFT trends in 2022
Flink SQL task taskmanager memory settings
雷达的类型
无意发现的【TiDB缓存表】,竟能解决读写热点问题
动态监听DOM元素高度变化
el-table-column行按钮防重控制loading
深入理解 Promise 之手把手教你写一版
JS 会有变量提升和函数提升
Introduction to radar related contents
Taro 小程序开启wxml代码压缩
Excel中构建SQL语句
Lumiprobe deoxyribonucleic acid phosphate CpG 1000 solid carrier
List集合详细讲解
Basic composition of radar
Building SQL statements in Excel
MySQL为什么选择B+树存储索引