/首页
/开源
/关于
洋枪棒产品后端架构简单升级改造记录
发表@2018-09-13 09:15:22
更新@2023-01-21 22:47:40
文中以及标题中所有人名、公司名以及产品名均以化名方式出现。 上周日接到微信群里一个好友(后文中称XF)的求助,大概意思就是不知道为什么产品新注册用户开始猛增,导致服务器崩溃,在收到通知后通过紧急升级服务器配置到16核CPU和16G内存勉强支撑住了。这个产品的名字叫做YQB,所以标题中我就用洋枪棒来称呼产品了。 首先介绍一下他们产品原有的技术状况,整体是LNMP架构,PHP框架使用的是YII 2.0,http服务器自然就是nginx了,mysql、redis、memcache、php挤在一台服务器上,产品前端以app为主,网页只有一个官网。本来平时没这么多用户,突然由于路子打开了,导致每天以比原来百倍的用户新增量持续增长,所以,原有的架构开始腐化,开始出现卡顿、持续高负载。 XF这次求助主要是因为他们公司服务端只有两个人,而且工作经验都比较短,都不知道清楚该怎么改造才能适应以后,所以让我来出个解决方案。 其实讲道理,是没太大难度的。不过问题说回来,只说架构上的问题,我尽量不去掺乎具体的代码。所以,这次改造的目的就是如下几条: - 解体原有的巨无霸一体系统 - 将架构分层,每层都避免单点故障 - 更容易地进行横向扩展 - 更容易和安全地进行代码增量测试 - 彻底上线新业务的时候,不用停服 其实,一旦说机器卡,大家肯定张口就是“加机器”。然而,加机器也是有讲究的: - 首先是机器加到刀刃上,一加必中! - 其次是加的又快又方便 像洋枪棒这种原有的架构,加机器的时候就很难满足上面的两点要求。因为MYSQL、PHP-FPM、NGINX是拥挤在一台机器上的,所以这三个中任何一个出现性能上的瓶颈都会导致服务卡顿。如果说是MYSQL卡,实际上只需要升级MYSQL需要的部分即可,但是mysql、php、nginx拥挤在一起,机器升级了,但并不是升级在刀刃了,这个会很难受。其次是,这样加机器并不是很方便。虽然你可以制作一个镜像,然后通过镜像快速配置好第二台机器的软件环境,但是,第二台机器的mysql、redis以及memcache是完全没用的,还得用第一台机器的mysql、redis等等。 然后是,由于都是单点,所以一旦出现故障,就意味着服务将处于完全不可用的状态。 最后是,如果你有新的代码要上线,但由于测试并不充分,所以能不能可以只让一小部分用户会触发新的业务代码,一旦发现错误,就可以稳稳地回滚代码,代码上的问题不会影响大部分用户。 所以,为了满足一些这些要求,这次的改动就以下面为准: ![](https://ti-node.com/static/upload/6434067116227297281) 上述架构将原来的巨无霸单体系统进行了拆解分层,大体来说从上到下分为nginx,php-fpm,redis,mysql四层,总体来说,具体如下几个优点: - 避免了原来单点故障带来的停服风险。比如nginx挂了一台,那么最起码还有一台nginx继续提供服务 - 通过性能分析可以锁定是具体哪一层出现性能卡顿,只需要横向扩展该层的机器即可。比如通过观察,发现fpm层的没每台服务器cpu都很高了,那么只需要为fpm这一层新加一台机器即可 - 上线新的代码可以通过负载均衡流量权重入口来实验代码是否存在巨大故障而不影响绝大部分的用户。新的业务代码可以只先上到一台fpm机器上,然后负载均衡上为该台机器只分配一个很小的权重,这样通过小流量长时间观察就可以收集到是否有严重错误 - 负载均衡层的高可用可由云服务商提供 - rds的高可用由云服务商提供 - redis由云服务商提供的主从双机版本提供高可用 通过上述改造达成的新架构可以保证相当长一段时间内架构上健康程度。 下午,在与XF的商议过程中发现其在代码上的几处不合理的地方: - 用户的token存储在了mysql数据库中,每次访问都要去mysql数据库中查询token对应的用户信息才能完成完整的session,给mysql形成了巨大的访问压力 - 数据库没有使用pconnect长链接 - 将nginx+fpm更改为swoole http server 如果将上述两处代码修改一下,不仅机器数量可以缩减节省成本,而且整体的响应速度一定会继续得到一次提升。