ORM编写目的
php换姿势curd的老话题不断, 本orm是基于最近流行的swoole扩展而提出的解决方案, 韩天峰的swoole带给phper全新的编程思路, 原来php还可以常驻内存踢掉php-fpm支配环节, 甚至可以忽略nginx中间件搞起微服务。在nginx+php-fpm业务流程下, 正常的涉及php计算的用户访问处理流程是这样的:nginx的master进程发现用户访问并将请求信息移交给worker进程
worker进程路由到index.php(如果你配置写的完全正确的情况下)
location里面会命令nginx加载到nginx所夹带的fast-cgi模块
fast-cgi告诉nginx我要监听本机9000端口, 有事情就转发到9000端口
刚刚好php-fpm也在监听9000端口
php-fpm拿到传入的请求信号, 调起它自己的worker来处理
php-fpm调来的worker处理完毕, 丢还给nginx
nginx回传给访问用户。
swoole创始团认为, 要不要搞这么麻烦? 干脆省下一堆, 都一次性“预热”到内存里面来, 也不要php-fpm来调来调去, 如此, 就产生了常驻内存的php进程(或是一组master+worker)来处理特定的数据请求, 诸如此类的微服务模式。
关于断线重连
接着问题来了,常驻内存虽然看起来很美丽,可是Mysql的连接并不稳定, 韩天峰先生在swoole连接池、异步、断线重连(https://wiki.swoole.com/wiki/page/350.html) 这篇文章当中就有提到过MySQL连接不稳定的几个因素:
1、MySQL服务器一定时间内自动切断连接;
2、那种长期无查询占茅坑不拉屎的TCP连接会被MySQL切断回收;
3、主动用命令kill process杀死连接, 或者MySQL服务器重新启动
笔者隔一段时间会捕获到类似下面的错误Error while sending STMT_PREPARE packet. PID=xxxxx
# 实际就是下方这个报错导致的, PDOException错误代码为HY000
server has gone away
phper需要发明出一套名叫“断线重连”的轮子, 或者想出一套路子维持连接生命周期, 来解决这个问题。有人说搞连接池来解决,还是没有解决到点子上, 连接池里面的连接也是一样触发数据库的周期断线机制好伐……
关于Hprose抛出异常崩掉业务流程之坑
MySQL配置文件my.cnf里面的interactive_timeout和wait_timeout(特别是wait_timeout)选项, 改到3600, 也就是1小时, 你网站不至于连续1个小时都没人看吧? 做个网页爬虫1小时之内主动爬一下你的页面, 比如你开了2个worker, 那么1小时以内你要连续点两次页面来重置访问连接计数器, 不要改太长时间, 容易产生大量僵尸连接。
interactive_timeout和wait_timeout默认值为8小时。
唠叨一下报错填坑过程:笔者参考laravel 5最新的orm, 扒了一套方法is_break外加pdo精美的捕获, 做了断线重连, 但是会报Warning错误;
网上thinkphp5.x非正式版本也遇到过这方面问题, 运用了和laravel类似的解决方式, 同样, 用swoole在内存中持续使用的时候, Warning隔三差五该出的还是会遇到的。
以上问题, 得出结论, 只能选择发呆忽略。接下来的问题笔者项目用到yaf, 其定制的异常处理机制会捕获到hprose客户端抛出的io异常(EXCEPTION/FATAL ERROR)错误, 需要设法跳开这个错误, 否则yaf会把业务流程引向error处理机制上
曾尝试过在实例化pdo时将\PDO::ATTR_ERRMODE这个选项改成\PDO::ERRMODE_SILENT, 发现pdo实例调用prepare方法时, Warning会被包裹着hrpose的swoole发送到hporse客户端, 而客户端将Warning错误升级为异常级别抛出, 此时:服务端改用捕获pdo实例中的errorInfo方法取得数组或者errorCode方法来拿错误代码判断是否闪断;
使用try catch捕获异常(显然没门);
用@符号掩盖掉prepare这一句的Warning错误
以上都会触发Warning的前提下,在hprose调用swoole服务端的时候随后跟上一句修改报错等级, 以下是实际代码:$server = new Server('tcp://0.0.0.0:1314');
// 将E_WARNING屏蔽
$server->setErrorTypes(E_ERROR);
实测发现加或者不加这行配置, 结果都是一样的, 现有的Hprose还是抛异常。
以我半小时都没人点一下的小博客而言, 测试结果为: swoole自带的set方法有个提高worker数量, 可以用, 但Reactor必须等于1, 就解决报错的问题了。本人底层学的很菜, 原因未知, 稀里糊涂, 相关的参考文档 https://wiki.swoole.com/wiki/page/163.html
另外,仔细翻了下文档, 其中说到dns携带的参数里可以指定ATTR_PERSISTENT和ATTR_TIMEOUT两个属性, 经过实测, 未果, 该报警告还是报警告。另外, 据某些博客说ATTR_PERSISTENT在驱动层已经集成了连接池, 这可是个不错的消息(实际对这个问题还是没用)。
代码地址
使用说明
可实例化pdo操作类的基础模型类
如此一来, 再写一个BasicModel实例化这个pdo操作类就可以当基础模型来用了, 这个地址 http://wkwkk.com/article/98a742396c78db8ed15c32649c70e9c4.html 是一个在Yaf中读写分离的代码例子:
解决爬虫类脚本内存不断上升不释放的问题
对于小内存主机来说,如果你不去切割爬虫脚本的工作, 当然在php单任务生命周期内, 内存的升高问题是很难得到缓解的。
如果你偏偏就是不喜欢切割任务,那么看pdo操作类里面有一句:PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
将true改为false
关掉pdo缓冲操作来节省内存。