【AWS+Drupal应用案例】如何让一个千万级流量网站从一直挂机到起死回生?

BootDev成立之初,旨在为大网站提供自动部署解决方案。我们的优势,简单通俗地讲,便宜且快;专业地说,我们让大网站以低成本,快速度交付内容!我们有能力在客户自己的AWS账号下部署一个自动伸缩架构,支持高流量高可用,减省网站使用云的学习周期和使用风险。


BootDev拥有7年的Drupal经验,Drupal也是我们最擅长的东西之一。众所周知,Drupal以其极高性能要求著名,却同样也是世界上最难的开源CMS,这个没有之一。大言不惭地说,BootDev都能把Drupal做好,还有其他什么网站做不好?


2014年末的时候遇到这样一个客户,这是一个旅游咨询媒体的中大型drupal+AWS网站,正好是两者的结合。

当时他有5个子网站,PV数为150万/月,存在以下一些情况:

  1. 网站cron job定时任务一直会让服务挂掉,每周需要重启服务器解决。

  2. 有8个网页服务器节点(Web nodes)和1个数据库,MemCache,CDN,AWS S3都已部署

  3. Git还没有架好,无法直接部署代码到8台服务器

  4. 每个月AWS服务器支出在8000 USD左右,价格昂贵

  5. 服务器一直处于高负载状态,cron job永远结束不了

  6. 图像被储存在不同文件架构和系统中

  7. 缓存访问率低

  8. 没有浏览器缓存

  9. 相比亚洲类似的网站(如 cityweekend.com / scmp.com)7人左右的技术团队,这个客户仅有前端工程师1人

客户网站的情况可以说非常不妙,但是我和团队的小伙伴临危受命,力挽狂澜。


我们从Drupal网站本身以及AWS服务器两方面双管齐下做了改进,并直接提供的是一个先进的后台和完善的框架。对网站主而言,不只是起死回生的救命稻草,更是省去前期艰难的学习周期和冗长的架构建设。以下就是我们当时的架构图:



完成制定架构,我们进行了以下调配。


<AWS 调配>

  1. 架构的版本管理不可少

    建立一个新的架构是费时费力费钱的,首先你得应对成千上万条参数,而且你不知道其中的哪条参数是对的,哪条会毁了你整个架构。BootDev因此相信,架构必须也要做版本管理,当然我们也是这样进行的。我们可以在一个真实的生产环境下,即时返回到上一个版本的架构,这样大大减少了因为调配或某些错误造成的损失。我们自己本身会通过AWS Cloudformation和OpsChef部署一个自动伸缩架构到我们的网站,任何针对架构的操作都有版本管理,因此遇到任何情况,我们可以分分钟返回。

  2. 自动伸缩,自如应对流量波峰波谷,更省钱。

    正如上一条提到的,由于自动伸缩架构的置备,我们因此无需为网站流量高峰担忧。之前一直standby的8台服务器也相应地减到2台,大小由Xlarge变成Large。当流量来临时,网络服务器的扩张过程只需10分钟,支付费用也即付即得,网站主无须为预先留存的机器付钱,只要为自己使用的机器付钱。

  3. AWS Cloudforamtion 支持使用多个域(Domain Sharding)

    这意味着你可以绑定多个域名指向你的CDN资源(分布),所以访客的浏览器可以在不同域名同时下载网页。

  4. AWS动态CDN的完美运用

    我们把域名指向Cloudfront,而Cloudfront会像代理服务器一样从原本的地方拿到数据。这样可以防止DDOS,这个设想和CloudFlare是一样的。不止如此,动态CDN可以帮助我们当网站处于高访问量状态下,无需真正访问服务器。这个科技难点在于,每个behavior里的任何path,都有很多应用参数需要自己调配,当然你也可以选择把这一切可以交给BootDev。

  5. AWS S3支持元数据,我们可以分批设定存储在AWS S3里图像的header,这样可以影响浏览器和CDN的缓存行为。比如,你其中一个访客下载了一张图片,同样的图片会被缓存,而不会被同一台机下载,有效地节约了带宽成本。


<Drupal的调配>

  1. 数据处理:重写10,000+条很耗资源的URL

    Drupal AWS S3 模块的一般操作结果是,当你第一次上传一张图片,会生成一个image styling url,而当你第二次请求同一张图片时,会生成另一个URL。同样,当用户编辑页面时,就可能会把一个错误的图片URL当做静态参数插入到文章内容中。那时会发生什么?你的Drupal网站持续不断生成图片并上传到S3,网站分分钟挂掉。

  2. Drupal 7的缓存Header默认设定为Dries Buytaert(Drupal 作者)的生日,这样可以让Drupal网页不留缓存并持续刷新。正常说来,系统admin会把缓存header设在Nginx里重写behaviors,但是这个对Drupal不起作用。我们用一个Http 回应header模块,在每个Drupal页面里设置了缓存header。

  3. 时刻为不可预测的流量做准备,保持系统存储的独立性:Drupal的Cache_form一直是个很烦的事。cache_form非常大,特别是放在MemCache(内存缓存服务器)下,成本会相当高。为什么cache_form会这么大?当Drupal为每一个用户生成一个form时,就会写入cache_form。当客户网站同时在线到达2万用户时,他们的cache_form最高达到100GB。一些小伙伴可能会通过周期性地清理不用的cache_form作为缓兵之计。但是如果你的缓存/数据库大小是根据流量大小决定的,对于一些无法预测流量网站是绝对不能接受的!我们用New Relic观察发现,每个前端页面请求都会由cache_form输入,这个是不正常的。而且主题里的代码会生出一套form,却显示不出来。我们移除了代码,解决了50%的问题。如何做到即时测试和确定问题所在?因为我们有DevOps工具,我们可以部署、返回、再部署以确认代码是怎样影响数据库的大小的并部署最佳配置。至于剩下的50%,我们通过页面缓存Form来做,当他被请求时,也避免了每次生成这个form的情况。

  4. 分开定时任务(cron job)是相当相当的重要。每次执行cron job的时候,你永远都不知道多少资源会被消耗。默认Drupal的架构,访客点击你的url触发cron job,当cron job结束,响应才返回。这个过程间接让其他用户觉得drupal很慢。对于生产量级的Drupal网站,我们需要把cron job分到另一台服务器。我们可以用drush(drupal shell)触发cron job,命令行服务器指向同一个数据库。然后,我们可以通过drush cron触发cron job。关于一个成熟的Drupal's cron job可以做什么,请浏览这个网站:https://www.drupal.org/project/ultimate_cron


<Nginx调配>

  1. 云架构中Headers 和Security措施:在上述的Drupal 调配中提到,Nginx不能重写Drupal的Header,却可以控制一些静态内容,像js/css/images 等。Nginx会照顾这些静态文件headers,包括CORS(跨来源资源共享),这是一个浏览器的security措施,我们花了很长的时间把CORS运行在多个站点,做到均衡负载,支持动态CDN和AWS S3架构。

  2. 专为自动伸缩设计:在一个自动伸缩的环境下,运行静态服务器缓存,比如Varnish,是很难的,因为如果你用Varnish服务器,需要自动伸缩的是Varnish本身,而不是Nginx+PHP-FPM服务器。而且生产级自营的Varnish需要3台服务器,这样使架构变得复杂、昂贵。BootDev做的是,把页面缓存放到被称为微缓存(Micro-caching)的Nginx,我们把微缓存设到了内存里, 这样它就有了好似Varnish这样的功能。每5分钟我们会删掉页面缓存一次,代价就是5分钟后的第一个用户点击下去响应时间会有点慢。但是因为我们的响应时间只有300ms,这个基本就不是问题了。

  3. 适合于Drupal的配置文件 :有很多Drupal的模块需要Nginx的额外支持,而在Apache HTTP服务器里是不需要的。我们做了很多调试,比如,CDN模块,我们是如何用Nginx在CDN上释放缓存。那为什么不直接配置Apache HTTP?因为高流量的网站,Nginx是个非常基本的需求,比如淘宝就用Nginx。Apache HTTP 服务器基本上会让网站运行得更加容易,但是也会带来限制,比如内存负荷很高。

  4. 页面缓存:缓存置于内存,让页面变快,降低硬盘损耗!把硬盘放在云上,每次 IO(Input/Output)的成本都是非常高,这是大家的共识,AWS上只给了3 IO每秒每1GB,所以如果你的硬盘是8GB,你有24 IOPS。高读写的运行,我们需要把他放进内存,而不建议在高并发运行下使用硬盘。

  5. 对于Nginx的基本并发参数,我们会监控New Relic上的数据,提供Nginx并发需求最低的能承受范围内的预测,比如需要设立多少数量的服务器,多久需要砍掉一个进程等。所以调配(Tuning)有必要成为一个服务项,而不是一时间的解决对策,当然如果全都能自动化,是最好不过的了。


<PHP-FPM调配>

  1. 有一个有趣的问题是关于你如何调配出你的PHP_Limit和PHP-FPM值?如果你是个系统管理员,答案可能会“只要看不到PHP跳不出error就可以”。但是BootDev是按每种服务器类型(AWS EC2)调配出PHP参数,这个大致公式:(总内存➖1.5G Linux内核*85%以防性能损失)➗每分钟实际请求数量。这个算法很简单?一点都不。实际参数需要按照每个代码部署不断调配。你的源代码会影响内存的使用,也因此,BootDev计划以“调配即服务”(Tuning As a service)作为我们的下一步。

  2. 当然Opcache要配好

  3. 我们把网站从php5.3升级到了5.6(之后会是PHP 7?)响应时间从500ms加速到了300ms,现在New Relic显示的APM Apdex Score达到了0.97!(最好成绩是0.99)当然使用Php 5.6,Drupal的确会跳出一些提醒,不过似乎至今还没有什么差错。


<其他调配>

  1. Bitbucket上设置的Git支持对有限数量用户提供无限免费的私人托管

  2. 用git和DevOps工具(Chef)部署新的代码让我们可以在同时升级复数个网络服务器。这点在自动伸缩环境下非常重要,因为在自动伸缩群组,新服务器的IP地址是不确定的,你总是必须知道IP才能对服务器采取行动。Chef可以自动地做管理,我们可以在服务器端同步代码。

  3. Docker,我们用Docker加速置备自动伸缩的速度,一个EC2一个docker。

  4. SOLR搜索,但是在我们这个案例中,只做一个单台机,因为搜索要求不是很高。


结果:

我们在AWS的Dev+Staging+生产环境下,把AWS的费用从月8000 USD砍到了2500 USD。客户网站流量也从月150万PV到了如今的1460万PV!

  1. 流量在次年增长了10倍

  2. 子网站从5个增长到了10个

  3. AWS费用没有上升

  4. 在我们的支持下,2015年网站的SLA达到99.78!

  5. 在没使用动态CDN情况下,保证同时在线用户2万人,自动伸缩架构也保证了技术人员不用凌晨2点起床,不用手动为网站服务。

    使用了动态CDN?那网站真的快得要上天了!

6. 响应时间从800ms降到了300ms

有了如此经典的企业级Drupal+AWS的这个案例经验,我们也考虑下一步进军高流量的Wordpress!
如今的互联网事业,最重要的关键是高可用和正常运行,这个就像人的呼吸和心跳,必须永远放在首位。要知道如果你的客户没办法看到你的网站,再好的网站内容也变得毫无意义。接下来是速度,正如下图所示网页load时间和转换率的关系,能多快地把你想传递的内容给到你的客户,也同样决定了你以后的商业走向。
因此, 如何优化服务器性能 ,至关重要。

以上,就就是我企业级Drupal+AWS网站的案例分享,如果对你有所触动和启发,也算是我们的价值所在!


如果你对我们感兴趣,欢迎探讨,询问!联系方式:[email protected]





猜你喜欢

转载自blog.csdn.net/keithyau/article/details/51306725