小公司后端架构、代码、流程吐槽
自从入职以来越来越难顶小公司的后端架构、代码结构
前提
任何的架构、代码,都离不开业务,用户量,所以需要提前说明一下
- 就我一个后端开发,需要负责日常开发、运维、架构方案设计
- 两年多经验,可能一些东西考虑的不是很周全,只根据当下的认知吐槽,可能下个月觉得现在幼稚
- 后台用户量不过万,物联网行业
- 简单吐槽一下
架构层面
项目1
这个项目主要的功能是为客户提供资源文件,包括运动资源、地图资源等,每个资源都有迭代版本,客户需要从我们这边下载。每次有资源更新时,表中的 version + 1
整体架构如图所示
- MyServer 是我们的服务器,Client_1 ~ Client_3 是 N 个客户服务器,每个服务器都有自己的 db
- 资源文件存储在腾讯云的 cos 中,总大小 25G,更新的频率很低
- 前端负责显示一些版本信息等
业务逻辑是,当有资源更新是,开发手动上传资源到 cos,手动执行sql把 version++,client大概每周从我们这边拉取 version 进行比对,如果不一样,向我们要 cos 的临时签名,client 拿着临时签名去 cos 下载资源,最后把下载好的资源存储到他们自己的服务器
问题点1
整体流程,还行吧,但是资源总量才 25G,直接放服务器上不好吗?回复的理由是,由于是轻量级服务器,占带宽,费流量,感觉有点道理?看了服务器监控发现。。。流量包每月4000G,用了三分之一不到,7日平均出带宽 1.8Mbps,没什么压力吧。。。加入 COS 就是为了把流量转嫁到 COS 和 client 端,不仅增加了复杂度,COS 的流量还有被盗刷的风险,并且因为临时签名不支持断点续传,还得把资源转移到服务器,不如直接向客户涨价,把流量费用包含在里面。。
问题点2
客户的服务器实现是各自找外包依靠我们的接口标准、部署标准做的,而由我们前端同时各个接入,???,不是,绕了一大圈做了个什么东西出来,我实在难理解,假如系统做新的变动时,需要考虑各个下游系统会不会被影响,甚至要挨个问,更新后我还得挨个客户群里一条条发,前端要一个一个接,沟通成本巨大,想想都痛苦
项目2
简单介绍一下:主要是对手表端采集的数据进行分析,展示各个指标,有一些边缘业务,如积分、社区、表盘资源等等
代码拉下来,好起来了,起手一个微服务,根据前提,有必要分出来这么多吗,就一个人维护,各个模块通信麻烦,面向简历编程吧,分析一下各层功能
api、common、这里公共的抽取出来我能理解,但是 Controller、Server、Order、Sys、active 等等根据什么进行剥离呢,业务?入口?不知道的还以为超大公司项目,超多人一起维护的哟
各个模块独自维护了独自的库,使用 zk 作为注册中心,模块之间使用 dubbo 通信,所以剥离了 api 模块,暴露出去的模块还没有使用分布式事务,只需要拼命上组件,不需要考虑配套的服务呗
问了一下前端知不知道什么原因,说是怕订单、社交等模块同时崩掉,互相影响,????,保证可用性也得多台机器啊,全部就一台,还不是一样挂,直接采用单体,这么小的项目启动也就不到一分钟吧,就算拆分也没必要拆这么多把
既然项目结构都两眼一黑了,服务器大概率也跑不了,软件上有 Nginx、Redis、MySQL,架构图如下
有三台服务器,一开始我还以为是集群,了解之后眼睛都快瞎了。
- Service1 负责 A 的国内项目,记为 A1;还跑了 B 项目的测试
- Service2 负责 A 的供应商特供项目,记为 A2;跑了 B 项目生产;以及其他项目的生产
- Service3 负责 A 的海外项目,记为 A3,硅谷服务器
- 数据库只有一个,在 Service2 中,三个服都是各自的库,都在一个 MySQL 中。由于前面提到,一个项目就是十几个模块,每个模块都有自己的库,所以三个项目加起来大概将近三十个库;不考虑硅谷的服务连国内的数据库卡顿的因素?
- Redis 都连接 Service2 的,没有设置淘汰策略,很多占用大的 key 也没有设置过期时间
- A1,A2,A3 是几乎完全一样的三份代码,也就是说,我需要维护三份一模一样的项目,如果要加一个新功能,还得复制过来,并且公共模块也是直接复制过来的,公共部分会有业务耦合,没有搭建 私有仓库
整个给我的感觉就是混乱。。。果然。。。技术垃圾并不影响公司营业
代码层面
-
日志上,控制台和 log 混打,日志不做滚动,定期删除,导致磁盘空间大量被占用
-
程序中出现大量的魔法值,能写死的全都写死,写死在 xml、写死在代码、写死在任何不报错的地方;配置信息不在外部配置文件或者表中处理,大量的字符串导致 JVM 内存被大量占用
-
没有统一的异常返回,描述枚举,全都是魔法值,业务异常统一的错误码,极度影响海外业务的多语言处理
-
入参使用字符串接收,自己再转成 Map ,里面有哪些字段只有天知道,出参一样道理
-
token 每个接口自己获取校验,自行报错,绝对不用拦截器处理
-
异常在 Controller 统一处理,绝对不用全局异常,同样的日志混合打印,越冗余,代码越长,业绩越好
-
存储过程、触发器、视图、事件,写上了就能保证绝对的数据安全,也不用写代码,立马更新(超级点赞噢👍,md,还没用过,当时找代码死活找不到对应的表和初始化逻辑,原来这畜生写在了触发器里,要不是突发奇想真的找不到
(这张图估计也不用打码了)
-
多用循环引用,能不能看懂我不管;两个 mqtt 通信组件之间,循环注入,内部循环调用,没个十多年的功底真的写不出来,下图只是一个例子
-
绝对不写注释,并且使用位运算,变量全部都用拼音,即使用英语的,两个类名也要差不多一样,让你稍微看岔就不明白什么意思,一周过后,谁都看不懂;真的是畜生
-
使用 Mybatis-plus 后,遍地的魔法值,不收敛到一处,让后人少改一处直接爆炸,还能导致大量的冗余代码,刷业绩
-
所有业务逻辑编写到 Controller 中,Service 只调用 DAO 查询,让 Service 形同虚设,并且 DAO 使用连表,甚至连库的查询,让你没办法迁移,服务分布式,但是数据库以后都别想分布式(后面公司发展海外业务,想要在原来的基础上改动,后面经过讨论直接重新写)
# 伪代码
select * from a left join B.b on a.id = B.b.id ....
- Redis 存储永久数据,并且不设置定期清除,让你某一天内存满了,发现了这个问题,设置淘汰策略,稍不留神,永久数据将会灰飞烟灭(CNM 差一点)
流程上
- 没有测试!!没有测试!!没有测试!!没有测试!!全靠大家点点点和 开发的功力
- 有企业微信死活不用,就用个人微信,问了还被反问为什么要用,文件传输、引用、图片+文字、组群、非常的麻烦好吗
- 一个接入方一个群,才几个月一堆群了已经
- 所有文档都是私下传,互相传、不同步上云,大家看到的版本都不一样
- 没有测试服,要自己搭建,并且操作系统还是 Deepin,全靠开发不偷懒,不然直接往线上更新
- 可以直接连生产环境,代码,sql 都是自己保证质量,所以。。。每次更新之前都镜像一份服务器数据
- 没有任何交接文档,全靠自己摸索
- 算法文档中,语义描述不清,全靠文字,前后词语对不上
- 所有代码不是统一到 svn,一部分找外包做,压缩包私发
最后
这些的这些构成了一坨屎山,每个文件都充满了屎,以前我想着,重构还好呀,但是现在发现,各处耦合,各处分散,一个人做这些真的不够用,在见过真正的屎山之后,才知道什么叫无能为力,只能在上面打补丁,拉新的屎,剩下的,要么跑路,要么重构,这种级别的项目,重写反而风险更小。。。
但是领导没有预留时间,后续也不太可能会有,并且公司中心并不在后台上,发展挺受限的,所以我觉得跑路是最好的选择
至于为什么还没跑路。。。是因为刚开始进去的时候,感觉还能接得住,另外开发 + 运维,感觉挺有挑战的,物联网行业也还行?再到后面一点,开了新业务,也很少维护老代码了,全部都是自己新写,从 0-1 开始,觉得还是可以接收,但是不管怎么说,业务性和成长性都太局限了。。。
虽然但是,还是假设可以重构,如果去做,我会怎么做(最近没空了就是。。一堆新需求😫
// TODO
这是一段防爬代码块,我不介意文章被爬取,但请注明出处
console.log("作者主页:https://www.cnblogs.com/Go-Solo");
console.log("原文地址:https://www.cnblogs.com/Go-Solo/p/18334477");