swoole之代码热更新实现 转自https://blog.csdn.net/nep_tune/article/details/81329918
随着swoole的版本迭代更新,已经足够稳定了,在阿里,腾讯,yy等各大公司都有着使用,也有很多游戏圈里的朋友也在使用,这些朋友经常会提到一个问题,每次代码更新还需要停止服务,然后重新启动,来达到更新代码,然而这种做法,是比较粗暴的。其实swoole里提供reload的特性,完全支持代码的热更新。
在介绍swoole的reload之前,先简要的讲讲web方式是如何改了文件就立即生效的:
几个概念:
1) sapi:可以简单的理解为php引擎对外的一个统一接口,使得php可以和外部程序进行交互
2) php的生命周期中关键四个调用:MINT -> RINT -> RSHUTDOWN -> MSHUTDOWN
3) fpm : fastcgi进程管理器
那么fpm方式的流程就是: fpm通过sapi接口与php进程交互,
在fpm启动的时候,
第一步: 会调用各扩展的MINT方法,进行一些数据初始化(长驻内存),
第二步: 每个请求过来,先会执行RINT对单个请求行一个初始化,
第三步: 执行php脚本,
第四步: 执行RSHUTDOWN方法,
第五步: 如果你要停止fpm了,才会执行MSHUTDOWN。
fpm对每个请求的处理都是一直在在重复执行 2~4步 。
在第三步中, php的脚本是动态执行的,由于每次都要执行一次php脚本,而每次php脚本都要有一个把php文件翻译成opcode的流程(比较耗时), 于是就产生的opcache工具。
opcache: 直接把php翻译后的opcode代码树保存到共享内存中,以便直接使用,从而减少每次都把php翻译成opcode的开销。
opcache的问题:按照他的描述,修改了php文件,并不能立即被更新,
opcache的解决方案:有一个配置来设置隔多长时间检测文件是否更新了,从而有机会在第二步重新来reload相关的文件.
当然,你也可以直接reload fpm,从而达到php热更新的效果(opcache扩展可以在第四步把相关的opcode cache给清空)。
swoole的问题:
swoole是以cli运行的,然后长驻内存的。整个生命周期只有在启动的时间可以一次执行RINT过程, 之后所有的请求都在第三步以内完成。(这也是swoole更快的原因之一),这样的话,相关的php脚本如果被执行了一次,就永久性的长驻内存了,更新代码就没有效果了。
swoole的解决方案:内置方法 $serv->reload()
前提:swoole是一个三层架构: master->manager->worker, master和manager是启动之后,就长驻内存的,所以这里reload的是worker进程,(而我们的业务逻辑正好都在worker进程)。
简单原理: 调用$server->reload()的时候:
第一步: 向manager进程发送USR1信号,
第二步: manager捕获到USR1信号,会向worker进程发送 TERM信号。
第三步:worker进程捕获这个TERM信号,做把一个running的标识设置0
第四步:woker的事件循环发现running标识为0,处理完当前逻辑就会自杀(自杀前会回调onWorkerStop函数),
第五步:manager再拉起一个新的worker (拉起后会回调onWorkerStart函数)
从这个流程中我们会发现,onWorkerStart 和 onWorkerStop非常像 sapi里的 RINT, RSHUTDOWN.
所以到了这里,实现代码热更新的的方案就是:
把业务逻辑的脚本文件的载入放到onWorkerStart方法里,如果用了opcache,那么把一些opcache的清理逻辑放到onWorkerStop方法里。
示例:
function onWorkerStart($serv,$worker_id) {
include"hot_update_class.php";
$class=newHotUpdate();
}
function onWorkerStop($serv, $worker_id) {
opcache_reset(); //zend_opcache的opcache清理函数
}
这时如果我们修改了hot_update_class.php里的相关文件,再执行$serv->reload(),就可以实现热更新了。
ps: 所以,我们可以把onWorkerStart当成我的业务逻辑的入口。
(
如果你使用了autoloader, 那么你把autoloader的注册放到onWorkerStart里来。
如果你使用了框架,那么你可以把框架的入口文件放到onWorkerStart里来。
)
如果你开启了opcache,那么,你可以在onWorkerStop的时候,执行相关的opcache清理工作。
(zend_opcache,直接调用opcache_reset()方法即可)
示例:
function onWorkerStop($serv,$worker_id) {
opcache_reset(); //zend_opcache的
//apc, xcache, eacc等其他方式,请调用相关函数
}
最后希望这篇博客能给你带来一些帮助。(注:如果你的worker里挂了异步事件,比如把某个curl挂到swoole_event_add里,那么worker的reload会把这些都清理掉,可能导致一些逻辑错误,解决方案正在酝酿中)
swoole官方交流群:321637118
swoole之代码热更新实现 转自https://blog.csdn.net/nep_tune/article/details/81329918的更多相关文章
- 码云私人代码 SSH 设置----https://blog.csdn.net/kkaazz/article/details/78667573
码云私人代码 SSH 设置 https://blog.csdn.net/kkaazz/article/details/78667573
- 基于eclipse的mybatis映射代码自动生成的插件http://blog.csdn.net/fu9958/article/details/7521681
基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...
- <转载> 22种代码味道(Martin Fowler与Kent Beck) http://blog.csdn.net/lovelion/article/details/9301691
Martin Fowler在Refactoring: Improving the Design of Existing Code(中译名:<重构——改善既有代码的设计>)一书中与Kent ...
- Cordova 代码热更新 - 简书
原文:Cordova 代码热更新 - 简书 Cordova 代码热更新 [图片上传失败...(image-a19be7-1521624289049)] 基于 Cordova 框架能将网页应用 (js, ...
- Unity3D热更新之LuaFramework篇[09]--资源热更新与代码热更新的具体实现
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建 中,我介绍了热更新的基本原理,并且着手搭建一台服务器. 本篇就做一个实战练习,真正的来实现热 ...
- Unity代码热更新方案 JSBinding + SharpKit 首页
目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...
- nodeJs 代码热更新
在开发node过程中,每次修改代码都需要重新启动服务,是一件很抓狂的事情 使用nodemon热加载可以帮我们很好的解决这一问题 1. 安装 npm install nodemon -g 2. 修改np ...
- idea内置tomcat中java代码热更新
按照上图设置后,然后修改代码后按shift+F9快捷键,即可实现代码更新,这时在debug模式下会看到代码变更后的输出
- node.js之nodemon 代码热更新 修改代码后服务器自动重启
1.安装nodemon: npm install -g nodemon //全局安装 npm install nodemon --save //局部安装 2.在项目根目录下创建 nodemon.jso ...
随机推荐
- nim调用GetSystemPowerStatus判断笔记本电脑是否接通外接电源
title: nim调用GetSystemPowerStatus判断笔记本电脑是否接通外接电源 tags:nim,winapi,dll --- 转载条件:如果你需要转载本文,你需要做到完整转载本文所有 ...
- 简单搭个webapp开发框架
集成开发工具idea 服务器容器Tomcat 第三方依赖管理maven 暂时不集成 (spring+springmvc+mybatis(数据持久层存取)+dubbo+zookeeper(集群调度)) ...
- php优秀框架codeigniter学习系列——CI_Input类学习
这篇文章主要介绍CI核心框架工具类CI_Input. 根据CI文档自己的定义,该类用来: 提前处理全局变量,以保证安全; 提供一些帮助函数用来处理输入数据. 以下选取类中的重点方法进行说明. __co ...
- Action访问Servlet API的三种方法
一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器 ...
- 花了2小时写bug
程序员的工作,写bug,修bug,改bug 写了2小时逻辑关系,没写明白 比昨天多了一个返回上一层的功能 也很简单,清除下数组内容即可 emm..明天继续深究吧 dic = { "植物&qu ...
- C# 比较和排序(IComparable和IComparer以及它们的泛型实现)
准备工作: 1.创建实体类:ClassInfo,默认想要对其按照班级学生数量进行排序 public class ClassInfo { /// <summary> /// 班级名称 // ...
- 运维seq语法2
2017-03-02 09:47:42 # seq 1 10结果是1 2 3 4 5 6 7 8 9 10例二:#!/bin/bashfor i in `seq 1 10`;doecho $i;d ...
- KeepAlive--高可用解决方案
原文地址https://segmentfault.com/a/1190000011078937 一:keepalive简述 一;高可用的解决方案 1)vrrp协议的实现keepalive 2)ais ...
- C语言---指针变量作为函数参数
在C语言中,函数的参数不仅可以是整数.小数.字符等具体的数据,还可以是指向它们的指针.用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着 ...
- Ubuntu如何百度云盘下载
我使用Firefox浏览器下载. (1)先为浏览器下载一个插件:网盘助手 (2)通过终端安装aria2: sudo apt-get install python-apt sudo apt-get in ...