<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[swoole之代码热更新实现]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Php/Js/Shell/Go]]></category>
<pubDate>Mon, 16 Jun 2014 06:40:26 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：作为swoole项目的顾问，平时工作时间很少看QQ群里如此有系统讲到swoole的热重启实现，特转载。<br/><br/>#分享自为知笔记#<br/>&lt;swoole之代码热更新实现_持续的思考&gt;<br/>swoole之代码热更新实现<br/><br/> 本人参与的swoole项目有幸被很多朋友使用，我也大力向周边的一些朋友推荐，随着swoole的版本迭代更新，已经足够稳定了，在阿里，腾讯，yy等各大公司都有着使用，也有很多游戏圈里的朋友也在使用，这些朋友经常会提到一个问题，每次代码更新还需要停止服务，然后重新启动，来达到更新代码，然而这种做法，是比较粗暴的。其实swoole里提供reload的特性，完全支持代码的热更新。<br/><br/>在介绍swoole的reload之前，先简要的讲讲web方式是如何改了文件就立即生效的：<br/><br/>  几个概念： <br/>  1） sapi：可以简单的更解为php引擎对外的一个统一接口，使得php可以和外部程序进行交互<br/>  2） php的生命周期：MINT -&gt; RINT -&gt; RSHUTDOWN -&gt; MSHUTDOWN<br/><br/>  3)  fpm : fastcgi进程管理器<br/><br/>  那么fpm方式的流程就是： fpm通过sapi接口与php进程交互，<br/>  在fpm启动的时候，<br/>第一步： 会调用各扩展的MINT方法，进行一些数据初始化（长驻内存），<br/>第二步： 每个请求过来，先会执行RINT对单个请求行一个初始化，<br/>第三步： 执行php脚本，<br/>第四步： 执行RSHUTDOWN方法，<br/>第五步： 如果你要停止fpm了，才会执行MSHUTDOWN。<br/><br/>  fpm对每个请求的处理都是一直在在重复执行 2~4步 。<br/><br/> 在第三步中， php的脚本是动态执行的，由于每次都要执行一次php脚本，而每次php脚本都要有一个把php文件翻译成opcode的流程（比较耗时）, 于是就产生的opcache工具。<br/><br/> opcache:  直接把php翻译后的opcode代码树保存到共享内存中，以便直接使用，从而减少每次都把php翻译成opcode的开销。<br/><br/>opcache的问题：按照他的描述，修改了php文件，并不能立即被更新，<br/><br/>opcache的解决方案：有一个配置来设置隔多长时间检测文件是否更新了，从而有机会在第二步重新来reload相关的文件.<br/><br/>  当然，你也可以直接reload fpm，从而达到php热更新的效果(opcache扩展可以在第四步把相关的opcode cache给清空)。<br/><br/>  <br/>  swoole的问题：<br/><br/>swoole是以cli运行的，然后长驻内存的。整个生命周期只有在启动的时间可以一次执行RINT过程， 之后所有的请求都在第三步以内完成。（这也是swoole更快的原因之一），这样的话，相关的php脚本如果被执行了一次，就永久性的长驻内存了，更新代码就没有效果了。<br/><br/>  swoole的解决方案：内置方法 $serv-&gt;reload()<br/><br/>前提：swoole是一个三层架构： master-&gt;manager-&gt;worker， master和manager是启动之后，就长驻内存的，所以这里reload的worker进程。<br/><br/>简单原理： 调用$server-&gt;reload()的时候：<br/><br/>  第一步： 向manager进程发送USR1信号，<br/>  第二步： manager捕获到USR1信号，会向worker进程发送 TERM信号。<br/>  第三步：worker进程捕获这个TERM信息，做把一个running的标识设置0<br/>  第四步：woker的事件循环发现running标识为0，处理完当前逻辑就会自杀（自杀前会回调onWorkerStop函数），<br/>  第五步：manager再拉起一个新的worker (拉起后会回调onWorkerStart函数）<br/><br/> 我们会发现，onWorkerStart 和 onWorkerStop非常像 sapi里的 RINT, RSHUTDOWN.<br/><br/>  所以到了这里，reload的方案就呼之欲出了：<br/><br/>  我们把业务逻辑的脚本代码载入放到onWorkerStart里来。就行了。<br/><br/>示例：<br/><br/>  function onWorkerStart($serv,$worker_id) &#123;<br/><br/>      include&quot;hot_update_class.php&quot;;<br/><br/>      $class=newHotUpdate();  <br/><br/>  &#125;<br/><br/><br/>如果修改了hot_update_class.php里的相关文件，再执行$serv-&gt;reload()，就可以实现热更新了。<br/><br/>如果你使用了autoloader, 那么你把autoloader的注册放到onWorkerStart里来。<br/><br/>如果你使用了框架，那么你可以把框架的入口文件放到onWorkerStart里来。<br/><br/>如果你开启了opcache，那么，你可以在onWorkerStop的时候，执行相关的opcache清理工作。<br/>（zend_opcache，直接调用opcache_reset()方法即可）<br/><br/>示例：<br/><br/>  function onWorkerStop($serv,$worker_id) &#123;<br/><br/>      opcache_reset(); //zend_opcache的      <br/><br/>      //apc, xcache, eacc等其他方式，请调用相关函数  <br/><br/>  &#125;<br/><br/> <br/><br/>最后希望这篇博客能给你带来一些帮助。（注：如果你的worker里挂了异步事件，比如把某个curl挂到swoole_event_add里，那么worker的reload会把这些都清理掉，可能导致一些逻辑错误，解决方案正在酝酿中）<br/><br/>swoole官方交流群：321637118<br/><br/>php swoole<br/><br/>来自：http://www.guangla.com/post/swoole-reload
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] swoole之代码热更新实现]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>