workerman 实现多服务器访问

walkor 回复了问题 • 2 人关注 • 1 个回复 • 1769 次浏览 • 2014-08-19 20:51 • 来自相关话题

Workerman文件传输问题

walkor 回复了问题 • 2 人关注 • 1 个回复 • 1836 次浏览 • 2014-08-19 20:25 • 来自相关话题

GATEWAY进程的IO模型

walkor 回复了问题 • 2 人关注 • 3 个回复 • 1446 次浏览 • 2014-08-19 12:30 • 来自相关话题

多个GATEWAY进程的客户端的连接信息在哪维护

walkor 回复了问题 • 3 人关注 • 4 个回复 • 2039 次浏览 • 2014-08-19 11:39 • 来自相关话题

thrift 编译接口文件

walkor 回复了问题 • 2 人关注 • 2 个回复 • 1877 次浏览 • 2014-08-19 11:27 • 来自相关话题

如果workerman实现分布式处理

walkor 回复了问题 • 3 人关注 • 8 个回复 • 2724 次浏览 • 2014-08-19 11:12 • 来自相关话题

opcache的缓存模式和workerman守护进程模式

walkor 回复了问题 • 3 人关注 • 1 个回复 • 4415 次浏览 • 2014-08-19 10:09 • 来自相关话题

請問為什麼,sendBufferToWorker函數無法將資料送出?

walkor 回复了问题 • 2 人关注 • 7 个回复 • 1524 次浏览 • 2014-08-18 10:04 • 来自相关话题

功能建議。

walkor 回复了问题 • 3 人关注 • 3 个回复 • 1708 次浏览 • 2014-08-10 10:18 • 来自相关话题

DemoChat的问题

hypcloud 回复了问题 • 2 人关注 • 4 个回复 • 1595 次浏览 • 2014-08-06 16:45 • 来自相关话题

接收的问题

walkor 回复了问题 • 2 人关注 • 3 个回复 • 1922 次浏览 • 2014-08-06 09:55 • 来自相关话题

麻烦问下有没有workerman与u3d客户端通信的解决方案,多平台的

walkor 回复了问题 • 2 人关注 • 1 个回复 • 1614 次浏览 • 2014-07-29 15:20 • 来自相关话题

workerman不支持c++的weboscket

walkor 回复了问题 • 2 人关注 • 1 个回复 • 2184 次浏览 • 2014-07-21 11:03 • 来自相关话题

workerman 用的什么 io复用方式?

walkor 回复了问题 • 2 人关注 • 1 个回复 • 1724 次浏览 • 2014-07-10 15:06 • 来自相关话题

workerman 可連結後端資料庫或是其他任何的php相關的模組嗎?

phpgame 回复了问题 • 3 人关注 • 2 个回复 • 1816 次浏览 • 2014-07-08 16:52 • 来自相关话题

聊天系统 多服务器部署

walkor 回复了问题 • 3 人关注 • 2 个回复 • 2022 次浏览 • 2014-07-01 14:12 • 来自相关话题

workerman能在windows上运行吗?

walkor 回复了问题 • 2 人关注 • 1 个回复 • 2202 次浏览 • 2014-06-28 21:27 • 来自相关话题

多聊天室的程序

walkor 回复了问题 • 3 人关注 • 2 个回复 • 1817 次浏览 • 2014-06-27 18:42 • 来自相关话题

使用workerman做游戏,如何方便调试

HappyLiu 回复了问题 • 3 人关注 • 3 个回复 • 4397 次浏览 • 2014-06-25 14:57 • 来自相关话题

文件上传小雨

walkor 回复了问题 • 3 人关注 • 2 个回复 • 2500 次浏览 • 2014-06-24 18:38 • 来自相关话题

Notice : Soft open files now is 1024, We recommend greater than 10000 这是什么?

walkor 回复了问题 • 3 人关注 • 1 个回复 • 2382 次浏览 • 2014-06-20 17:48 • 来自相关话题

一次收到多組資料封包,如何處理?

walkor 回复了问题 • 2 人关注 • 6 个回复 • 1853 次浏览 • 2014-06-17 14:30 • 来自相关话题

怎么解决 Function stream_socket_server may be disabled Please check disable_functions in php.ini

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 3123 次浏览 • 2015-02-04 14:35 • 来自相关话题

event.php里的onConnect, onMessage, onClose三个函数如何理解?

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 4024 次浏览 • 2014-06-14 22:39 • 来自相关话题

workerman需要的php模块posix、pcntl、sysvshm、sysvmsg缺少,怎么办

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 14655 次浏览 • 2014-06-14 22:38 • 来自相关话题

workerman里的gateway 和 gateworker 是如何衔接的,我有些不太明白

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 2651 次浏览 • 2014-06-14 22:11 • 来自相关话题

/usr/bin/env: php: No such file or directory 出现这样的问题?

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 4543 次浏览 • 2014-06-13 18:50 • 来自相关话题

workerman开发文档

walkor 发表了文章 • 1 个评论 • 6195 次浏览 • 2014-06-12 17:34 • 来自相关话题

# 注意,这个是workerman老版本文档,已经不适用目前版本 # 一、workerman是什么   workerman是一个高性能的PHP Socket服务器框架,它类似PHP-FPM,提供进程控制及socket通讯功 ...查看全部

# 注意,这个是workerman老版本文档,已经不适用目前版本

# 一、workerman是什么
  workerman是一个高性能的PHP Socket服务器框架,它类似PHP-FPM,提供进程控制及socket通讯功能,区别是PHP-FPM是以FAST-CGI的协议对外提供服务的,而workerman却可以支持各种协议(包括自定义协议),并且支持长链接,支持进程内全局对象资源等永久保持等特性。
#二、workerman能做什么
  虽然workerman可以作为Webserver的替代Nginx PHP-FPM等架构,并且性能也比Nginx PHP-FPM高,但是我们不推荐这样做,因为PHP的WebServer市场上已经很成熟了,workerman不会再去做重复的事情。反而workerman把精力花在传统WebServer无法胜任的角色上,例如非HTTP协议的应用、长链接应用、UDP应用、IM、游戏后端等。
#三、workerman目录结构

../
├── applications
└── workerman

  1、workerman目录是workerman框架的核心代码,包含了启动脚本及workerman配置等。为了方便理解你可以把它看作PHP-FPM。
  2、applications目录存放的是应用程序,例如应用框架、应用入口文件(类似index.php),业务逻辑等等。

workerman与applications是如何交互的
  workerman可以看作是PHP-FPM,所以它需要一个入口文件(类似index.php),这个入口文件可以放在applications中,这个入口文件一般满足以下要求:
  1、继承Man\Core\SocketWorker类
  2、实现Man\Core\SocketWorker::dealInput方法
  3、实现Man\Core\SocketWorker::dealProcess方法
workerman就是运行入口文件中的dealInput dealProcess方法来与业务衔接的。

#四、workerman请求周期
  workerman请求周期包括了请求解析+业务处理两部分,正好对应Man\Core\SocketWorker::dealInput/dealProcess两个方法。也就是说客户端每次请求一般都会调用Man\Core\SocketWorker::dealInput/dealProcess,这两个方法也正是暴露给开发者的接口,实现这两个接口使得开发者可以在请求到来时和请求接收完毕时加入自己的业务逻辑。下面详细说明两个方法。

Man\Core\SocketWorker::dealInput($recv_buffer)方法
  这个方法是用来根据应用层协议判断从客户端接收到的$recv_buffer数据是否合法、是否完整。这个方法的返回值有三种情况,X>0说明还有X字节没有收到,X==0说明数据全部收到,进入业务处理阶段dealProcess,X==false说明数据包格式错误

Man\Core\SocketWorker::dealProcess($recv_buffer)方法
  当Man\Core\SocketWorker::dealInput($recv_buffer)返回0时,即说明客户端接收到的$recv_buffer是合法并完整的,这时根据应用层协议解析出实际的内容做相应的业务逻辑。

#五、如何使用workerman
1、使用workerman第一步就是要确认你用哪种应用层协议。
什么是应用层协议?
  应用层协议是用来识别网络传来数据是否完整及传输的数据是什么,协议一般包括两部分:
  1、数据完整性标记(Man\Core\SocketWorker::dealInput)。
  2、数据格式(Man\Core\SocketWorker::dealProcess)。
  不要把协议想象成是很复杂的东西,举个例子应用层协议类似于有人给你邮寄过来一堆物品(网络数据),你要判断东西(数据)是否都送来了,那么你就需要看下快递清单(类似协议头,里面记录了数据长度),清单上写着3个箱子,你看到确实有3个箱子,确认物品全部收到了(以上是Man\Core\SocketWorker::dealInput函数要做的事)。然后打开箱子(双方协商的解包方法、json_decode、parse_xml等)便可以看到具体的物品(数据)了,有了物品(数据)你便可以做你应该做的事情了(这部分是Man\Core\SocketWorker::dealProcess做的事情)。

让我们来定义一个应用层协议
1、数据完整性标识
  第一种:固定位置的一个字段标记整个包的长度。例如数据首部四个字节(int)是数据包长度+数据,即$packed_int . $string
  第二种:在每一段数据结束时加上一个特粟的标记位,一般是一个字节。例如在数据末尾加上\0表示一个数据包结束,即$string.‘\0’
  当然还有其它方法
2、数据格式
  数据格式有很多选择,如文本、json、xml、二进制流等等

一个协议的实现 4bytes+json, 即pack('N', $len).$json

创建文件 applications/JsonDemo/JsonProto.php

<?php
class JsonProto
{
// 根据首部四个字节(int)判断数据是否接收完毕
public static function check($buffer)
{
// 读取首部四个字节
$buffer_data = unpack('Ntotal_length', $buffer);
// 得到这次数据的整体长度(字节)
$total_length = $buffer_data['total_length'];
// 已经收到的长度(字节)
$recv_length = strlen($buffer);
if($total_length>$recv_length)
{
// 还有这么多字节要接收
return $total_length - $recv_length;
}
// 接收完毕
return 0;
}

// 打包
public static function encode($data)
{
// 选用json格式化数据
$buffer = json_encode($data);
// 包的整体长度为json长度加首部四个字节(首部数据包长度存储占用空间)
$total_length = 4 + strlen($buffer);
return pack('N', $total_length) . $buffer;
}

// 解包
public static function decode($buffer)
{
$buffer_data = unpack('Ntotal_length', $buffer);
// 得到这次数据的整体长度(字节)
$total_length = $buffer_data['total_length'];
// json的数据
$json_string = substr($buffer, 4);
return json_decode($json_string, true);
}
}



2、创建入口文件并实现 Man\Core\SocketWorker::dealInput dealProcess方法
创建入口文件 applications/JsonDemo/JsonDemo.php

<?php
require_once __DIR__.'/JsonProto.php';
class JsonDemo extends Man\Core\SocketWorker
{
// workeman 请求周期第一步,根据应用层协议判断数据是否接收完毕
public function dealInput($recv_buffer)
{
// 判断数据是否接收完毕
return JsonProto::check($recv_buffer);
}

// workerman请求周期第二步,请求接收完毕后根据接收到的数据运行对应的业务逻辑
public function dealProcess($recv_buffer)
{
// 得到json数据
$json_data = JsonProto::decode($recv_buffer);

/**
* 这里根据你的json_data内容出处理不同的业务逻辑
**/

// 如果有需要,可以向客户端发送结果
$this->sendToClient(JsonProto::encode(array('code'=>0, 'msg'=>'ok')));
}
}


3、配置workerman
创建配置 workerman/conf/conf.d/JsonDemo.conf,配置名与类名相同。


;进程入口文件,类似index.php
worker_file = ../applications/JsonDemo/JsonDemo.php
;监听的ip 端口,udp协议则是 listen=udp://0.0.0.0:2020
listen = tcp://0.0.0.0:2020
;你的网络服务是长连接还是短连接。如果需要和客户端一直保持链接(例如聊天类应用)则设置为1,否则设置为0
persistent_connection = 0
;启动多少服务进程
start_workers=5
;以哪个用户运行该进程,为了安全考录,应该使用权限较低的用户,例如www-data nobody等
user=root
;socket有数据可读的时候预读长度,一般设置为应用层协议包头的长度,因为JsonProto首部四个字节标识了长度,所以这里设置为4
preread_length=4



#六、启动workerman
./workerman/bin/workermand start

至此你的服务框架已经开发完了

#七、写一个简单的PHP客户端


<?php
require_once __DIR__.'/JsonProto.php';
$socket = stream_socket_client('tcp://127.0.0.1:2020');
// JsonDemo::dealInput 会收到 $recv_buffer 类似 xxxx{'mod':'abc','act':'cde'} 这样的数据,其中xxxx是四个字节的int数字,表现为乱码,后面是json串
fwrite($socket, JsonProto::encode(array('mod'=>'abc', 'act'=>'cde')));
var_export(fread($socket, 65535));



#八、关于进程模型
workerman整体的进程模型是master slave 模型:
  1、master进程负责监控slave,slave进程退出时master进程会重新创建相同的slave进程
  2、slave进程是实际干活儿的进程,负责接收请求(Man\Core\SocketWorker::dealInput)以及处理请求(Man\Core\SocketWorker::dealProcess)

进程模型的变种
  workerman整体的进程模型是master slave 模型,但是根据slave的工作不同,有一些区别,下面通过例子讲解。
workerman源代码中有两个例子,一个是FileRecevierDemo(二进制文件传输),一个是ChatDemo(聊天)。

FileRecevierDemo文件传输
  测试方法是启动workerman后,命令行运行 cd applications/FileReceiverDemo/ ,命令行运行 php ClientDemo.php workerman.png 2 会把当前目录的workerman.png 文件传输给workerman,然后workerman会把文件存储到本地(逻辑在applications/FileReceiverDemo/FileReceiverDemo.php中),并且返回存储位置,然后服务端和客户端断开链接。
FileRecevierDemo分析
  1、dealInput:所用协议 头部5个字节,前4个字节如上面JsonDemo一样标识数据包长度,另外一个字节表示文件类型(1:jpg,2:png..),再后面紧接着是二进制图片数据
  2、dealProcess:因为头部固定5个字节,则从第6个字节开始到包长的所有数据就是图片数据,截取完毕后根据头部1个字节的文件类型(1:jpg、2:png..),保存文件到本地,并发给客户端结果($this->sendToClient())

FileRecevierDemo进程模型
  FileRecevierDemo是典型的master slave进程模型,slave进程具有以下特点:
  1、slave既负责网络传输,又负责业务处理
  2、短链接(业务处理完毕后就断开链接,下次传文件时会再次链接)

ChatDemo聊天
  测试方法:启动workerman后,命令行运行 cd applications/ChatDemo/Tests,命令行运行 php Chat.php。打字回车发给所有人,uid:XXXXX发消息给某个人。

ChatDemo进程模型分析
  1、ChatDemo的slave进程分为两种:gateway进程和worker进程
  2、gateway进程:applications/ChatDemo/Bootstrap/Gateway.php,这个进程只负责网路IO,不处理业务逻辑。具体工作内容为:维持服务端与客户端的长链接,将客户端的数据转发给worker进程(目前是udp协议,有需要可以自行改成tcp),worker进程做实际的业务处理,有需要时将结果数据发给gateway进程(目前是udp协议,有需要可以自行改成tcp),gateway进程将结果数据转发给对应的用户。
  3、worker进程:applications/ChatDemo/Bootstrap/Worker.php,这个进程主要负责业务逻辑。具体工作内容为:负责接收gateway转发来的客户端请求,并解析处理,如果有需要,则同样通过gateway向某个/些客户端发送数据。

ChatDemo进程模型特点
  1、有两个slave进程,一个负责网络IO并维持客户端链接,一个负责业务处理
  2、长链接,客户端与gateway之间是TCP长链接,通过这个链接实现客户端与服务端的双向通信

#九、为什么使用gateway worker模型
  gateway worker模型非常适合长链接应用,例如聊天、游戏后台等。如果是短链接,则建议使用上面FileRecevierDemo基础的master slave模型。
  1、gateway只负责网络IO,worker主要负责业务逻辑。各司其职,非常高效。
  打个比方,一个餐馆有4工人(进程),他们即负责招呼客人(网络IO),又负责在厨房做菜(业务逻辑)。当客人一下子来很多的时候(很多链接或很多数据),大家有可能都去招待客人了(都处理网络IO),厨房没人做菜(做业务)。当大家都做菜的时候(做业务),又没人招呼客人(接收链接),导致客人(用户)都在等待。但是当我们把工人(进程)分工一下,2个人专门招呼客人(geteway进程),两个人专门做菜(worker进程),这样每个时刻都有有人(进程)招待客人(接收数据),都有人(进程)做菜(处理业务)。当gateway不够用的时候(一般都是够用的)增加gateway,worker忙不过来的时候增加worker进程。这样效率会提升很多。
  2、提高稳定性
  gateway进程因为要维持用户链接,这要求gateway进程一定要非常稳定,不然如果gateway进程出问题,则这个进程上的所有用户都会断开链接。让gateway只负责网络IO,不负责业务,就是因为业务频繁变化,可能会有致命的错误(例如调用了一个不存在的函数)导致进程退出,进而导致用户链接断开。而让gateway只负责网络IO,就是要避免这种风险。而worker进程是无状态的(没有保存用户链接等状态信息),即使偶尔出现FatalErr,也只会影响当前的这次请求,而不会对整个服务造成大的影响。
  3、热更新
  由于gateway进程没有业务逻辑,所以geteway进程极少有代码更新。而worker进程由于负责业务逻辑,会有经常性的代码更新。这样看来我们每次代码更新,只要重启worker进程就可以实现运行新的业务代码。实际上也是这样,当更新程序逻辑时,我们只需要重启worker进程就可以了,这样就不会导致更新代码的时候用户链接会断开,达到不影响用户的情况下热更新后台程序。
  4、扩展容易
  当worker进程不够用的时候,我们可以水平扩展它,可增加worker的进程数量,甚至可以增加服务器专门运行worker进程,达到水平扩展的目的,以支持更大的用户量。gateway进程也是同样的道理。

#十、gateway worker进程模型预留的接口
  正如上面所说,gateway worker模型非常适合长链接应用,为此ChatDemo专门抽象出来相应的接口以简化长链接应用的开发。
使用ChatDemo中的gateway worker进程模型,业务开发者只需要实现worker进程中的业务逻辑即可,开发者只需要关注applications/ChatDemo/Event.php。这个文件开放了三个方法给开发者去实现。
  1、onConnect
  当用户链接服务器后发的第一个数据包时会触发这个方法,一般在这里做用户登录验证工作,例如通过用户传来的$message($message是客户端传递过来未作任何加工的原始数据,里面一般包含了用户名和密码)获得用户名密码,然后从数据库中获得uid(uid必须为大于0小于42亿的数字),并存储这个uid的内部gateway通信地址( GateWay::storeUid($uid)),还要向gateway进程注册(GateWay::notifyConnectionSuccess($uid))这个uid,还可以在这里向数据库中标记该用户在线状态。如果用户不合法则可以调用GateWay::kickCurrentUser(‘’)踢掉当前登录用户。
  2、onMessage
  当合法用户(onConnection时用户合法并注册)发来数据时会触发这个方法。这个方法里面主要是处理业务逻辑。$message是客户端发过来的未作任何加工的原始数据,通过商定的协议去解析$message,然后根据数据内容做路由分发,运行同的业务函数等。如果这期间需要给某uid或者所有人的客户端发消息,则使用Gateway::sendToUid/SendToAll方法即可。
  3、onClose
  当用户客户端主动断开时,触发这个方法。
在这个方法中开发者可以清理用户的数据,例如在数据库中加上下线标记。

发送数据接口
  chatDemo中提供了两个给用户客户端发送数据的接口
  1、Gateway::sendToAll($message)
  这个是向所有在线的(当前链接服务器的)所有用户发送消息。$message是要发送的数据,客户端会收到未经过任何处理的原始$message数据。客户端收到这个$message数据后根据协议解析数据内容,做相应的展现。
  2、Gateway::sendToUid($uid, $message);
  向某个在线用户的客户端发送消息,$uid是接收者的uid。$message是要发送的数据,目标用户的客户端会收到未经过任何处理的原始$message数据。客户端收到这个$message数据后根据协议解析数据内容,做相应的展现。
  3、Gateway::kickUid/kickCurrentUid
  踢掉某uid用户/当前用户
  4、如何给某批(群组)的用户发消息
  需要循环调用Gateway::sendToUid($uid, $message);方法


待续.....

为什么不支持win呢有没有解决办法

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 1703 次浏览 • 2014-06-11 10:44 • 来自相关话题

Workerman 在 Centos 环境下的部署

endler 发表了文章 • 0 个评论 • 3253 次浏览 • 2014-05-30 12:11 • 来自相关话题

安装要点: 1,安装php-cli 版本≥5.3 centos yum 装的 php 是 5.1.6 ,请升级到 5.3 以上,我装的是5.5.10. php命令如 ...查看全部
安装要点:


1,安装php-cli 版本≥5.3

centos yum 装的 php 是 5.1.6 ,请升级到 5.3 以上,我装的是5.5.10.

php命令如果不能执行,请修改环境变量

php -v 查看php版本

环境变量修改:


编辑 ~/.bash_profile,将:


PATH=$PATH:$HOME/bin


改为:


PATH=$PATH:$HOME/bin:/usr/local/php/bin


使 PHP 环境变量生效:

# . ~/.bash_profile

2,安装php扩展

posix、pcntl、sysvshm、sysvmsg

1)首先进入php安装目录的扩展目录



cd /root/lnmp0.4-full/php-5.2.10/sysvshm/


2)执行



/usr/local/php/bin/phpize


3) 编译安装



./configure --with-php-config=/usr/local/php/bin/php-config

make && make install


4)修改php.ini 注意,cli 的php.ini 路径可能不同,我的是在 /etc/php.ini

查看php.ini 位置的命令



php -i|grep php.ini / php --ini


查找:extension = 再最后一个extension= 后面添加上


extension = "sysvshm.so"

5)重启 php

其它模块类似,php -m 查看php已安装模块



3,下载,启动workerman,



wget http:// www.workerman.net/download/workermanzip


也可以下载demo小蝌蚪


http:// www.workerman.net/download/todpolezip

解压后,进入目录


启动:./bin/workermand start

停止:./bin/workermand stop

重启:./bin/workermand restart

平滑重启:./bin/workermand reload

查看状态:./bin/workermand status

4,测试workermand

telnet ip 端口

win7默认telnet 是关闭的,

控制面板 -> 程序和功能 -> 打开或关闭windows功能 -> 把telnet客户端 打勾 -> 确定即可

如果超时连不上可能是端口没有打开

5,centos打开端口

1)编辑iptables



vi /etc/sysconfig/iptables


2)添加


-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 3001 -j ACCEPT

注意,添加在80,22行下面,添加错位置有可能不起作用。

3)重启


重新启动服务


service iptables restart



查看端口是否开放


/sbin/iptables -L -n

workerman启动的问题,怎么解决

phpgame 回复了问题 • 2 人关注 • 1 个回复 • 2602 次浏览 • 2014-05-29 17:34 • 来自相关话题

PHP小蝌蚪游戏如何分布式部署

walkor 发表了文章 • 3 个评论 • 3082 次浏览 • 2014-05-09 23:41 • 来自相关话题

PHP小蝌蚪游戏使用的是phpgame框架,phpgame框架设计的时候就是基于分布式设计的,所以PHP小蝌蚪游戏也是可以分布式部署的。 # 分布式具有以下好处: 1、充分综合利用资源,并行计算处理,高性能 2 ...查看全部
PHP小蝌蚪游戏使用的是phpgame框架,phpgame框架设计的时候就是基于分布式设计的,所以PHP小蝌蚪游戏也是可以分布式部署的。

# 分布式具有以下好处:
1、充分综合利用资源,并行计算处理,高性能
2、避免单点故障造成的整个系统崩溃
3、提高系统整体承载能力
4、节约成本

关于第4点节约成本:拿小蝌蚪游戏来说,小蝌蚪由于游戏自身的特点对于CPU及内存要求不高,但是会比较消耗的服务器带宽。小蝌蚪使用的服务器是两台阿里云的低配(单核+500M内存+5M带宽)云主机价格为2x157¥/月,同样的带宽如果选用单台(单核+500M内存+10M带宽)服务器则需要1*657¥/月。所以选择两台低配5M带宽的服务器要比单台划算很多,后面如果还需要扩容则增加低配置服务器即可,所以支持分布式部署会节约不少成本,既拿很多低配机器撑起海量请求。

# 如何分布式部署小蝌蚪游戏呢?

首先了解下phpgame框架的进程模型
phpgame框架分为两组进程gateway进程和worker进程(分别对应workers下的gateway.php和worker.php)

  • gateway进程只负责网络IO,gateway进程是异步非阻塞的。gateway具体职责是
1、hold住客户端连接2、并将客户端发来的数据转发给worker进程处理3、接收worker进程的处理结果并发送给客户端
  • worker进程主要职责是处理用户请求,具体如下
1、接收gateway进程socket转发来的用户请求
2、处理请求
3、如果有需要,通过socket向gateway发送结果数据,gateway将结果数据再转发给用户

那么基于这种进程模型可以看到,gateway进程和worker进程是可以分开部署在不同机器上,这为我们分布式部署提供了便利。
所以当小蝌蚪带宽资源不足时,可以简单的增加gateway的机器,然后配置gateway进程将请求转发给同一台worker机器即可,这样就实现了增加低配服务器提高接入服务器带宽的目的,节约了成本又大大的增加了系统的承载能力。

# 具体如何配置:
1、首先前端配置,根据当前域名判断是否使用多个接入机
applications/Todpole/Web/js/Setting.js

var Settings = function() {
// [b]如果是workerman.net phpgame.cn域名 则采用多个接入端随机负载均衡[/b]
var domain_arr = ['workerman.net', 'phpgame.cn','www.workerman.net', 'www.phpgame.cn'];
if(0 >= $.inArray(document.domain, domain_arr)){
this.socketServer = 'ws://'+domain_arr[Math.floor(Math.random() * domain_arr.length + 1)-1]+':8280';
}
else{
// 运行在其它域名上
this.socketServer = 'ws://'+document.domain+':8280';
}
}


2、服务端配置
gateway接入机的配置 conf/conf.d/Gateway.conf

listen = tcp://0.0.0.0:8280
persistent_connection = 1
start_workers = 5
user = www-data
preread_length = 65535
;[b]本机内网ip[/b]
lan_ip = [b][i]本gateway接入机IP[/b][/i]
lan_port_start = 20000
;[b]worker进程的ip[/b]
game_worker[] = udp://[b][i]worker机器IP[/b][/i]:8183


worker业务逻辑机器的配置

;确认worker监听的ip是0.0.0.0,最好是本机内网ip
listen = udp://[b][i]0.0.0.0[/b][/i]:8183
start_workers = 5
user = www-data
preread_length = 23
max_requests=1000


3、替换原applications/Todpole/Store.php的内容如下:

class Store
{
protected static $instance = null;

public static function connect()
{
if(!self::$instance)
{
self::$instance = new Memcache;
self::$instance->addServer('[b]memcache内网机器IP[/b]', 11211);
}
return self::$instance;
}

public static function set($key, $value, $ttl = 0)
{
if(self::connect())
{
return self::$instance->set($key, $value, $ttl);
}
return false;
}

public static function get($key)
{
if(self::connect())
{
return self::$instance->get($key);
}
return false;
}

public static function delete($key)
{
if(self::connect())
{
return self::$instance->delete($key);
}
return false;
}

public static function deleteAll()
{
}
}

4、安装memcahced (debian系统运行命令 apt-get install memcached)
此时memcached可能已经运行起来了,可以先kill掉,然后运行 /usr/bin/memcached -m 128 -p 11211 -u nobody -l 0.0.0.0 -D 启动memcahced服务
给php安装memcache扩展(debian系统运行命令 apt-get install php5-memcache)

好了,重启服务,大功告成!