众所周知,easyswoole作为常驻内存的框架,修改代码并不能直接生效,而是需要重启服务,那么,当你的easyswoole项目上线之后,该如何保证旧请求的同时去更新代码呢?
nginx reload和restart
首先,我们需要了解到nginx reload和restart的区别.
reload
nginx 执行reload命令后,将会重新加载一次配置文件,并且给其他worker进程发送信号,进程收到信号之后,将不再接收新请求,当旧请求执行完毕后,将会自动销毁.
同时,如果reload加载的配置文件出错,nginx将会自动回滚到正常时候的配置,并不会造成服务中断.
restart
restart= stop+start,当nginx执行restart命令后,将会先中断服务,不再接收请求.
同时,当配置文件出错时,restart将会无法正常start,服务将一直中断.
更新线上easyswoole代码.
easyswoole reload
easyswoole本身自带reload代码,可实现关于worker进程的重启,但由于easyswoole的task进程是通过自定义进程实现,无法实现重启.
所以理论上,我们依然需要直接stop+start
那么,如何才能使得stop+start依然不中断服务呢?
反向代理
在上一篇文章中,我们了解到了nginx反向代理,负载均衡的实现.nginx实现负载均衡,同时,easyswoole 服务,理应跟nginx反向代理配合使用:
首先,我们创建一个测试的easyswole服务,并且在index控制器中写入以下测试方法:
public function index() { $this->response()->write('<h1>test 1</h1>'); go(function(){ //假设每次请求进来,都将投递一个异步任务 TaskManager::getInstance()->async(function (){ echo 1; \\co::sleep(1); }); }); }
启动服务后,通过nginx 反向代理.
upstream test.cn { server 127.0.0.1:9501; } server { root /data/wwwroot/; server_name local.swoole.com; location / { proxy\_http\_version 1.1; proxy\_set\_header Connection "keep-alive"; proxy\_set\_header X-Real-IP $remote_addr; if (!-f $request_filename) { proxy_pass http://test.cn; } } }
在这个时候,我们已经启动了一个正在运行的服务:
新增测试脚本,测试请求
为了便于测试,我们新增一个测试脚本:
<?php /** * Created by PhpStorm. * User: 10671 * Date: 2020/5/25 0025 * Time: 21:33 */ while(1){ $test = file\_get\_contents("http://1.cn"); var_dump($test); usleep(100000); }
此脚本将会一直请求1.cn,并且打印数据.
更新代码
那么,假设现在我们需要更新代码,该怎么使得线上生效呢?首先,我们重新创建一个文件夹.
cp -r 1.cn/ 2.cn/
修改 dev.php端口改为 9502:
假设修改代码为test2:
public function index() { $this->response()->write('<h1>test 2</h1>'); go(function(){ //假设每次请求进来,都将投递一个异步任务 TaskManager::getInstance()->async(function (){ echo 1; \\co::sleep(1); }); }); }
启动该服务.并测试是否启动成功.
\[root@localhost 2.cn\]# curl http://127.0.0.1:9502 <h1>test 2</h1>\[root@localhost 2.cn\]#
此时,服务器运行了2个服务: 9501为旧版本服务,9502为新版本服务
注意,此例子为测试例子,在实际中,请使用git等版本控制工具更新代码.
此时9501正在一直接收请求,并且不断的在投递异步任务:
\[root@localhost 1.cn\]# php easyswoole task status ┌─────────┬─────────┬──────┬───────┬─────────────┐ │ running │ success │ fail │ pid │ workerIndex │ ├─────────┼─────────┼──────┼───────┼─────────────┤ │ 20 │ 71 │ 0 │ 36212 │ 0 │ ├─────────┼─────────┼──────┼───────┼─────────────┤ │ 20 │ 70 │ 0 │ 36213 │ 1 │ ├─────────┼─────────┼──────┼───────┼─────────────┤ │ 20 │ 70 │ 0 │ 36214 │ 2 │ ├─────────┼─────────┼──────┼───────┼─────────────┤ │ 20 │ 70 │ 0 │ 36215 │ 3 │ └─────────┴─────────┴──────┴───────┴─────────────┘
修改nginx代理,并reload 重载配置
此时,我们修改nginx的配置,改为代理9502:
upstream test.cn { server 127.0.0.1:9502; }
同时热重启nginx:
查看task任务状态
此时,nginx的新请求已经进入新服务.9501服务此时并没有中断,用于处理还未完成的task异步任务:
直到处理完成,才可关闭9501服务.
此时,线上版本已经更新成功,服务并没有中断.