最近在用swoole做群聊,确实是非常好用,但是使用过程中还是遇到了不少问题如下:
1、后台管理问题
2、热重启问题
未完待续。。。
环境说明: 系统:Ubuntu14.04 (安装教程包括CentOS6.5)
PHP版本:PHP-5.5.10
swoole版本:1.7.7-stable
Github链接:https://github.com/LinkedDestiny/swoole-doc
1.多端口监听
在实际运用场景中,服务器可能需要监听不同host下的不同端口。比如,一个应用服务器,可能需要监听外网的服务端口,同时也需要监听内网的管理端口。在Swoole中,可以轻松的实现这样的功能。 Swoole提供了addlistener函数用于给服务器添加一个需要监听的host及port,并指定对应的Socket类型(TCP,UDP,Unix Socket以及对应的IPv4和IPv6版本)。 代码如下:
$serv = new swoole_server("192.168.1.1", 9501); // 监听外网的9501端口
$serv->addlistener("127.0.0.1", 9502 , SWOOLE_TCP); // 监听本地的9502端口
$serv->start(); // addlistener必须在start前调用
此时,swoole_server就会同时监听两个host下的两个端口。这里要注意的是,来自两个端口的数据会在同一个onReceive中获取到,这时就要用到swoole的另一个成员函数connection_info,通过这个函数获取到fd的from_port,就可以判定消息的类型。
$info = $serv->connection_info($fd, $from_id);
//来自9502的内网管理端口
if($info['from_port'] == 9502) {
$serv->send($fd, "welcome admin\n");
}
//来自外网
else {
$serv->send($fd, 'Swoole: '.$data);
}
2.服务器热重启
所谓热重启,就是当服务器相关代码有所变动之后,无需停止服务,而是在服务器仍然运行的状态下更新文件。Swoole通过内置的reload函数以及两个自定义信号量实现了这一功能。 首先我讲解一下Swoole可用的三个信号:SIGTERM,SIGUSR1,SIGUSR2。SIGTERM用于停止服务器,SIGUSR1用于重启全部的Worker进程,SIGUSR2用于重启全部的Task Worker进程。 那要如何实现热更新代码文件呢?Swoole的回调函数中有这个一个回调onWorkerStart;该回调会在Worker进程启动时被调用。因此,当swoole_server收到SIGUSR1信号并重启全部Worker进程后,onWorkerStart就会被调用。如果在onWorkerStart中require全部的代码文件,每次onWorkerStart后都会重新require一次php文件,这样就能实现代码文件的热更新。 来看下代码实现:
public function onStart( $serv ) {
cli_set_process_title("reload_master");
}
public function onWorkerStart( $serv , $worker_id) {
require_once "reload_page.php";
Test(); // reload_page.php中定义的一个函数
}
首先,在onStart回调函数中通过php的cli_set_process_title函数设置进程名。 在onWorkerStart中,require相关的php文件。 然后,新建一个reload.sh文件,输入如下内容:
echo "Reloading..."
cmd=$(pidof reload_master)
kill -USR1 "$cmd"
echo "Reloaded"
这样,就可以通过执行这个脚本重启服务器了。 点此查看完整源码
3.Timer补充:after函数
在swoole-1.7.7stable版本中,Timer新增了一个函数after。该函数的作用是在指定的时间间隔后执行回调函数,并且只执行一次。 这个函数可以弥补Timer本身做不到或者做起来很难的一些定时工作。 代码如下:
$serv->after( 1000 , array($this, 'onAfter') , $str );
这里指定在1000ms后,执行onAfter回调函数,函数参数为$str。 举个例子,比如服务器要求在收到某个请求后,在30S后向所有用户发起推送。这样的需求就可以直接用after函数来实现。