AI营销前端性能优化之路
### 引言:
在这个互联网时代里,千千万万的网站成了人们日常生活中不可或缺的一部分,人们通过网站浏览新闻、购物、管理平台,等等。试想一下,当你打开一个网页时,页面半天无法打开,图片一条一条的加载出来,这这会是怎样一种体验?如果很多人都会像下图中的人一样抓狂了吧!
![网络响应慢抓狂](https://bj.openstorage.cn/v1/iflyad/gnometest/tech/crazy.jpg)
什么样的网站能够给用户更好的体验,保留更多的用户?在AI营销投放管理系统运营的两年里,也时时刻刻面临着这样的问题。本篇文章中介绍了AI营销投放管理系统不同阶段在系统响应时间上做的种种优化,帮助小伙伴们了解网站性能优化的一些方法。
### 阶段一:快速开发,简单部署
在AI营销投放管理系统上线初期,面对的用户主要是是内部投放的运营和优化人员,在这个阶段平台功能相对简单,除了基本的活动、订单管理栏目,投放效果报表栏目和用户信息管理栏目之外,一直在快速开发各种新功能,用于支持投放需求。
最初的AI营销投放系统结构相对简单,按照如下结构部署:
![阶段一架构图](http://iflyad.bjdn.openstorage.cn/gnometest/tech/tech_01.png)
按照这种架构部署,在前期用户不多,投放需求较少的情况下能够基本满足运营投放管理需求,但随着投放业务的增加,渐渐暴露出一些性能问题,其中最为突出的则是页面加载速度慢问题。经过排查定位发现主要由以下两个原因导致页面加载速度慢。
#### 页面静态资源加载慢
优化方案:
1) 调整订单页面素材访问方式,将所有的素材更改为CDN素材
![cdn图片加载效果](http://iflyad.bjdn.openstorage.cn/gnometest/tech/cdn_pic.png)
使用了CDN后,等于是原有情况复杂的网络中,开启了一条快速通道,能够极大的加速图片等静态文件的访问。
![cdn原理](http://iflyad.bjdn.openstorage.cn/gnometest/tech/cdn_case.png)
2) 在nginx访客规则里增加静态文件分离规则
```
location ~ .*.(gif|jpg|jpeg|png|bmp|swf|js|css|woff|ttf|TTF|svg|pdf|docx|md|ico|txt|xlsx)$ {
root /***/***/develop/dsp_web/public;
if (-f $request_filename) {
# 设置一天的缓存
expires 1d;
break;
}
}
```
对网站静态文件设置了expires后,服务器响应文件内容时,同时响应etag标签(内容的签名,内容一变,他也变)和last_modified_since 2个标签值,当浏览器下次去请求时,头信息发送这两个标签,服务器检测文件有没有发生变化,如无,直接头信息返回etag和last_modified_since,浏览器知道内容无改变,于是直接调用本地缓存。
这个过程中虽然请求了服务器,但由于请求返回的数据极少,可以很大程度上缩短请求响应时间。优化后当二次请求网页图片、CSS和JS等静态文件时效果如下:
![expires二次响应效果](http://iflyad.bjdn.openstorage.cn/gnometest/tech/expires.png)
#### 模版加载请求过多
在订单编辑页面中会有多个素材需要按照一定的模版排列展示,在旧的逻辑里,每当展示一个模版时,都会事先根据模版id,获取模版布局内容,当订单中素材较多时,如一个订单里有50个素材,则需要遍历这50个素材,先发送五十次模版内容请求,再进行页面渲染,导致编辑页面渲染很慢。
优化方案:
由于系统使用的模版并不多,当订单中49个素材都是同一个模版时,实际上49个模版内容请求都是无意义的,因此,更改原有每次渲染模版请求一次的方式,页面加载时预加载全部模版信息,渲染模版时直接使用,减少大量模版信息请求,提升了订单编辑页面加载速度。
### 阶段二:访问上升,优化部署
随着业务的发展,用户量和数据量都有了一定程度的提升,系统访问量也随之上升,这时候单机部署的弊端开始逐渐显露出来。在系统运行中经常出现诸如高峰时段网站整体响应变慢、服务器压力过大服务挂掉等问题。
为了解决这些问题,我们对AI营销管理系统的部署方案进行了升级,于是便有了如下架构:
![阶段二架构图](http://iflyad.bjdn.openstorage.cn/gnometest/tech/tech_02.png)
1) 引入nginx负载均衡,启动多个前端node结点
AI营销管理系统前端使用nodejs Express框架,node主要用来渲染页面和转发接口请求,由于node是单线程运行,在访问量较大时,单节点处理能力不足,就会造成页面接口响应不及时问题。而启动多个节点后,相当于在原有单条流水线处理的基础上,增加了多条流水线处理前端请求,大大的增强了请求处理速度。
2) 增加备份结点机器,预防宕机
在增强了服务处理能力的同时,为了预防机器异常宕机,通过Nginx为Web服务增加了备份结点。
负载均衡和主从备份Nginx配置
```
# 负载均衡配置:
upstream dsp_web {
# 多个端口下的node实例
server 127.*.*.16:8081;
server 127.*.*.16:8082;
...
# 备份机器结点,在主结点工作正常时不会被访问
server 127.*.*.15:8091 backup;
}
server{
listen 80;
server_name market.voiceads.cn;
location / {
proxy_pass http://dsp_web;
proxy_set_header Host $host;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
...
}
```
在正常情况下,通过Nginx访问16机器上多个node结点,而15机器上的node结点不会被访问,当16机器出现宕机或服务异常退出时,Nginx会自动将请求转发到15机器上的备用结点,实际上等于是为Web端做了一层兜底。
### 阶段三:业务沉重,架构优化,业务解耦
当业务进一步发展时,业务逻辑也渐渐变得更加复杂,例如订单编辑操作,除了基本的订单信息更新外,还需要处理素材审核预判、发送中控通知消息等一系列逻辑。严重耦合的业务逻辑,一定程度上拖慢了系统的事务处理能力,而通过增加不同端口下结点提升并发能力的方式也带来了另外一个问题,每次上线时都需要重启多个结点,非常便于管理。
为此,系统架构又出现了如下的调整:
![阶段三架构图](http://iflyad.bjdn.openstorage.cn/gnometest/tech/tech_03.png)
1) 引入PM2进程管理
PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。
通过PM2可启动指定应用,并分配给多个子进程进行处理。
![PM2应用管理多子进程](http://iflyad.bjdn.openstorage.cn/gnometest/tech/pm2_list.png)
PM2同样支持对多个子进程进行监控。
![PM2子进程监控](http://iflyad.bjdn.openstorage.cn/gnometest/tech/pm2_monit.png)
2) 业务解耦
对业务中较为复杂的逻辑,进行结构,将部分实时性要求不高的逻辑剥离出去,开发对应的逻辑处理定时器任务,采用异步处理的方式完成逻辑处理。
如在订单复制和编辑的逻辑中,需要对新建的素材进行逻辑判断,如果素材已存在于系统中,且该素材已经通过运营审核,则将该素材直接默认置为内审通过。当单个订单素材数量超过20个时,订单新建和复制操作会被素材状态检查操作严重拖慢。把素材内审状态逻辑解耦,通过定时脚本处理后,可减少大量素材状态查询逻辑,提升编辑和复制响应速度。
### 总结:
在AI营销平台运营的两年时间里,为提高系统并发性能、优化页面响应速度我们做了如下几个方面的尝试:
1. 静态文件访问分离,增加缓存
2. 引入CDN,为资源文件加速
3. 增加负载均衡,提升并发
4. 业务逻辑解耦,异步处理
通过一次又一次优化,平台的性能也在逐步提升,但这并没有结束,在性能提升的路上我们还有很多地方可以去尝试,如更深入的挖掘CPU性能、改善应用程序逻辑、优化中间件配置、OS参数调优等等。让我们日后在探索中前行,将平台性能做到极致。