<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>https://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>https://jackxiang.com/post//</link>
<title><![CDATA[[实践OK]Swoole、PHP与MySQL：连接池,swoole扩展实现真正的PHP数据库连接池。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[数据库技术]]></category>
<pubDate>Sun, 03 Jan 2016 05:08:00 +0000</pubDate> 
<guid>https://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：天峰兄弟及Swoole的出现解决了长连接问题，但对mysql的线程池还需要进一步解决成一个体系，这块web直接连， 那么连接池也就是多余的 ，RPC形成一个过程也就让性能消耗最小，非常直接且跨平台，再谈一点这块的一个背景：也包括在PHP出现前的WEB1.0阶段，如，在新浪企业邮箱就有基于Sun Solaris 系统上面用c++写Mysql的长连接实现邮箱用户验证登录，那时候的长连接是基于Solaris 下的RPC实现（那时硬件也是sun提供的），对mysql那一端形成一个远程过程的调用，通过XDR数据结构进行解析mysql传来的数据项（RPC也为sun最新提出并后来在linux上默认支持），也就是说像用户登录验证这一块用Mysql的长连接来实现，提高其效率运行相当稳定，后面这个系统迁移到了FreeBSD后，出现了mysql长连接的服务经常出现假死，也就是说进程还在，但是已经连接不上mysql了，重新启动这个RPC服务又好了，原因未知，当时我对c++不了解（现在也不太了解，只听说要看是否形成coredump啥的），当年我还写过一个判断死了就杀死，重启动，判断的程序也老半天回不来，于是我又改成了一个多线程，如果超时没有回来，就干掉那个进程，重启Rpc服务，再后来，这套C++的cgi被替换成了php，再后来基于FreeBSD的系统迁移到了Linux，也就是现在一直在linux上，linux也就强大了起来，回想起来，当年一个登录服务如此极致，现在都变成了直接查询mysql了，这个长连接技术有还有用吗？我只能说对有上千台上万台的服务器可能有用，能节省一定的机器成本罢。但是，追求技术永无止境，需要有这样的一些东西来繁荣我们这个PHP的市场，长连接这个话题不再是Java做成了连接池，像c++也能做成连接池，像腾讯广平就有c++团队还有写cgi实现长连接Mysql服务，据说前二年吧更多关注了H5，像实时技术，比如Tail技术在web上的实现，有转向nodejs的趋势（node试想通过在google这颗大树下提供出来的V8引擎让前端程序员为排头兵统一后端服务及接口），而此时的PHP拿不出这样的技术，是很危险的，有了swoole起到填补作用，我更多的是觉得官方应该重视这个技术，而不是形成一个扩展，像H5的来到，像websocket的进入，这些东西对于Node来讲，从前端向后端的统一，而PHp呢？没有谁来解决，那么从用户角度来讲，开发者用户的流失或迁移，对PHP本身也是一个损失，但我还是说PHP是最好的语言没有之一，期望其能伴随潮流，与时俱进，更好满足当前web端新的需求。<br/><br/>发牢骚：port其实是通过源码编译的，所以不好。FreeBSD这不是都提供了嘛，还要怎么的，有点像人们的皮带，一天不系，你觉得不舒服，要勒紧吗？现代这帮人典型的吃现成的，导致了FreeBSD的没落。<br/>源码包自然有必要提供, 但是你不能要求每个用户用一个软件都编译半天吧，源码的好处是只要你微调得当，性能是最大化的<br/>，然并卵，现在机器性能都挺好，还有8M的嵌入式没法支持，什么不支持，我是发现还有比我懒的人了，听说有交叉编译也不会是在8M上编译啊。<br/><br/>前企业邮箱杀rpc的shell，都快忘记了，做个备份： http://jackxiang.com/post/1273/&nbsp;&nbsp; 2008-9-23 18:31 八年前的事情了。<br/>从Solaris 到FreeBSD再到linux（Centos），其最后居然是linux 居上，而像sun的java被收购，最后FreeBSD的开源太底层（基于系统OS开源），BSD 的代码不是被控制在任何一个人手里，而 Linux的内核基本上被 Linus Torvalds ( Linux创始人)所控制，BSD 并没有单一的人来说什么可以或什么不可以进入代码。但BSD太自由了难度反而大了，人少了是根本原因，再就是商业化的需求没有满足到，被linux干下坡路了，但是，Debian Linux操作系统创始人去世 年仅42岁 ....，我想这个事件会给linux带来不可估量的损失，为什么，debian linux向FreeBSD学习port技术后，发展出的ubutu系统..不说了，反上这个哥们算是能善于学习，他死了...linux社区未来不太好说，但会有波澜是肯定的了。<br/>————————————————————————————————————————————————————————————————<br/>PHP的数据库连接池一直以来都是一个难题，很多从PHP语言转向Java的项目，大多数原因都是因为Java有更好的连接池实现。PHP的MySQL扩展提供了长连接的API，但在PHP机器数量较多，规模较大的情况下，mysql_pconnect非但不能节约MySQL资源，反而会加剧数据库的负荷。<br/><br/>假设有100台PHP的应用服务器，每个机器需要启动100个apache或fpm工作进程，那每个进程都会产生一个长连接到MySQL。这一共会产生1万个My SQL连接。大家都知道MySQL是每个连接会占用1个线程。那MYSQL就需要创建1万个线程，这样大量的系统资源被浪费在线程间上下文切换上。而你的业务代码中并不是所有地方都在做数据库操作，所以这个就是浪费的。<br/><br/>连接池就不同了，100个worker进程，公用10个数据库连接即可，当操作完数据库后，立即释放资源给其他worker进程。这样就算有100台PHP的服务器，那也只会创建1000个MySQL的连接，完全可以接受的。<br/><br/>首先，环境约定如下：<br/>说一下测试环境吧：OS CentOS 7.1 x86；PHP 5.4.44；Mysql 5.7.9-log；swoole-1.7.22。<br/><br/>一）开始编译，网上好多都是编译过了，但是出现某些函数找不到运行时会警告，特别标名一下原因：<br/>以前确实没有好的办法来解决此问题的，现在有了swoole扩展，利用swoole提供的task功能可以很方便做出一个连接池来。<br/>编译时要注意一下：<br/><textarea name="code" class="php" rows="15" cols="100">
[root@iZ25dcp92ckZ swoole-src-swoole-1.7.22-stable]# phpize 
[root@iZ25dcp92ckZ swoole-src-swoole-1.7.22-stable]#./configure --enable-sockets --with-php-config=/usr/local/php/bin/php-config --enable-swoole-debug -enable-async-mysql --enable-ringbuffer --enable-async-mysql=/usr/local/mysql/
[root@iZ25dcp92ckZ swoole-src-swoole-1.7.22-stable]# make &amp;&amp; make install
</textarea><br/>还是出现：[2015-06-29 18:58:24 *9092.0] WARN zm_deactivate_swoole: Fatal error: Call to undefined function swoole_get_mysqli_sock()<br/>因为参数：编译swoole时需要加enable-async-mysql参数来开启 swoole_get_mysqli_sock<br/><br/>php -r &quot;print_r(get_defined_functions());&quot;&#124;grep swoole_get_mysqli_sock 并没发现有这个函数~可能新版本移掉了吧。<br/>实践发现，这块swoole的官方对这块的编译参数并不太提及，不是没有这个函数，这个swoole_get_mysqli_sock函数通过源码里发现是有的。<br/>是因为configure里出现了问题，出现在这儿，对比一下编译且运行Ok的./configure选项就知道了，正确的如下：<br/><textarea name="code" class="php" rows="15" cols="100">
[root@iZ25dcp92ckZ swoole-src-swoole-1.7.22-stable]# ./configure --enable-sockets --with-php-config=/usr/local/php/bin/php-config --enable-swoole-debug -enable-async-mysql --enable-ringbuffer --enable-async-mysql
</textarea><br/>一些博文里的：--enable-async-mysql 后面有路径，这块在swoole-src-swoole-1.7.22-stable里是没有这个路径反而编译正确了。<br/>————————————————————服务端的代码贴在这儿—————————————————————————————<br/>代码如下：<br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php
class DBServer
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;protected $pool_size = 20;
&nbsp;&nbsp;&nbsp;&nbsp;protected $idle_pool = array(); //空闲连接
&nbsp;&nbsp;&nbsp;&nbsp;protected $busy_pool = array(); //工作连接
&nbsp;&nbsp;&nbsp;&nbsp;protected $wait_queue = array(); //等待的请求
&nbsp;&nbsp;&nbsp;&nbsp;protected $wait_queue_max = 100; //等待队列的最大长度，超过后将拒绝新的请求
 
&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp; * @var swoole_server
&nbsp;&nbsp;&nbsp;&nbsp; */
&nbsp;&nbsp;&nbsp;&nbsp;protected $serv;
 
&nbsp;&nbsp;&nbsp;&nbsp;function run()
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$serv = new swoole_server(&quot;127.0.0.1&quot;, 9508);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$serv-&gt;set(array(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;worker_num&#039; =&gt; 1,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;));
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$serv-&gt;on(&#039;WorkerStart&#039;, array($this, &#039;onStart&#039;));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//$serv-&gt;on(&#039;Connect&#039;, array($this, &#039;onConnect&#039;));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$serv-&gt;on(&#039;Receive&#039;, array($this, &#039;onReceive&#039;));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//$serv-&gt;on(&#039;Close&#039;, array($this, &#039;onClose&#039;));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$serv-&gt;start();
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
 
&nbsp;&nbsp;&nbsp;&nbsp;function onStart($serv)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;serv = $serv;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for ($i = 0; $i &lt; $this-&gt;pool_size; $i++) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db = new mysqli;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db-&gt;connect(&#039;localhost&#039;, &#039;root&#039;, &#039;**PWD**&#039;, &#039;*DbName***&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db_sock = swoole_get_mysqli_sock($db);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swoole_event_add($db_sock, array($this, &#039;onSQLReady&#039;));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;idle_pool[] = array(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;mysqli&#039; =&gt; $db,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;db_sock&#039; =&gt; $db_sock,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;fd&#039; =&gt; 0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;Server: start.Swoole version is [&quot; . SWOOLE_VERSION . &quot;]&#92;n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
 
&nbsp;&nbsp;&nbsp;&nbsp;function onSQLReady($db_sock)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db_res = $this-&gt;busy_pool[$db_sock];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mysqli = $db_res[&#039;mysqli&#039;];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$fd = $db_res[&#039;fd&#039;];
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo __METHOD__ . &quot;: client_sock=$fd&#124;db_sock=$db_sock&#92;n&quot;;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($result = $mysqli-&gt;reap_async_query()) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ret = var_export($result-&gt;fetch_all(MYSQLI_ASSOC), true) . &quot;&#92;n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;serv-&gt;send($fd, $ret);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (is_object($result)) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysqli_free_result($result);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;serv-&gt;send($fd, sprintf(&quot;MySQLi Error: %s&#92;n&quot;, mysqli_error($mysqli)));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//release mysqli object
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;idle_pool[] = $db_res;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset($this-&gt;busy_pool[$db_sock]);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这里可以取出一个等待请求
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (count($this-&gt;wait_queue) &gt; 0) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$idle_n = count($this-&gt;idle_pool);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for ($i = 0; $i &lt; $idle_n; $i++) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$req = array_shift($this-&gt;wait_queue);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;doQuery($req[&#039;fd&#039;], $req[&#039;sql&#039;]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
 
&nbsp;&nbsp;&nbsp;&nbsp;function onReceive($serv, $fd, $from_id, $data)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//没有空闲的数据库连接
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (count($this-&gt;idle_pool) == 0) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//等待队列未满
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (count($this-&gt;wait_queue) &lt; $this-&gt;wait_queue_max) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;wait_queue[] = array(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;fd&#039; =&gt; $fd,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;sql&#039; =&gt; $data,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;serv-&gt;send($fd, &quot;request too many, Please try again later.&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;doQuery($fd, $data);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
 
&nbsp;&nbsp;&nbsp;&nbsp;function doQuery($fd, $sql)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//从空闲池中移除
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db = array_pop($this-&gt;idle_pool);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @var mysqli
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mysqli = $db[&#039;mysqli&#039;];
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for ($i = 0; $i &lt; 2; $i++) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result = $mysqli-&gt;query($sql, MYSQLI_ASYNC);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($result === false) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($mysqli-&gt;errno == 2013 or $mysqli-&gt;errno == 2006) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mysqli-&gt;close();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$r = $mysqli-&gt;connect();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($r === true) continue;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$db[&#039;fd&#039;] = $fd;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//加入工作池中
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;busy_pool[$db[&#039;db_sock&#039;]] = $db;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&#125;
 
$server = new DBServer();
$server-&gt;run();
</textarea><br/><br/>rango有一个更详细的连接池服务端的代码放这儿了：<br/>http://rango.swoole.com/archives/288<br/><br/>二）客户端代码如下：<br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php
function dbcp_query($sql)&#123;
&nbsp;&nbsp;&nbsp;&nbsp;$link=new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_SYNC);//TCP方式、同步
&nbsp;&nbsp;&nbsp;&nbsp;$link-&gt;connect(&#039;127.0.0.1&#039;,9509);//连接
&nbsp;&nbsp;&nbsp;&nbsp;$link-&gt;send($sql);//执行查询
&nbsp;&nbsp;&nbsp;&nbsp;die(var_dump($link-&gt;recv()));
&nbsp;&nbsp;&nbsp;&nbsp;return unserialize($link-&gt;recv()); //这行会报错，注释掉了：PHP Notice:&nbsp;&nbsp;unserialize(): Error at offset 0 of 292 bytes in /data/htdocs/mysql.swoole.com/mysqlSwooleCli.php on line 6
&nbsp;&nbsp;&nbsp;&nbsp;//swoole_client类析构时会自动关闭连接
&#125;
$sql=&quot;SELECT * FROM `boblog_links` limit 1&quot;;
$dbRetArr = dbcp_query($sql);
var_dump($dbRetArr);
</textarea><br/><br/>三）运行一下看有没有返回：<br/>[root@iZ25dcp92ckZ mysql.swoole.com]# php&nbsp;&nbsp;mysqlSwooleCli.php <br/>string(292) &quot;array (<br/>&nbsp;&nbsp;0 =&gt; <br/>&nbsp;&nbsp;array (<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linkid&#039; =&gt; &#039;3&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linkname&#039; =&gt; &#039;猪头党乐园&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linkurl&#039; =&gt; &#039;http://www.gipsky.com/&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linklogo&#039; =&gt; &#039;&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linkdesc&#039; =&gt; &#039;&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linkgptoid&#039; =&gt; &#039;19&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;linkorder&#039; =&gt; &#039;3&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;isdisplay&#039; =&gt; &#039;1&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;empty1&#039; =&gt; &#039;&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#039;empty2&#039; =&gt; &#039;&#039;,<br/>&nbsp;&nbsp;),<br/>)<br/>&quot;<br/><br/>最后，这个到底是不是真长连接在mysql这儿了呢？我们验证一下，连接mysql看下：<br/><textarea name="code" class="php" rows="15" cols="100">
mysql&gt; show processlist;
+------+------+-----------+-----------------+---------+------+----------+------------------+
&#124; Id&nbsp;&nbsp; &#124; User &#124; Host&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; db&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; Command &#124; Time &#124; State&nbsp;&nbsp;&nbsp;&nbsp;&#124; Info&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
+------+------+-----------+-----------------+---------+------+----------+------------------+
&#124; 8047 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8048 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8049 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8050 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8051 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8052 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8053 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8054 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8055 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8056 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8057 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8058 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8059 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8060 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8061 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8062 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8063 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8064 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8065 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;616 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8066 &#124; root &#124; localhost &#124; jack&#039;sDbName &#124; Sleep&nbsp;&nbsp; &#124;&nbsp;&nbsp;160 &#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;
&#124; 8144 &#124; root &#124; localhost &#124; NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; Query&nbsp;&nbsp; &#124;&nbsp;&nbsp;&nbsp;&nbsp;0 &#124; starting &#124; show processlist &#124;
+------+------+-----------+-----------------+---------+------+----------+------------------+

</textarea><br/><br/>还有问题？优化如下，我提出我为何要坚持引入RPC的原因：<br/>摘录来自：http://bokjan.com/prog/php-db-conn-pool-with-swoole.html&nbsp;&nbsp;现在没了。<br/>现在可以运行了，本次实验是成功的。但是如果使用dbcp_query()这个函数，每次调用都要发起一次TCP连接，执行的语句多了，肯定出问题。这个时候我们就可以把它封装成一个类了，单纯实现这个会比较的简单，但是打出来要点时间，这里就不写了。<br/><br/>我的看法：对于这位兄弟提到的每次调用都要发起一次TCP连接，而这个问题在RPC里直接供给前端WEB会得到很好的解决，为什么呢？<br/>目前这种搞法是：一个web请求来到服务器后，这个服务器再生成一个连接swoole的连接池的端口，这儿是：9508端口它再去长连接Mysql的3306端口。<br/>那么，如果每次来一个用户这个9508就会再进去一个连接，再到Mysql的3306接口，这块这个9508取到数据完后，销毁这个socket的fd句柄，来得越多，<br/>这个是不是就会出现很多句柄在这儿生生死列，也就是上面这个兄弟讲的每次调用都要发起一次TCP连接，执行的语句多了，肯定出问题。不是封装的事，<br/>而这种架构在我看来本来就有问题，为此，我提出我的一个引入RPC的看法，以解决每次都生生死死的效率问题，思路如下：<br/>这块RPC引入带来了额外的XDR兼容跨平台的数据接口的打包、解包、返回同样需要打包，再到客户端揭包的一个客外的socket数据流量，不是RPC最大8K性能问题所在。<br/>架构如下：在每台服务器上的RPC服务器上启动一次性多个RPC，每个RPC连接一个Mysql的长链接，而rpc的client直接放到Apache/nginx的cgi目录下，这样从<br/>Web端传过来的请求，直接通过WEB传到RPC服务器器直达Mysql，而这个RPC服务服务这块并不需要重新销毁重新生成请求，有更多连接过来只是再多起几个RPC的server（同时Mysql的长连接也多了几个），也就是说通过RPC的Client与RPC的Server长连接类似KeepAlive，直接打通了Mysql数据库，这样提高了效率，因为这个连接池不管怎么样，都需要给web端来访问，当前解决的就是web端用户一下就来了很多人的一个问题，还形成了可扩展的一个Client和Server模型。<br/>总之的总之，Rpc调用远程就像调用一个函数一样，避免了重新销毁重新生成请求的一个消耗，也避免了下面的serialize和unserialize的一个性能问题，也就真正实现了最大化性能和架构可扩展的解决方案，也就是为何我建议加一个RPC功能，把底层做到极致，通过简单配置就能打通Mysql的各个表结构。<br/><br/>最后：今天做的是数据库连接池的实现。从上面的代码我们可以看见，程序与连接池之间的数据交换是使用php序列进行的。这里会有两次的serialize、unserialize，绝对也是一个开销。Rango的文章里面有说到“MySQL是每个连接会占用1个线程……大量的系统资源被浪费在线程间上下文切换上……不是所有地方都在做数据库操作，所以这个就是浪费的。”再看看他那篇文章的假设：“假设有100台PHP的应用服务器，每个机器需要启动100个apache或fpm工作进程。”这肯定不是一个小项目，确实就适合用连接池了。写的东西是用来练手或者解闷儿的？常规方法已经可以了。不要忘了一点：程序与连接池的交互我们应该还是用Swoole实现的，Swoole可是一个TCP/UDP扩展。而Swoole只能运行在Linux平台上面，但是Linux平台上的MySQL是可以用UNIX Socket通讯的。<br/><br/>来自：http://rango.swoole.com/archives/265<br/>http://bokjan.com/prog/php-db-conn-pool-with-swoole.html
]]>
</description>
</item><item>
<link>https://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [实践OK]Swoole、PHP与MySQL：连接池,swoole扩展实现真正的PHP数据库连接池。]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>https://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>