PHP+MySQL真是皮糙耐操的组合
几个项目内容彼此差异很大,但都对支付、结算部分具有很高的精度要求,其中一个,具有大量的实时同步的数据。
大量到什么程度呢?大约平均每秒获取30条更新数据,这30条数据,实际触发200条左右的数据比较和更新。去年大约9、10月份在为这个项目做准备的阶段,我主观上觉得PHP+MySQL很难胜任此任务,一度对.net、Java、Scala、golang,以及不同的数据库,包括pgsql、sqlserver、mongodb都做了很多的调研与测试准备,后来一度选择了Scala的方案。不过真的动手的时候,静态语言的特性,真的让我有很多不适应的地方,尤其是servlet容器,每次更新都要reload??这方面可能我真的被动态语言宠坏了。
第一阶段编写了部分重构和改进的代码,令我决定放弃了选择静态语言去改造整个项目的方案。因为在线部分的系统业务实在太庞大了,而且很多业务逻辑,早前开发的PHP的版本,已经封装得是非常健壮和完善,唯一能说服我去改造的,只有语言之间的性能差异。经过了一些比对,尤其是servlet实际的部署更新方面与现有PHP的对比,我做了一个特性列表的比对,并且每个特性都实际测试了servlet模式和PHP模式的比较,最终决定放弃选择静态语言改造整个项目的方案。
在Web系统的构建上,PHP支持动态更新是一个非常重要的特性,这也许已经成为他区别现有所有的Web开发语言中,一个最大的优势了。Ruby、node.js、golang、Java,最多只能做到模板动态更新,发布模式下,类库文件属于调用时才加载到位的机制、永不释放、或编译成二进制文件、预先即加载。
放弃了重构的方案,就要转换思路了。原来的设想,是以Web作为系统的核心,原本改造的一个目的是,让Web具有更加主动的执行一些操作和任务的功能,让他能主动的去发起和执行一些任务。但实际的情况下,第一阶段已经用PHP开发的代码,我并不想破坏或者重构??因为在业务逻辑的层面,他并没有问题。我完全可以把已经开发的Web视作一个WebService的点,剩下的,就是部署多个的Service点,将外部的数据接口,和WebService对接,并由WebService发起对这些Service的管理与监控。
大概的情形就如下面的拓扑图:
每个外部的Service,只包含实现自己本身所要执行操作的最小的程序逻辑,核心业务逻辑交给WebService。并且Service之间并不通信,彼此不需要知道彼此的存在,必须做到,随意添加、随意部署、随时更新。他们就像是章鱼的触手,但有着各自更明确具体的功用和任务,但是他们不具有思考和判断的能力,他们只是准确无误(尤其不能时误)的去执行不同的任务。
确定这个思路的时候,我并不准确的知道他的可行性,这个环境最核心的环节是WebService的容纳能力,这一点也是我最无法确定的。不过随着时间的推进,我已经没有更多的选择了。外部Service部分,我选择了node.js,因为npm的丰富度,以及我本身对js的熟悉度。
Service开发的难度不高,很快就封装了一个任务调度器和WebSocket Server。经过长期密集的监控,任务调度器的时间延迟,在可接受的范围内,这一点我之前测试node.js的时候就知道了,单核条件下,高密集的压力下,他会毫不思考的直接将CPU可用的计算能力用到满载为止。
很快的,新的Service部署上线了,校准数据,WebService业务逻辑的调整,这些自不必说了。我一直所担心的,WebService上可能发生的问题,居然一点都没发生??尤其是在测试服务器上,那只是一台最最低廉的服务器(即弃即用,只要他系统一崩溃,我就直接从镜像重装),单机运行,居然丝毫不乱。PHP+MySQL的耐操能力,真的超乎我的想象,当然,因为事前对起容纳能力和计算能力的担心,针对业务逻辑的特点,我也设计了多层的缓存解决方案,所以这里还得加上Memcache。
但是这些用node.js写的Service,其健壮度和稳定性真的很低,经常无缘由的停止服务,而且内存的调度和释放方面,也不尽如人意。当然了,本身在开发Service的时候,我并没有刻意的去优化(基本上可以用粗犷来形容),毕竟有很多事情还没得到实践验证,没必要过度的耗神费脑子。在我预算中,这部分迟早是要重构的??本身的逻辑也并复杂,最终的方案也未必会选择node.js。
结合最早的调研和测试,对Service的重构,现在的关注点落在了jvm和golang上。jvm经过了这么多年的风霜洗礼,他的内存管理已经比较完善,而且对于其调优的经验与分享,google一搜一大把,可参照的依据也非常之多(再到Google趋势上看看,这世间所有的开发语言里面,Java也是遥遥领先),而且之前我已经开了一些可用的代码。golang绝对是一个杀手级的语言,我相信这个语言绝对拥有比jvm更高的可调优的运行性能,不过看到他的指针符号,我真的有些心有余悸,而且他的变量是可污染的,这个有些麻烦啊。