微信号:yogoup

介绍:网站性能提升与架构设计

Hotjar在架构演进中总结的8条经验

2016-06-14 17:53 杜亦舒

Hotjar 提供了帮网站主了解用户行为的服务,网站接上此服务后,可以生成用户的点击热区,录制用户的行为,查看各个页面的跳出路径以及停留时间等,根据这些统计数据,网站主可以发现问题,有针对性的地完善产品


现在为 15万以上 的网站提供服务,脚本每天被请求 5亿次以上,数据库中的数据量达到 37.25TB,每天 5GB 左右的增长,每秒有 1500次 左右的写请求


从起步,到这个成绩,Hotjar只发展了两年,短时间内的快速发展,对 Hotjar的架构提出了挑战,通过不断的研究调整,顺利支撑住了网站的成长,并总结分享了几条经验


架构的演进过程


V1




初期架构非常简单,后台 Python,前台 AngularJS,数据库 PostgreSQL,使用 Amazon 的负载均衡服务 ELB 把请求分发给两台应用服务器,NewRelic 负责性能管理和监控


特点是简单,适合起步,并且具有很好的水平扩展能力


现在的架构


随着网站规模的增加,虽然V1架构经过扩充还是可以不错的提供服务,但技术栈过于单薄,需求场景增多,需要更多适合的技术来处理,到现在,技术栈已经相当丰富




负载均衡后面有8个应用服务器


性能监控还是使用 NewRelic


通过 Librato 监控实时操作和获取性能分析


StatusCake 和 VictorOps 在出现错误时发送通知


Intercom 和 Mixpanel 用来辅助市场团队


使用 Graylog 记录 JS和 Python的错误日志


数据存储使用 PostgreSQL,S3,Elasticsearch


Amazon 的 SES 服务给用户发送Email


Redis 和 Memcached 做为内存缓存 


经验



(1)不要低估网站的成长速度,基础架构要能支持快速扩展


hotjar 刚开始只有2台应用服务器,共2个CPU和3.4G内存,现在有8台,64个CPU和120G内存


能够轻松和高效的进行扩展,是因为在初期架构设计中就非常重视水平扩展能力,这是非常重要的,一定要尽早考虑


(2)频繁访问的静态内容尽量使用 CDN


开始时,用户直接从 hotjar的服务器上加载统计脚本,加载量大后,性能变差,hotjar把脚本转到了CDN,加载速度和稳定性都大幅提升


(3)在重要的性能点上,不要局限在你的开发语言上,可以考虑使用更适合的语言


越多的用户使用 hotjar,就有越多的统计数据发送到服务器,数据处理的性能成为关键


hotjar的后台服务使用 python 开发,经过一系列的代码优化和性能测试,最后决定在这个功能点上不再使用 python,改用 Lua 开发


Lua 是一个强大的轻量级嵌入式脚本语言,非常快,自从使用 nginx+lua 后,性能立即大幅提升,错误率降低,可以处理更多的请求


(4)如果某些数据对延时要求不高,并且获取简单,例如通过主键就可以查询到,这时可以考虑使用云存储,不必非要放在自己的数据库中


初期,hotjar把所有数据都存储在自己的关系数据库中,经过高速增长之后,发现数据库中有大量数据是很少访问的,便把此类数据迁移到云存储,并修改了相应代码


这样可以节省数据库空间,提升数据库查询性能


(5)你的核心数据库不一定适合所有场景,可以考虑使用更多的数据库来适应不同的需求


hotjar 发展了6个月后,每天需要处理 15万条记录,这时开始有用户反馈,浏览记录列表时非常慢,技术团队开始优化他们的数据库PostgreSQL


但结果并不理想,团队便寻找更加合适的技术,Elasticsearch 很快成为首选,


转换过程并不容易,先修改代码,把新记录同时写入 PostgreSQL 和 Elasticsearch,同时,后台进行历史记录拷贝,当数据迁移完成后,马上把查询切换到 ES


之后,用户立即就感受到了这个巨大的性能变化,效果很好


(6)有时,即使是一个小小的结构性变化,就可以在成本和性能上产生大的收益


尽管脚本放到了CDN上,但在优化脚本加载这个事儿上还可以做更多


每个用户都有一个唯一的脚本,如果用户修改了他的后台配置,这个脚本需要重新生成,导致脚本缓存失效,需要从新加载,大概40K左右,看似不大,但请求多了也受不了,CDN成本上去了


为此,决定把脚本分为两个,一个是 hotjar的业务代码,改动频率低,一个是用户的配置信息,体积很小,每次用户改动后,只影响这个小脚本


这个改动虽然简单,但是节省了很多成本,并且加载更快了


(7)尽管你无法在早期仔细考虑数据库的schema,但要确保有适当的监控,并思考如何在修改schema时减少对数据库的影响


hotjar 在数据库设计上吃过亏,开始时,所有表的ID字段类型设为了int4类型,这在 postgres 中是非常标准的选择,但后来问题来了


几个月之后,对所有用户网站的数据收集工作停止了,因为ID字段的值达到了上限,int4 能存储的最大数是 2,147,483,647


必然要修改数据类型,但数据库中已经有数十亿的记录,这个简单的更新操作将需要运行数天


为尽量降低停机时间,只能新建库,使用新的数据类型,然后进行数据迁移,修复这个错误最后花费了数周的工作


没有一个适合的监控,没能尽早发现问题,是一个重要教训


(8)监控是非常重要的,有越多的监控,就可以越快的识别问题


初期,处理用户的问题反馈时非常迷茫,常常无法复现问题,不知道这个问题是个例,还是影响了很多用户


后来加了一套监控,找问题方便多了,可以快速定位,也可以知道发生频率,大量减少了花在调查上的时间




点击下方“阅读原文”查看 文章列表
 
 
性能与架构 更多文章 前端工程 - 静态资源的更新 linux 实时监控进程状态 - pidstat 技术人员的困境 JS的 HTTP 库 Axios 手机浏览器中的 DevTools
猜您喜欢 为设计师准备的 10 个最棒的 Chrome 扩展插件 2016互联网行业薪酬数据:哪个职位最赚钱? 关于Java启动性能的一个解决方法 Android 开发中实用工具 python 中文乱码 问题深入分析