ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
> 环境说明: 系统:Ubuntu14.04 (安装教程包括CentOS6.5) > PHP版本:PHP-5.5.10 > swoole版本:1.7.7-stable ## **1.多端口监听** 在实际运用场景中,服务器可能需要监听不同host下的不同端口。比如,一个应用服务器,可能需要监听外网的服务端口,同时也需要监听内网的管理端口。在Swoole中,可以轻松的实现这样的功能。 Swoole提供了[addlistener](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/03.swoole_server%E5%87%BD%E6%95%B0%E5%88%97%E8%A1%A8.md#swoole_serveraddlistener)函数用于给服务器添加一个需要监听的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](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/03.swoole_server%E5%87%BD%E6%95%B0%E5%88%97%E8%A1%A8.md#swoole_serverconnection_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); } ~~~ [点此查看完整源码](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/04/swoole_multi_port_server.php) ## **2.服务器热重启** 所谓热重启,就是当服务器相关代码有所变动之后,无需停止服务,而是在服务器仍然运行的状态下更新文件。Swoole通过内置的reload函数以及两个自定义信号量实现了这一功能。 首先我讲解一下Swoole可用的三个信号:SIGTERM,SIGUSR1,SIGUSR2。SIGTERM用于停止服务器,SIGUSR1用于重启全部的Worker进程,SIGUSR2用于重启全部的Task Worker进程。 那要如何实现热更新代码文件呢?Swoole的回调函数中有这个一个回调[onWorkerStart](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/02.%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0.md#3onworkerstart);该回调会在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](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/02.%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0.md#2onstart)回调函数中通过php的cli_set_process_title函数设置进程名。 在[onWorkerStart](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/02.%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0.md#3onworkerstart)中,require相关的php文件。 然后,新建一个reload.sh文件,输入如下内容: ~~~ echo "Reloading..." cmd=$(pidof reload_master) kill -USR1 "$cmd" echo "Reloaded" ~~~ 这样,就可以通过执行这个脚本重启服务器了。 [点此查看完整源码](https://github.com/LinkedDestiny/swoole-doc/tree/master/src/04/reload) ## **3.Timer补充:after函数** 在swoole-1.7.7stable版本中,Timer新增了一个函数[after](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/03.swoole_server%E5%87%BD%E6%95%B0%E5%88%97%E8%A1%A8.md#swoole_serverafter)。该函数的作用是在指定的时间间隔后执行回调函数,并且只执行一次。 这个函数可以弥补Timer本身做不到或者做起来很难的一些定时工作。 代码如下: ~~~ $serv->after( 1000 , array($this, 'onAfter') , $str ); ~~~ 这里指定在1000ms后,执行onAfter回调函数,函数参数为$str。 举个例子,比如服务器要求在收到某个请求后,在30S后向所有用户发起推送。这样的需求就可以直接用after函数来实现。 [点此查看完整源码](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/04/swoole_after_server.php) ## **4.Timer进阶:简易crontab** 未完成