首页 > 编程知识 正文

实战大练兵总结,设计师实战总结

时间:2023-05-04 19:31:37 阅读:167763 作者:272

编者推荐语:

本文中的晾衣架相当多,用node写BFF和后端的伙伴可以对比一下自己的项目来学习。

以下文章来源于比较真实的前端,作者英俊你冲哥

较真的前端

前端开发者的沟通与关怀平台

因为我第一次知道这篇文章,所以大家可以阅读文章底部的原文并访问原文的地址。 文末有视频。

项目背景小编我在国内某知名互联网(非一线)做前端开发。 因为平时经常做NodeJS,所以也很少负责BFF和服务端。

前几天,我所在的团队接到了为我们公司某项服务提供数据可视化和数据分析平台的“大工作”。

在与数据生产方(服务器维护方)进行了几次联系后,我了解到这次的后端服务器有几大挑战:

全栈开发:本项目在数据生产完成后,前端页面、后端服务、数据加工等所有工作由前端集团独立完成

数据量庞大

实时展示:我们希望为用户提供实时数据展示。 要实时处理这么大量的数据并不容易

权限认证

项目为我们对接的服务做好了维护准备,我们提供的是将所有实时数据丢入clickhouse (适合大数据存储分析的数据库),除了实时数据外,还进行时间级聚合

也就是说,每个业务线在其服务上生成的数据每小时都会被聚合,并落在另一个表中。 其中包括时间内的合计、平均值、uv平均值、pv合计值等。

剩下的事情要靠我们几个前端同学来解决。

技术选型后端当然是用NodeJS写的,但毕竟我们是前端开发,所以选择NodeJS是理所当然的。

但是,基于NodeJS的http服务器框架应该选择什么? 现在市场上熟知的有三个。

Express和Koa、EggJS

Express本人使用多年,做过两个运行多年的大型项目,但实际使用起来很辛苦。 的请求实例每次都通过参数分层传递,所有错误也分层传递。 使用不愉快,需要尽快寻找变化。

Koa是由Express员工创建的,从根本上解决了Express的许多缺点,但需要更适合企业APP应用的框架

EggJS——最终选择EggJS成为了最终的选择,但我认为Egg有以下优点。

多环境配置作为企业APP应用,有多个环境——测试环境、stage环境、生产环境,每个环境的APP应用所连接的基础服务的参数、结构信息都不同。 EggJS在启动时通过注入环境变量可以加载不同的配置文件并挂在context上,APP码无需在意环境的差异,可以轻松解决多环境问题。

系统稳定性,Express和Koa增加了运输和部署的复杂性,但为了系统的稳定性,需要在PM2中进行流程管理和监控,而EggJS具有流程管理和监控功能

定时任务,如果Egg本身有schedule模块,则不需要引入第三方插件。

丰富的生态在这次的项目中在后端很常见,但是在前端使用了很多前所未有的技术,如状态监视Prometheus、消息队列Kafka等,所以它们已经

插件开发简单,如果生态还没有你想要的Egg插件,自己开发一个就不难了。 我自己在这个项目的开发中做了四个插件。 另一个已经是开源的——egg-etcd。

系统设计这次开发的系统结构图大致如下。

系统的要点:

通过中间件解决对每个请求的登录权限的检查

利用Etcd实现配置信息的实时同步

“热数据”缓存在Redis中,其他数据实时检索到Clickhouse和后端接口

使用中间件是非常合适的,因为中间件通过数据安全性对每个请求都要检查登录状态(sso)资源权限

由于Egg中间件的结构遵循洋葱圈,因此每个请求都是通过每个中间件的层次来处理的。

在我们的基础设施中,http API具有登录校验和资源的权限检查,但在开始开发该项目的时候,没有针对NodeJS的sdk包,所以将这两个检查过程打包到两个插件中

有了这两个Plugin,以后只需在不同环境的config文件中放置appKey、appSecret和其他相关信息即可。 (这些是我们对http API请求的安全检查机制,类似于微信公众平台。)

事实证明,有了这两个Plugin后,今后Egg项目的开发效率得到了大幅度地提升。

使用Etcd做配置管理

项目中的所有配置都写在了配置中心(本次项目选择用etcd),这样做有几个好处:

安全性:把所有机密信息(如数据连接用户名和密码等)通过环境变量来注入到镜像中,而环境变量值写在etcd中,这样这些信息都不会明文暴露在代码中。并且etcd自带权限管理,所以只有当前项目权限的开发者才会看到关键信息

实时性:部分配置信息是可能随时发生变化的,项目需要与最新的配置保持同步,etcd提供事件监听,可以做到配置的“响应式”

共享配置:部分配置是多个应用共享的,通过引入etcd上相同的path来省去了维护多份数据的成本

介于Egg生态中并没有Etcd的插件,我自行开发了一个并且开源Egg-Etcd

数据缓存

每次接口请求的数据都会缓存到Redis中,下次请求如果发现Redis中已经存在,则从Redis中取。

为了保证数据的实时性,Redis缓存时间可以设置的短一些

系统稳定性

上图和我监控架构很相似,不过有一些不同点:

我们的AlertManager通知的手段会更多。

多了异常监控sentry

系统稳定性需要关注的几点:

多实例+多进程:一个进程”倒下”了,立即拉起一个新的进程并关闭异常进程,保证一直有健康正常的进程来响应前端请求。

本次项目是2个实例,每个实例16个进程。

平滑重启+自动扩容:应用部署新版本时不应该是让服务变得不可用,哪怕是一秒钟,所以需要通过多实例交替重启来实现”平滑重启”

我们公司云平台的做法是 :先删除一个实例pod,再拉起一个新的pod,等新pod的存活检查和就绪检查都通过后,再删除一个……这样循环,从而实现平滑重启

自动扩容是调皮的服饰的应用突然迎来一波流量典雅的棉花糖,云平台可以自动为你复制出多个pod,你只需要设置满足扩容的条件即可(如CPU使用率超过85%并持续1分钟)

异常监控:代码如果出现抛出异常,应该第一时间得知,化被动为主动。(代码抛异常,有时并不会让系统崩溃,所以很容易被人忽视)。

本次项目使用了Sentry,如果发生错误,开发者会第一时间收到邮件通知,并且可以在平台中看到各个异常相关的数据和统计。

指标监控:对于应用运行状态和指标的监控也是十分重要,如CPU使用率、内存使用率、流量等等,可以自定义指标,如QPS、错误累计数、文件句柄数等等。

本次项目使用了Prometheus来监控。

在Prometheus的下游,我们公司还提供了Grafana——进行指标可视化,和报警平台——通过PromQL来对关注指标进行报警,报警方式还很多,包括:邮件 => 社交软件 => 发送短信 => 拨打电话(一旦出了异常,报警是躲不掉的)

日志收集:一旦出了错误,就需要分析日志,我们公司提供了云端日志收集,所以不管你有多少个实例,你的实例是否已经被销毁了,日志文件都是可以保留且可合并分析。

公司云平台为我们提供了Kibana,通过ES语法来检索日志、输出报表、图形化分析,只要确保日志格式是符合规范的,无论你使用哪种语言创建日志,都是可以以相同的方式进行检索查询及分析。

小结

通过上面的总结,我们的系统已经可以稳定运行了,并且形成了像下面一样的完整闭环。下一节的”性能优化”就是基于这个闭环来进行优化的。

性能优化

在上面的指标监控的加持下,在运行了一段时间后,通过Grafana的指标监控显示,发现了我们的数据可视化系统中,某个业务线的接口返回时间很长,大约要22s以上,这个时长是无法容忍的。

根据日志排查发现,原因是某个业务线的数据量很大,针对于该业务线的所有数据都很慢。

22s到0.1s的优化

通过日志排查,日常消耗在egg-sequelize进行数据查询上,通过其他SQL平台进行查询依然很慢,说明这个查询本身就是慢查询。

如果是MySQL的话,如果出现慢查询,我这里会收到报警,但是clickhouse目前没有这种处理。

首页 - 实时数据优化

首页展示内容是当前业务线的实时内容,包括:

各指标今日到当前的实时趋势(粒度:小时)

今日关键信息排行榜

今日各步骤的转换率

上面三个接口返回时长都在22s以上。

数据均已做过处理

解决方案:

介于用户对于这些数据的实时性要求不是那么那么高,偏差几分钟是在接受范围内的,所以我利用定时任务每5分钟计算一次首页数据,并将这些计算结果缓存到redis中,所以这些接口实际是从Redis读数据,速度大幅提升,最多5分钟的延迟也是用户可以接受的。

接口返回时长均在100ms之下

用户行为分析页 - 时间范围内聚合

数据均已做处理

用户行为分析页面的特点是用户可能会对长时间范围内的数据进行聚合和分析,所以用户选择的时间跨度越大返回时长越长,clickhouse的查询就越慢(单个业务线的每日数据量在千万以上)。

这个页面查询数据的特点:

聚合是按照时间维度(小时、天)

查询有多个指标

所以最后的解决方案是,对各个业务线在小时和天两个级别将上面的所有指标数据提前计算出来,并落到clickhouse上,所以此页面的计算会是在中间表上进行查询,效率非常高。定时任务中没有计算到的时间点(如当前小时和上个小时还没有计算和落库),可以再单独去clickhouse中查询,最终将两份数据合并。

接口返回时长也在100ms左右

还能做些什么 What’s the Next?

该项目已经在线上正常运转3个月以上了,在性能上还没有收到用户的负面反馈,总体来说还是符合预期的。

但是我系统中还很多不完美的地方:

虽然通过追加中间表来提高了查询速度,但是精细筛选条件下的数据查询依然很慢,原因是中间表是在没有筛选条件下进行聚合在落库的。

较大的时间跨度范围内的UV查询依然很慢,原因是在大量数据内做distinct处理是十分耗时的。

接下来要做的努力:

增加埋点收集,分析我们平台的用户行为,发现用户常用的搜索条件是什么,然后提前进行数据切片并落库。

实时性要求变高后,需要引入Flink + Kafka,进行实时运算再塞到消息队列Kafka中,最后再数据落地,这样数据量会减少很多。

总结

经过这次项目过后,我们在Node应用开发上积累了很多经验,并且沉淀出了多个egg插件,为今后的开发打下了良好基础、效率大大的提升。事实上,在此之后的多个Node项目的开发周期可以控制在一周内,开发人员可以将精力集中在业务逻辑上。

转自https://mp.weixin.qq.com/s/KEwCmlqFzT0XKOUw-ZUT0w

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。