本文未经许可禁止转载,如有转载意愿请与作者联系。
我们团队现在做的是一个微信第三方平台项目,项目起步时间不长,到现在差不多两年。起初是个探索性的小项目,但是随着业务的发展,已有的结构渐渐不能满足业务需求以及高峰时段的压力;不仅如此,一些历史问题也给我的开发流程带来了不少问题。所以这半年以来,再满足产品高速迭代的需求的前提下,我们也对后台框架以及服务器的结构做了持续的调整和优化。本文主要是针对后台部分的变动进行整理。
项目开始的时候,组里还有其他两个项目处于维护阶段。并且这个项目后台的起步也是直接从原来的项目里 copy 了部分结构代码并在这基础上进行改动,所以有很多历史遗留问题在里面。项目本身的框架还是 11 年左右的一个 cakePHP 的变种框架,项目框架从来没有更新过,甚至项目本身的 String
类封装每次调用都会触发 bug。
在服务器上,三个项目最开始的时候是共享所有的服务器资源的。而较老的项目由于只维护不开发,一些业务组件,比如 memcached、sphinx 中文版(Coreseek)以及一些 PHP 的扩展早已没有更新,但是每次服务器变更的时候还得考虑这些东西。
最近半年,通过不断的调整和修改,我们解决了大部分历史遗留问题,并成功升级到 PHP7。
PHP 最近几年发展势头也是很快,Composer、Laravel 等组件和框架逐渐流行起来。借助第三方的力量能够很大程度的简化自己的工作、提高开发效率。
虽然以前项目中也有引入 PHPExcel 等第三方库,但都是通过下载源码丢到项目本身的方式来做的。这样做的问题是引入并不方便,并且一般不会及时通过升级来解决一些第三方库的 bug、漏洞等问题。为了提高框架的基础能力,我们在框架中引入了 Composer 。
在 Compoer 的引入的同时我们也引入了一些优秀的库来解决基础问题。之前项目中的 cURL 封装到处都是,不统一不是很理想,所以在有了 Composer 之后项目中直接加入了 guzzle 。同样,为了解决异常日志栈的记录问题, monolog 也被加入到项目中。
这其中最大的一个变更是,受限于框架底层实现的问题,框架本身的 ORM 极其难用,并且整个是基于 mysql_query
来实现的。所以我们设法直接在框架中集成了 Laravel 的 ORM eloquent
减轻痛苦。
至此,项目解决了四个基本问题:
这些改动都是为了解决开发上的问题。但开发上某些问题依旧存在:老的代码难以改动,并且 PHP 5.5 之后 mysql_query
系列的方法已经逐步被废弃。所以在后续的修改中一次性将这些方法都替换成了 mysqli
的实现,这也使得后续的 PHP7 升级工作能够继续进行下去。
项目的拆分分为两个部分,一个是逐步隔离两个老项目和新项目之间的资源、使新项目能够摆脱历史包袱快步前进;第二个是对新项目本身的拆分工作。
上文中提到,项目起步时的基础代码和环境都是从原来的两个项目里直接 copy 过来的,甚至硬件资源都是公用的。因为几个项目整个的战线拉的很长,所以一些依赖的组件和服务有些都是很古老的,甚至是没有继续维护的。也有一些内部的组件依赖。这导致无论想做什么新的尝试都需要瞻前顾后,总是要考虑到是不是会影响到原来的东西。
由于硬件资源完全共享,而一些业务高峰时间带来的压力总是会导致服务器资源占用飙升,几个项目的服务同时挂掉,并且经常短时间内难以恢复正常。为了解决这个问题,我们对之前的两个项目和这个项目的物理资源分配做了一些调整,并做了隔离。
在项目上,最开始这个项目的所有功能模块,包括消息转发系统和主站部分全部都是耦合在一起的一套代码,由于框架本身的问题,效率并不高。在项目的改进中,我们逐渐分离了核心的消息系统部分并采用性能更高的框架(phalcon)完全重写。硬件上消息系统和主站也进行了分开部署,使两个部分不会相互影响。
技术总是在持续的优化中进步,项目改进的脚步也从不曾停止。
在持续的改进过程中,我们继续进行了以下的部分工作:
E_NOTICE
及以上的告警,尽量减少 bug 并优化代码逻辑,搭建 sentry
平台记录线上的错误及异常日志,便于查找和及时修复; supervisor
集中管理; PHP7 带来的内存使用量降低和性能优化是很令人心动的,在很长一段时间里,受限与项目环境的原因,项目基本上没有可能在短期内升级。
但在升级 PHP7 之前实际上已经进行过另外一次升级工作。起因是机房迁移,需要将所有的服务器都迁移到新的机器上去。借助这个机会,我们把所有的服务组件都进行了整理和重新编译,并且相应的升级了 Nginx(1.4 到 1.8)、openssl(解决之前 openssl 爆出的一些列安全问题),也将 PHP 从 5.4 升级到了 5.6。
在这期间,由于对 MySQL 存储 emoji 表情有需求,通过较长时间调研和实践,最终也将 MySQL 从 5.5 升级到了 5.7(但请注意:MySQL 主从同步,无法直接从 5.5 同步到 5.7,只能通过 5.5 -> 5.6 -> 5.7 这种方式)。
之后的几个月里,项目基本上保持着告诉稳定的状态运行着。经过一段时间的等待,项目需要的几个开源的核心扩展完成 PHP7 版本的开发工作之后,我们也开始进行升级 PHP7 的工作。
升级的工作主要包括两部分:检查语法兼容性,解决扩展兼容问题。因为有些扩展并不是来自开源社区,需要自己手动去改。
整个升级的节奏也是分成了两个部分:先动消息框架,再升级主站。由于两个老项目的状态,所以决定不对其进行变更,还是维持在原来的状态。丢掉包袱才能快步前进。
消息框架依赖较少,主要就是 phalcon 和 redis,所以升级过程比较顺利。
主站依赖的内部扩展较多,语法兼容性问题也比较多。所以使用了开源项目检查语法兼容性。对框架底层做了一些改动,这里面最主要的还是从 mysql
换到 mysqli
的工作。
扩展部分在编译过程中就可以把大部分不兼容的语法暴露出来,进行修改并重新编译测试即可。
总结起来,一共经历过以下步骤:
mysql_query
替换为 mysqli
; 随着业务的发展,项目也会面对越来越多的问题。技术上不断前进,不断提高个人水平。做好迎接更多的挑战的准备,也总会有更多的惊喜。