Events.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. /**
  15. * 用于检测业务代码死循环或者长时间阻塞等问题
  16. * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
  17. * 然后观察一段时间workerman.log看是否有process_timeout异常
  18. */
  19. declare(ticks=1);
  20. use \GatewayWorker\Lib\Gateway;
  21. use Workerman\Lib\Timer;
  22. //defined('IN_WEB') or define('IN_WEB', true);
  23. define('WORKERNAME', 'Service');
  24. //define('WWWROOT', dirname(__FILE__).'/../../');
  25. //require_once WWWROOT . 'core.php';
  26. //define( 'PATH_CFG', WWWROOT . 'config/'.$config['sidlist'][1].$isTset.'/');
  27. //require_once PATH_CFG . 'config.inc.php';
  28. //oo::setConfig( $config); //设置全局变量
  29. //oo::functions()->header();
  30. /**
  31. * 主逻辑
  32. * 主要是处理 onConnect onMessage onClose 三个方法
  33. * onConnect 和 onClose 如果不需要可以不用实现并删除
  34. */
  35. class Events
  36. {
  37. public static function onWorkerStart($worker){
  38. global $dbs;
  39. global $rediss;
  40. $dbs = oo::commonOprDb('common');
  41. $dbs->connect();
  42. $redisArr =['common','statistics'];
  43. foreach ($redisArr as $v){
  44. $rediss[$v] = oo::commonOprRedis($v);
  45. }
  46. $time_id = Timer::add(5, function () use (&$time_id,$redisArr) {
  47. global $dbs;
  48. global $rediss;
  49. if(!$dbs->ping()){//失败释放内存,重连
  50. echo date('Y-m-d H:i:s').'close-mysql'."\r\n";
  51. $dbs->close();
  52. oo::$objDb =[];
  53. $dbs = oo::commonOprDb('common');
  54. }
  55. foreach ($redisArr as $v){
  56. if(!$rediss[$v]->ping()){//失败释放内存,重连
  57. echo date('Y-m-d H:i:s').'close-redis'."\r\n";
  58. $rediss[$v]->close();
  59. oo::$objRedis =[];
  60. $rediss[$v] = oo::commonOprRedis('common');
  61. }
  62. }
  63. });
  64. //保存各自节点所有在线玩家信息
  65. $recordTimer = Timer::add(30, function () { //每30秒存储一次all uid到redis
  66. if(!oo::commonOprModel('workerman')->checkNeedSave()){
  67. return;
  68. }
  69. oo::commonOprModel('workerman')->saveAllUids(Gateway::getAllUidList());
  70. });
  71. //订阅各自节点的消息
  72. Timer::add(2, function () {
  73. $lastSubPush = time();
  74. oo::commonOprModel('workerman')->pushMsgSubscribe();
  75. });
  76. }
  77. /**
  78. * 当客户端连接时触发
  79. * 如果业务不需此回调可以删除onConnect
  80. *
  81. * @param int $client_id 连接id
  82. */
  83. public static function onConnect($client_id){
  84. $time_id = Timer::add(5, function () use ($client_id , &$time_id) {
  85. if(empty(Gateway::getSession($client_id))){
  86. Gateway::closeClient($client_id);
  87. }
  88. Timer::del($time_id);
  89. });
  90. }
  91. /**
  92. * 当客户端发来消息时触发
  93. * @param int $client_id 连接id
  94. * @param mixed $message 具体消息
  95. */
  96. public static function onMessage($client_id, $message){
  97. json_decode($message);
  98. if(json_last_error() == JSON_ERROR_NONE){
  99. $res =json_decode($message,true);
  100. $res['encryp'] = 0;
  101. }else{
  102. $res = ProtocolsEvent::wsDecode($message);
  103. $res['encryp'] = 1;
  104. }
  105. if($res['cmd'] == 0x2008){
  106. list($t1, $t2) = explode(' ', microtime());
  107. $mSeconds = (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
  108. $str = json_encode(['cmd'=>0x600d,'code'=>1,"ts"=>time(), 'm_ts' => $mSeconds]);
  109. if($res['encryp']){
  110. $str = ProtocolsEvent::encode($str);
  111. }
  112. Gateway::sendToClient($client_id, $str);
  113. $uid = Gateway::getUidByClientId($client_id);
  114. $uid && oo::commonOprModel('workerman')->online($uid);
  115. return;
  116. }
  117. if(in_array($res['cmd'],array_keys(ocmd::$Cmd))){
  118. $res['cmd'] = ocmd::$Cmd[$res['cmd']];
  119. $session = Gateway::getSession($client_id);
  120. if(!isset($res['uid'])){
  121. if(isset($session[$client_id]['uid'])){
  122. $res['uid'] = intval($session[$client_id]['uid']);
  123. }
  124. }
  125. //每10次请求更新一次在线标记
  126. if(!empty($res['uid'])){
  127. $incrRet = oo::commonOprRedis('user')->incr(okeys::userWsReq($res['uid']));
  128. if($incrRet && $incrRet == 1){ //60秒过期
  129. oo::commonOprRedis('user')->expire(okeys::userWsReq($res['uid']), 60);
  130. }
  131. if($incrRet && $incrRet % 11 == 0){ //更新在线标记
  132. oo::commonOprRedis('user')->delete(okeys::userWsReq($res['uid']));
  133. oo::commonOprModel('workerman')->online($res['uid']);
  134. }
  135. }
  136. $action = explode('_',$res['cmd']);
  137. self::CrazyGodEvents(ucfirst($action[0]),ucfirst($action[1]),$client_id,$res);
  138. }
  139. }
  140. /**
  141. * 当用户断开连接时触发
  142. * @param int $client_id 连接id
  143. */
  144. public static function onClose($client_id){
  145. self::CrazyGodEvents('User','Offline',$client_id);
  146. }
  147. /**
  148. * 选择业务类
  149. * @param $mod
  150. * @param $func
  151. * @param $client_id
  152. * @param mixed $data
  153. */
  154. public static function CrazyGodEvents($mod,$func, $client_id, $data = ''){
  155. require_once __DIR__ . '/../Function/' .$mod.'.php';
  156. $mod = $mod.'CrazyWorker';
  157. $obj = new $mod(isset($data['sid'])?$data['sid']:1,$client_id);
  158. $obj->$func($client_id,$data);
  159. }
  160. }