优化调整历史项目点滴

1、项目历史

初到团队的时候,业务不多,只有3个项目和3个管理后台,部署在5台云服务器上。当时团队使用的PHP框架是公司自研框架,不过在开发了2个需求之后发现,不仅仅是开发效率出现瓶颈,数据库也出现了瓶颈。扩容以及使用缓存,解决了数据库压力之后,就开始了架构调整。

最近半年,通过不断的调整优化,开发效率的瓶颈已经被解决,团队开发节奏越来越顺畅,从原来的问题驱动开发 :) 已经慢慢转变成技术驱动开发。

2、项目分析

先说下当时项目开发的亮点:

  1. 公司自研框架提供接口调试,有安全校验
  2. 提供测试环境、预发布环境、线上环境
  3. 产品原型、UI素材比较专业

再分析下项目开发的劣势:

代码管理

使用SVN管理代码,人工同步数据库表结构之后,rsync发布代码,其中还需要检查代码中是否有环境配置没有替换成线上环境。

服务端环境

PHP版本还停留在5.3,web服务使用Apache。由于个人开发环境统一在一台测试服务器上,导致开发调试只能不断var_dump()。定时脚本使用cgi方式调用,crontab管理,有执行时间超时的可能。

开发效率

各个项目日志比较分散,日志信息不全,使用file_put_content()写文件。公司自研框架适合接口开发,出现H5活动需求,开发比较吃力。基础代码,都是使用复制粘贴的方式,加到各个项目中,容易出现基础代码不同的问题。

开发规范

数据库没有统一规范。当时团队一大半人喜欢Sublime开发PHP,代码风格也不够统一。

3、项目优化

项目的优化节奏按照以下优先级落地:

  1. 保证发布稳定
  2. 提高开发效率
  3. 提升服务性能
  4. 统一规范

保证发布稳定

  • 使用 Git 替换掉SVN,在一台空闲的服务器上搭建了 GitLab CE,同时团队统一使用小章鱼 GitKraken 代替Git命令行操作。当时团队内部PPT分享过Git的使用。
  • 使用Git命令发布代码替换掉rsync发布代码,后续由于服务器增多,使用shell脚本发布代码。
  • 写了一个 数据库表结构对比脚本,减少人工同步数据库表结构不一致风险。
  • 项目中所有 配置收拢 到了一个配置文件中,区分测试环境,预发布环境,线上环境配置,软链接到指定环境,方便环境切换,以及配置管理。
  • 使用 Cronsun 替换掉crontab管理定时脚本任务。

提高开发效率

  • 引入 Composer,使用开源社区提供优秀的库解决基础问题。
  • 引入 Monolog,舍弃file_put_content()用法,汇聚各个项目日志和web服务日志到了一个目录中,根据错误级别写到指定日志文件中,不同项目互相调用,使用TraceId串联日志。
  • 引入 Guzzlehttp,替换掉封装的到处都是的CURL。
  • 引入 Eloquent ORM,框架本身提供的ORM极其难用,并且查询数据库的代码分散难以维护。
  • 引入 RabbitMQ,之前的开发模式只有同步逻辑,就连登录、注册这些本应该非常干净的逻辑,方法中都包含数不清的其他需求代码 :) 引入之后,封装过使用接口,只提供了 publish 和 subscribe 两个方法,减少使用成本。
  • 有了MQ,就有了常驻的消费脚本,考虑到常驻脚本的稳定性,引入 Monit,并且配置 钉钉Robot,MQ中堆积消息包,就会发送钉钉通知。
  • 引入 Lumen框架 开发接口,当时开发一个H5活动v1.0时候,使用的还是自研框架,开发效率收到了很大的影响。引入Lumen框架之后,接到H5活动v2.0需求,收益比较明显。
  • 保留PHP5.3和Apache(80端口),引入 PHP7.1Nginx(8080端口)SLB(80端口)作为另外一条链路开发。这也是推进引入Lumen框架的另一个原因。
  • 使用 Lumen框架Inspinia管理后台模板,开发管理后台。当时考虑新的管理后台是否需要替换框架,讨论出来的结论是,抛开历史包袱,延用ThinkPHP框架和使用Laravel类框架,更赞成使用Laravel类框架。使用Laravel框架还是使用Lumen框架,出于减少团队内部框架数量考虑,更赞成选用Lumen框架。
  • 引入 团队内部开发的Composer包,Composer提供了加载Git代码的能力,刚好可以解决以前各个项目基础代码复制粘贴导致的代码不统一问题。现在的Composer包中包含分布式锁、日志、MQ等。
  • 使用 artisan开发定时脚本。原先定时脚本都是暴露接口,cgi方式调用,存在外网调用安全问题以及超时问题,调整成cli方式调用定时脚本后,开发考虑成本降低。
  • 搭建 本地开发环境,配合 XDEBUG 调试代码,FTP上传var_dump()调试代码的时光一去不复返。
  • 需求 开发文档 补充,团队中比较喜欢使用 PlantUMLMarkDown 写文档,上传到内网的 Confluence 中。
  • 提供 Swagger 接口调试页面。考虑到以后引入grpc或者thrift做RPC通信协议,Swagger接入成本比较小。

提升服务性能

  • 引入 Linuxbrew,编译PHP7.1,Nginx,Redis包,并且整个Linuxbrew放到Git中管理,减少新增服务器时候部署环境成本。
  • HTTP升级到 HTTPS,暂时还没有做到全站点HTTPS。
  • 开启 Opcache,配合开源web页面,清除缓存。
  • 部署 ElasticSearch集群,在引入ES之前,搜索一直是由MySQL的like查询实现 :)

统一规范

  • 推广统一PHP代码风格规范:PSR。
  • 代码分层清晰,加入(伪)枚举类。代码分层参考:Laravel 的中大型專案架構
  • 开发内部Composer包规范。
  • 数据库建表、索引规范。
  • 其他流程规范。

4、调整优化带来的问题

并不是不停地引入新鲜的血液,就能解决掉所有历史遗留问题。反而,在调整优化的这段时间内,额外带来了很多问题:

  • RabbitMQ很脆弱,内存问题可能导致RabbitMQ挂掉。
  • 无法知晓Monit进程是否挂掉。
  • vendor目录放到git目录中,composer加载内部开发的包出现git子模块问题。
  • Opcache缓存。
  • 引入Lumen框架,安全校验不够,对接客户端链路没有打通。
  • ...

5、 项目后续调整

现在几乎所有项目都跑在PHP7.1和Nginx上了。开发模式和一年前相比,已经大相径庭。架构也向微服务架构转变中,现在架构,还是落后时代很远。

微服务的征途,现在才刚刚开始:

  • 全站点HTTPS
  • JWT
  • 拆分更细的服务(PHP做服务?还是先用JAVA来吧)
  • grpc/thrift
  • etcd/zookeeper + qconf
  • ...

6、总结

现在的服务越来越稳定,开发效率也提高了很多。不断提升自己,才能迎接好下一轮挑战,说不定是惊喜呢。