workerman分布式部署

文档:http://doc2.workerman.net/326146

目标:

项目需要研发im聊天功能,若用户量逐渐增大,单服务器的部署方式恐怕无法满足,因此,考虑使用多服务器分布式部署共同支撑大量人群同时在线。

 

首先我们需要先了解运行原理,官方文档的解释是:

workerman分布式部署_第1张图片

1、Register、Gateway、BusinessWorker进程启动

2、Gateway、BusinessWorker进程启动后向Register服务进程发起长连接注册自己

3、Register服务收到Gateway的注册后,把所有Gateway的通讯地址保存在内存中

4、Register服务收到BusinessWorker的注册后,把内存中所有的Gateway的通讯地址发给BusinessWorker

5、BusinessWorker进程得到所有的Gateway内部通讯地址后尝试连接Gateway

6、如果运行过程中有新的Gateway服务注册到Register(一般是分布式部署加机器),则将新的Gateway内部通讯地址列表将广播给所有BusinessWorker,BusinessWorker收到后建立连接

7、如果有Gateway下线,则Register服务会收到通知,会将对应的内部通讯地址删除,然后广播新的内部通讯地址列表给所有BusinessWorker,BusinessWorker不再连接下线的Gateway

8、至此Gateway与BusinessWorker通过Register已经建立起长连接

9、客户端的事件及数据全部由Gateway转发给BusinessWorker处理,BusinessWorker默认调用Events.php中的onConnect onMessage onClose处理业务逻辑。

10、BusinessWorker的业务逻辑入口全部在Events.php中,包括onWorkerStart进程启动事件(进程事件)、onConnect连接事件(客户端事件)、onMessage消息事件(客户端事件)、onClose连接关闭事件(客户端事件)、onWorkerStop进程退出事件(进程事件)

 

也就是说多服务启动服务时,registerAddress需要一致,各服务的businessWorker的lanIp会同步到其他gateway。当client进行send message操作时,client连接的gateway把业务推到worker,worker找到接收信息client的gateway并发送信息,其中gateway作收发信息用,worker用作处理业务逻辑。

 

 

进行实践:

由于没有那么多服务器进行试验,因此使用了docker代替。

docker1 ip:172.17.0.2

docker2 ip:172.17.0.3  #设置为register服务器

 

 

代码部分,重点设置registerAddress为主服务器ip

#docker1 start_gateway.php

 

use \Workerman\Worker;

use \GatewayWorker\Gateway;

use \Workerman\Autoloader;

 

require_once __DIR__ . '/../../vendor/autoload.php';

// gateway 进程

$gateway = new Gateway("Websocket://0.0.0.0:7373");

$gateway->name = 'gateway';// 设置名称,方便status时查看

$gateway->count = 4;// 设置进程数,gateway进程数建议与cpu核数相同

$gateway->lanIp = '172.17.0.2'; // 分布式部署时请设置成内网ip(非127.0.0.1)此处做演示用,需填写真实的服务器内网ip

$gateway->startPort = 2310;// 不可被其他项目占用端口,2300-2303 , 2310-2313,   必须1236,1238端口不能重复,不能2个项目都用1236端口,可以全部替换其他端口!同时startPort不能冲突

$gateway->pingInterval = 10;// 心跳间隔

$gateway->pingData = '{"type":"ping"}';// 心跳数据

$gateway->registerAddress = '172.17.0.3:1238';// 服务注册地址

 

if(!defined('GLOBAL_START'))

{

    Worker::runAll();

}

 

 

#docker1 start_businesswork.php

 

use \Workerman\Worker;

use \GatewayWorker\BusinessWorker;

use \Workerman\Autoloader;

 

require_once __DIR__ . '/../../vendor/autoload.php';

 

$worker = new BusinessWorker();// bussinessWorker 进程

$worker->name = 'businessWorker';// worker名称

$worker->count = 4;// bussinessWorker进程数量

$worker->registerAddress = '172.17.0.3:1238';// 服务注册地址

// 如果不是在根目录启动,则运行runAll方法

if(!defined('GLOBAL_START'))

{

    Worker::runAll();

}

 

#docker2 start_gateway.php

 

use \Workerman\Worker;

use \GatewayWorker\Gateway;

use \Workerman\Autoloader;

require_once __DIR__ . '/../../vendor/autoload.php';

 

// gateway 进程

$gateway = new Gateway("Websocket://0.0.0.0:7373");

$gateway->name = 'gateway';// 设置名称,方便status时查看

$gateway->count = 4;// 设置进程数,gateway进程数建议与cpu核数相同

$gateway->lanIp = '172.17.0.3'; // 分布式部署时请设置成内网ip(非127.0.0.1)此处做演示用,需填写真实的服务器内网ip

$gateway->startPort = 2310;// 不可被其他项目占用端口,2300-2303 , 2310-2313,   必须1236,1238端口不能重复,不能2个项目都用1236端口,可以全部替换其他端口!同时startPort不能冲突

$gateway->pingInterval = 10;// 心跳间隔

$gateway->pingData = '{"type":"ping"}';// 心跳数据

$gateway->registerAddress = '172.17.0.3:1238';// 服务注册地址

 

if(!defined('GLOBAL_START'))

{

    Worker::runAll();

}

 

#docker2 start_businesswork.php

 

use \Workerman\Worker;

use \GatewayWorker\BusinessWorker;

use \Workerman\Autoloader;

require_once __DIR__ . '/../../vendor/autoload.php';

$worker = new BusinessWorker();// bussinessWorker 进程

$worker->name = 'businessWorker';// worker名称

$worker->count = 4;// bussinessWorker进程数量

$worker->registerAddress = '172.17.0.3:1238';// 服务注册地址

// 如果不是在根目录启动,则运行runAll方法

if(!defined('GLOBAL_START'))

{

    Worker::runAll();

}

 

 

 

#测试页面

 

Aliplayer Online Settings

    

 

 

然后分别启动:php start.php start

测试:web端测试:打开两个窗口,websocket ip分别填两个docker映射出来的端口,发送信息,对方聊天框能收到信息。

结论:两个docker都运行了gateway进程和worker进程,client可以连接任意一个gatewayworker进行互相通讯。

 

 

注意事项:

1、start_gateway.php中如果$gateway->startPort=2300; $gateway->count=4;,则2300 2301 2302 2303四个端口需要被设置成能被其它服务器访问,也就是起始端口$gateway->startPort到$gateway->startPort + $gateway->count - 1这 $gateway->count个端口要设置成能被其它内网服务器访问。

2、如果多机部署服务器不在一个局域网,部署时ip参数可以使用外网ip(注意云服务器一般没有外网网卡,所以阿里云、腾讯云等云服务器一般无法外网部署集群),对应端口防火墙应该设置成能被外网服务器访问。

3、为了方便前端接入和扩容,可以再gateway前面加一层DNS、LVS等负载均衡策略。

4、如果有了前端接入的负载均衡策略,就可以用同样的方法增加服务器。

 

 

附录:官方的并发估计

http://doc3.workerman.net/315236

并发连接数是指服务器当前时刻一共维持了多少TCP连接,而这些连接上是否有数据通讯并不关注,例如一台消息推送服务器上可能维持了百万的设备连接,由于连接上很少有数据通讯,所以这台服务器上负载可能几乎为0,只要内存足够,还可以继续接受连接。

并发请求数一般用QPS(服务器每秒处理多少请求)来衡量,而当前时刻服务器上有多少个tcp连接并不十分关注。例如一台服务器只有10个客户端连接,每个客户端连接上每秒有1W个请求,那么要求服务端需要至少能支撑10*1W=10W每秒的吞吐量(QPS)。假设10W吞吐量每秒是这台服务器的极限,如果每个客户端每秒发送1个请求给服务端,那么这台服务器能够支撑10W个客户端。

并发连接数受限于服务器内存,一般24G内存workerman服务器可以支持大概120W并发连接。

并发请求数受限于服务器cpu处理能力,一台24核workerman服务器可以达到45W每秒的吞吐量(QPS),实际值根据业务复杂度以及代码质量有所变化。

你可能感兴趣的:(php)