wangpin34 / blog

个人博客, 博文写在 Issues 里

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

周记 2019/9/20: 前端铲屎官,微服务缓存初体验

wangpin34 opened this issue · comments

commented

来自前端小伙伴的「铲屎」经历

最近,有个前端小伙伴频繁的和我谈起自己所负责的项目中让人难以忍受的东西。我这里将去除了项目信息的部分内容分享给读者们,为了叙述方便,采用第一人称。如有雷同,纯属巧合。

为什么总是来找我?

我很不明白,产品经理明明知道新功能的设计稿还没有准备好,我也多次说明没有设计稿我没办法展开工作,可是,这个产品经理还是每天雷打不动催我一遍。你要说是因为设计师办公室比较远不方便沟通让我帮个忙也就罢了,可是设计师分明就坐在你旁边,你要是想知道最新情况,直接问设计师不是更好吗?

接口字段保持一致真那么难?

我就想知道后端发明这么多不同的数据结构干嘛?同意义字段在一个或多个接口的 request/response,名称不同,类型不同,前端要挨个的问清楚,然后组织 mapping table,转换数据。
例如,用户名,service A 中叫做 username,service B 中叫做 user_name。这是名称不同。
尺寸数据,service A 中是数字(浮点型),service B 中是字符串。

确诊了,你是铲屎官

听了这些,我很确定的一点是,在这个小伙伴所负责的项目中,前端所担任的角色是铲屎官:做最费力但最不讨好的工作。不是吗?好不容易催来了设计稿,赶在 dead line 之前完成了项目,但功劳大半还是产品经理的,而你不仅被人无视,如果不注意催稿的方式方法还有可能得罪设计师们。殚精竭虑修修补补完成 mapping table,数据总算可以正常流转,可是你没法夸耀自己,老板不会理解你的辛苦,后端也不会认可你的工作。惨不惨?

很多不专业的公司和团队是这样使用前端工程师(傅)的,他们是各个角色的粘合剂,是产品经理,设计师,后端工程师,之间的沟通桥梁。虽然不是项目经理,但总要扮演项目经理的角色,在其他成员之间穿插游走,跟产品经理沟通需求,跟设计师祈求稿子,向后端跪着请求不要随便改字段。往往等到一切信息就绪,留给自己做开发的时间也很少了,于是只能加班加点赶工期。

功能上线之后呢?甭管什么问题,首先肯定是前端出错了,于是第一个被从被窝里面 call 醒的人总是前端工程师,谁让你「啥都懂」呢?前端工程师熟练的打开 develop tools,看到 console 里醒目的 service error,自信的说,“是后端服务出错了。” 然后旁边的运维一脸坚毅,“麻烦看一下是哪个后端服务出的错。” 所以很多前端工程师在项目呆久了,不管有没有兴趣,在这样的磨练中,后端的来龙去脉也大概摸清了,变成了最懂系统架构的人。也算是不幸中的万幸吧。

你是这样的铲屎官吗?如果是,你有想过怎么改变这种尴尬的现状吗?

微服务缓存初体验

前端并非不懂缓存,事实上,如果你想,浏览器的缓存可以玩出花:

  1. 静态资源如 js,css,image,等等,设置合理的 cache-control 以利用浏览器缓存。
  2. 动态资源如 api call,设置合理的节流/防抖,减少 api 调用次数
  3. 利用 localstorage 存储少量用户数据
  4. 利用 cache api 存储大量用户/非用户数据,如 pwa 中的应用

以上基本是关于缓存前端可以做到的所有事情了(欢迎打脸)。但对于一个追求卓越的工程师来说,凡是可以用缓存来加速的,那就有必要尝试以下。比如我司的业务场景:

前端服务拼接若干个后端服务提供的数据,返回给客户端。这些数据都是一次生成不再更改的,所以,如果将数据缓存在后端,就可以节省下反复请求其他后端服务的开销。

技术选型:Mongo vs Redis。我的理解是缓存数据不必考虑 schema,只需要做 key-value 存储,所以 选择 Redis。我在微服务的 Dockerfile 里面安装 Redis 并启动,使用这个 Redis 作为缓存数据库。

RUN wget -O redis-5.0.5.tar.gz http://download.redis.io/releases/redis-5.0.5.tar.gz
RUN mkdir /usr/local/redis
RUN tar -xzf redis-5.0.5.tar.gz
RUN cp -R redis-5.0.5/** /usr/local/redis
RUN rm -rf redis-5.0.5.tar.gz
RUN rm -rf redis-5.0.5
WORKDIR /usr/local/redis
RUN make

CMD /usr/local/redis/src/redis-server

解释一下前面提到的 key-value 存储的具体做法:我将资源 -> key 的算法封装为函数,比如,对于 order 和 session 两种资源,生成的 key 如下:
order 123 -> /orders/123
sessions 456 -> sessions/456
然后将 order 和 session 的数据序列化,作为 value 存储起来。

试用结果:原本需要 700 ms 左右响应的 API 优化到 100 ~ 200 ms。

总结一下
添加缓存支持的第一步很简单,尤其是熟悉并使用 docker 的情况下。但缺点还是很明显的,因为 Redis 和微服务本身在一个 Docker Image 中,所以重新启动/部署微服务,就会导致缓存数据失效。改进的办法是使用独立的 Redis 实例作为缓存服务。