🚴♀️ 小公司的技术架构演进
!本篇文章过于久远,其中观点和内容可能已经不准确,请见谅!~
小公司和大公司的产品目标一样的情况下,整体思路有很多差异,而每个公司不同阶段,项目需求迭代,用户量上升,都会涉及到架构的演进。而小公司一人多职位,需求变更频繁:没有专业甚至专职的产品经理把控需求,技术能力偏低:大量入门人员和实习生,起点较低:不需要那么复杂的技术发展路线。这样的环境差异,导致技术架构的演进几乎和大公司差异很大。今天来唠一唠小公司技术架构层面的演进,没有代表性,至少很多是我从手中堆起来的全部架构。
大公司技术支持比较完善,内部的开发平台、组件平台、构建平台都有现成的,有更标准化的开发规范、设计语言和内部沉淀等,Leader 一般也都是非常有经验的人。这些支持下的项目开发,技术架构都非常成熟。
小公司能选择的就比较少了,外部技术支持几乎没有,甚至云服务商的成套的解决方案(阿里云、腾讯云等Paas、Saas等服务)都没得选(成本或者保密),只能选择开源项目。另一方面人的能力确实有很大影响,没有薪资竞争力,有能力负责任靠谱的人很少,代码质量之类最基本的地方都非常不稳定,都是很现实的问题。
虽然小公司这么不堪,但是有效利用各种资源、踩一些坑之后,正常的业务搭建起来其实是没有问题的。我们小公司稳定开发人员十人左右,另外加上一些实习生边学边做提供一些支持,也确实搭建起来很大、很复杂的项目承接一些流量了。
我在其中是前端开发负责人,web 端整个大产品的全部架构选型和开发;刚开始也负责部分后台架构的设计、选型和搭建;中间负责过中间层的抽象和接口,后台完整管理系统的搭建;最后负责包括客户端在内的大前端的工作。
不仅仅是从零开始,还有一些展望因为精力问题没有实现,其中很多关键技术因为涉及业务保密没有写,跟很多人的技术选型肯定存在不同,还有很多因为场景、现实问题做的错误决策,仅仅是展示演进过程,不喜勿喷。
- 【前端】【后端】【数据库】
- 第一版主要进行最核心功能开发,搭建简单的业务交互能力。
- 有用户系统、内容系统等基本场景。
- 【前端】【中间件】【后端】【数据库】
- 业务类别增多,复杂度上升,中间层做有状态和数据聚合,后端做无状态的数据存取
- 解耦中后台,方便聚合数据,中台关心对象结构和接口封装,后台关心数据存储和性能
- 【前端】【中间件】【后端多服务】【数据库】
- 后端不仅仅需要数据的存取了,还有更多的服务需要管理
- 视频转码、文件管理、文件同步等
- 添加简单的服务状态监控
- 【前端】【中间件】【后端多服务】【多数据库】
- 无结构化数据需求,添加 mongdb 和 redis 保证性能和灵活性
- 【前端】【中间件】【后端多服务】【多数据库】【多机房】
- 基本业务搭建完毕,部署到 IDC
- 拆分内网服务和外网服务,内网作为测试环境和数据准备环境,外网正式部署和运营
- 文件和数据同步服务
- 【前端】【中间件】【后端多服务】【多数据库】【多机房】【微服务】
- 服务封装微服务,隔离业务,分布式服务,运维监控,自动化运维等
逐步根据需求添加服务,没有一上来就是分布式数据库,也不是一上来就是中间件、服务拆分、微服务,很多都是发现现有的架构有问题才去找方法解决的。其中中间件初期时我提出来的,运维监控和自动化部署第一版也是我实现的,微服务的尝试首先再前端应用部署上尝试的。
从一开始的 PC Web 端业务为主,到现在的客户端技术为主,中间经历了很多的方向变更,因为这几年的移动互联网发展趋势,以为顶多能占很大比例,但是现在手机端业务占据了几乎全部,这在几年前无法想象。
- web / android
- 都是既有的业务目标,先实现核心玩法
- web / ios / android
- 业务捋顺之后将 ios 补进来
- web / cms / ios / android
- cms 面向内部的后台管理系统搭建,技术相同,但也算一个不同的端
- ios / android / h5 / web / cms
- 移动为先,移动端能力优先考虑,考虑到快速迭代和线上更新,用 h5 Hybird 来快速实现轻量业务
- flutter / android / ios / h5 / cms
- 快速搭建性能优异的应用,flutter 作为重点技术加到大前端全家桶
其中经历了很多,尤其是 Android IOS 重复业务踩坑,所以后面跨平台的能力让 flutter 作为主要技术实现客户端能力。Web 端刚开始花了很多精力做了两版甚至,最后经过评估缩减了。上面列举的只是端和技术,具体没有说的业务也变更了很多放心就不说了,都是泪。现在大前端技术的发展日新月异,很多能力的使用在之前无法想象的技术栈,后来也稀疏平常,具体的端里面的技术下面再说。web / h5 / flutter 都是我负责的,其中协作和业务承接的转换还挺有意思。
- 史前阶段,文件夹
- 还没有协作的时候,需求只有每个人搭建自己负责的业务核心,持续很短,验证关键技术。
- gitlab
- 代码中心管理,需要一些协作和管理了,内网搭建起来一个代码仓库
- 一是避免代码丢失,二是按照版本记录每天的开发日报,三是涉及到多人协作了
- gitlab + gitflow
- 多人协作之后,大项目需要分支开发模式,引入 gitflow 的形式辅助开发
- 保证 master 分支可用,dev 分支可测,功能分支日常开发,但是并未引入代码评审
- gitlab + webhook 自动部署
- 功能需要及时测试,每个功能合并到分支上后,需要每次都拉取代码
- 于是我这边封装了一个小服务放到测试服务器,每次新功能合并,都自动部署到测试环境
- gitlab + merge request + review
- 人手多了之后代码质量没法保证,引入 MR 和 Code Review 机制
- 一方面明显不可靠的代码能当场检查,而且方便指导实习生
- gitlab + jenkins + git precommit + linter + issue 跟踪
- 代码临近部署上线,质量保证的需求下,添加持续集成功能,配合 docker 微服务
- 本地开发环境提交前运行 lint
- 服务端分支合并后自动运行一些核心的测试用例保证没有大问题
- 有测试人员专门测试并提交 issue
- gitlab + 制品库(正在建设)
- 每个服务和部署都封装成标准制品,对外提供统一的端口和依赖
目前内网的项目有几十个,大部分都有完整的文档支持,文档模板可以参考 📒 项目说明怎么写 - Readme 的自我修养,协作效率和代码质量都越来越高。
- fis + smarty + yii2
- 因为项目比较早期,Web 很重,做内容需要 SEO,不能都堆到客户端,服务端渲染页面的一个解决方案
- 支持模块化、组件化、资源压缩、部署等需求
- 前端也负责后台渲染层的实现
- fis 组件库,解决方案封装
- 业务深入之后,很多业务组件封装、拆分、抽象出来了组件库
- 包括联合后端的多语言支持、页面多端展示、大文件上传、富文本编辑器、p2p 、播放器等方案封装
- fis + vue
- 出现一些复杂业务,比如个人主页、IM 等需要复杂交互的界面
- 引入 vue 客户端框架,方便进行复杂的业务聚合
- vue 组件库 相关解决方案 组件库平台
- 这部分页面增多的时候,同样抽象出来了统一的组件库,搭建了能够在线预览和版本管理的组件库
- 前端工程化方案 zfes
- 根据实践需求,加上 vue 相关的解决方案,抽象出 zfes 的工程化方案
- 支持命令行工具、项目组织方法、多级版本化组件系统,预设 Mock 接口、I18N 多语言、AB 测试、多层兜底的数据请求层等工具
- react antd cms
- 在需要后台管理系统的阶段,引入 Antd 设计和 react 技术栈,搭建起来十多个子系统,近百页面的 cms 管理系统
- react spa typescript
- 需要一些复杂的单页应用,于是采用 react 技术栈实现复杂功能的单页
- 同时引入 typescript 技术栈提高协作效率和代码质量
- 组件库和全链路前端渐进式方案 kitu
- 自己平时的准备的实现中,抽象出一个全链路的渐进式工程方案
- 方案本身只提供插件,全部运行脚本跟随项目,不再黑盒包裹全部的逻辑,低侵入性和细粒度
- taro h5 小程序
- 对外提供很多的 h5 页面开始需要小程序版本,考虑到工作量引入 taro
- h5
- 朴素营销的 h5 一直没有断过,利用 jQuery 辅助实现一些简单的交互和业务
- flutter
- 新业务调研后,采用 flutter 作为多端开发的尝试,结果不错
- 除了涉及底层较多的部分,新业务大部分交互页面都是用 flutter 搭建
前端的技术栈受外界影响很大,因为我本人也是愿意尝试新的技术能力。一个新的技术生态活跃,生产环境有成熟产品,提升效率,没有理由不能引入进来,还能防止技术架构老旧的思维定式,探索业务的表现形式等。尤其是 flutter 还是在我力荐下尝试接入客户端产品,在主要工作界面上,工作效率和表现力上优于原生,引入后的迭代效率和组件开发上比之前提效很多。
大部分的技术工作都是在堆页面,所以除了组件抽离之外的业务并不是很复杂,一些大的解决方案上面说了,另外有一部分单独花了精力完成:
- 大文件、多文件上传
- 因为现有的上传服务和开源的不是很兼容,所以自行实现了一个分片上传的功能,可以断点上传、失败重试、并行上传、秒传、界面进度提示的上传组件
- 多语言
- 联合中间件,支持了多语言功能,同界面多语言支持,支持 po 文件
- 富文本编辑器相关
- 开发简单的内容发布器,简单的富文本编辑器
- 支持话题、表情和 @ 混排
- 播放器相关封装
- 支持播放 flv、HLS 内容的播放器,支持进度条预览、前置广告、清晰度切换、播放速度等
- 支持鉴权播放、多剧集连播、历史进度等功能
- 支持直播、弹幕、礼物、聊天室的能力
- Web IM
- 从底层封装完整功能的 IM 功能,好友管理、通知、消息管理、可扩展的消息类型等
- 支持语音、视频、图片、地理位置、音视频通话等功能
- 多页面复用单 ws 通道的能力
- 底层连接信令和上层不同聊天业务分离
- Hybird 和 h5 同构能力
- p2p
- 实现 P2P 通信,支持音视频通话、多人 P2P Mesh 和其他复杂功能的点对点业务
- 前端工程化方案 zfes
- 根据实践需求,加上 vue 相关的解决方案,抽象出 zfes 的工程化方案
- 支持命令行工具、项目组织方法、多级版本化组件系统,预设 Mock 接口、I18N 多语言、AB 测试、多层兜底的数据请求层等工具
- 组件库和全链路前端渐进式方案 kitu
- 自己平时的准备的实现中,抽象出一个全链路的渐进式工程方案
- 方案本身只提供插件,全部运行脚本跟随项目,不再黑盒包裹全部的逻辑侵入性强
很多技术没什么难点但是比较繁复或者业务差不多都没有细说,有很多抽象的工作并没有什么特别的也没说,而且很多都是做的时候踩坑不少,回想起来也就那样,所以值得记录的好像并不多。
flutter 相关文章写了几篇,可以在列表中查看 flutter。
- 兜底重试、原生替换、Mock、通用状态处理等功能的http库
- http 层面因为涉及到的 api 较多,而且需要重试和错误提示信息
- 于是单独封装了一个网络接口层,支持重试、兜底数据和通用错误处理
- 拓展了下拉刷新上拉加载的通用滚动组件
- 很多页面的内容都属于滚动列表组件
- 添加下拉刷新、上拉加载的逻辑
- 添加滚动组件的通用状态缓存,不必保留组件状态,提升内存表现
- 页面数据优先组件缓存机制
- 页面内存占用严重,于是不再保留页面和组件缓存,仅保留状态,每次快速重建
- 类抖音的滑动播放
- 支持上下滑动播放,比例适配,支持右滑进入新页面
- 多 tab 滚动嵌套、能够暂存状态的滚动组件
- 官方对多滚动嵌套滚动组件的支持比较差,这里结合业务封装了多个嵌套滚动的状态暂存恢复功能,满足分离滚动,还可以从状态重建
- 性能优化,稳定性优化
- 花了很大的精力优化性能和内存占用
flutter 是一个优秀的跨端开发技术栈,与前端的相关技术很不同,但是感觉很有前景。
后台管理系统每一个子系统都包含了很多的能力和页面,这里不再细说:
- 多角色和权限管理
- cms 数据查看,简单数据大屏
- 内容审核
- 热门内容推荐系统
- 自动鉴黄,敏感词系统
- 服务监控系统
- 交易异常管理系统
- 应用发布系统
- 全站投诉反馈处理系统
- 数据测试、发布、同步系统
- 一站式用户信息聚合系统
- 营销数据中心
业务上无论大小公司其实大部分都是完成核心功能,然后逐步迭代验证商业模式或者完成完整功能。
大公司从产品一开始就有有经验的产品经理梳理需求,对接领导、开发和设计,每个人任务和目标比较明确,排期和会议都是很顺利的事情。
小公司不太一样的是产品经理经验不足,甚至没有PM这个岗位。导致主程承担这个能力,但是以经验来看,从开发角度考虑需求和用户角度就会很不一样,导致经常性的开大会讨论一个细节问题。最后很有可能开发一群人决定的结果,领导或者用户没法接受,最后出现加开关、都做、先出 Demo 看看等结论,再次反复梳理。
产品实现过程中一定要有一个角色,能利落的跟领导核对需求和业务目标,落实排期和意见,不然混乱是肯定会出现的。另一方面,小公司的主程需要有能力承担起这个责任,能跟领导聊业务,能将理解出的结果落实到其他人员,提供问题和解决方案。
理解领导的需求,能够对未来一段时间的业务进行预判,选择合适的技术栈,按时、保证质量的完成需求,这是每一个人应该有的能力,在此基础上整个公司的业务和架构才会有进化。
感谢您的阅读,本文由 Ubug 版权所有。如若转载,请注明出处:Ubug(https://ubug.io/blog/technical-architecture-evolution-in-small-company)