从系统整体观思考系统构建
技艺精进之路,永无止境。
引子
很多时候,程序员做的都是代码堆砌的事情。就是一点一点垒代码堆功能,缺乏一种清晰的系统整体观和设计观。
如何建立系统整体观呢?
-
建立系统的架构主页,包括系统的背景、产品和研发目标、系统全景图(技术设施、业务底座、核心业务能力、系统模块及交互、产品上层)、核心主体流程、重要设计决策集、技术栈及技术选型、系统部署图;
-
建立系统词汇表;
-
建立系统的领域模型;
-
建立并加固系统的存储设计;
-
从模块级别思考系统,思考构成系统的模块、关联关系及交互;
-
思考模块与系统的技术重难点(复杂或易错的业务逻辑、海量数据处理、性能、稳定性、可扩展性、可伸缩、可用性);
-
清晰表达系统重要模块与功能的设计实现方案;
-
梳理系统构建的开发套路和构建方式。
系统领域模型
系统词汇表
构建系统的词汇表和名词解释,在开发、产品、测试、业务人员、客户之间进行顺畅的交流。
词汇表和名词解释要求:
- 用语严谨贴切;
- 解释通俗易懂,有好的示例辅助理解。
整理系统词汇表有两个好处:
- 学习和整理业务知识,加深对业务的理解;
- 作为各种业务与技术文档的链接入口。
例如:入侵检测词汇表(节选)
词汇 | 字段名 | 语义 | 链接 |
---|---|---|---|
入侵检测 | IDS-名词解释 | ||
告警 | Detection | 一个通过规则判定为入侵的可疑或恶意行为。这个告警可以被手动或自动处置与响应。每个detection 都有 score,来表达告警的危险程度。每个 detection 都与一个或多个元素关联。 | |
元素 | Element | 1. 产生恶意行为的可疑或恶意对象,包括进程、文件(脚本、webfile、配置文件、可执行二进制文件、模块、动态库等)、进程树、IP、域名、socket、账户、内存类、进程段、动态加载模块等。 2. 被施加恶意行为的载体对象,包括主机、容器、集群。 |
Agent 虚表定义 |
规则 | Rule | 算法、正则、序列等广义的入侵行为检测方式。 | |
规则库 | Rule Repository | 以一定分类方式规定和组织起来的规则集合。 | IDS-检测方式与检测规则库对应关系 |
评分 | Score | 告警的危险程度的量化。告警的 score 主要由规则决定。同时也受多种因素影响,比如攻击特征(有强有弱),该行为的异常情况(和上下文及统计与算法模型相关),影响结果(大量网络传输,文件被破坏,策略/文件被修改,账号新增,异常登陆等等),告警特异性(独特的还是大量雷同的)等。 | 告警置信度自动化评估 |
检测引擎 | DetectEngine | 检测入侵行为的技术手段和工具。检测引擎通常会引用规则。 主要区分区分行为引擎和特征引擎。涉及码和规则的往往是特征引擎。 |
关于告警详情中检测方式的文案【持续增加】 |
领域模型
软件系统如何与业务对接呢?领域模型作为桥梁。初步阅读《领域驱动设计》,有一个感触是:在设计软件时,在技术手段之上要有一个不断演进的领域模型用于高层设计引导,才能使软件能持久贴切地反映领域需求实现。不是所有系统都适合领域驱动设计,但是运用领域驱动思想去思考业务,总是有益的。
绘制系统的领域模型,凸显系统中各种基本实体及关联关系。
画图,画图,画图!一图胜千言,画图见真功夫。
数据交换格式
制定通用的数据交换格式,使得数据可以在系统之间流畅地流动。
从模块级别思考系统
模块若干问
-
这个模块有哪些基本术语和名词解释?内涵和外延,概念之间的关联关系,能不能给自己(和别人)解释清楚?
-
这个模块的设计和实现有哪些技术难点?解决方案是什么?
-
这个模块有木有通用机制?能不能提炼出来,做成可复用可扩展的?
-
有没有清晰的文档,能够阐明这个模块的设计思想?能不能让别人容易地理解?
-
能不能让别人相对容易地在这个基础上添加新功能?如何添加新功能?
-
各个模块之间的关联和交互?对于所构建的模块和系统是否有一个比较清晰的整体图景?能不能画出来?
-
各个模块的代码是否良好地组织,并放置在合适的包下?
-
做出技术决策的原则、准则和依据是什么?是怎么思考这个问题的?
入侵系统服务端模块
检测配置模块
提供用户自定义的检测、阻断行为定制和自定义检测、阻断、响应规则。
技术重难点:多个自定义配置的叠加覆盖逻辑;检测配置的变更下发。
规则管理模块
提供规则的新建、导入、下发能力。
技术重难点: 规则的分类、组织和管理;全量规则与增量规则下发;短时间大量 agent 获取全量规则的性能和稳定性问题。
检测模块
构建具体的安全事件的检测流程、生成检测结果和告警。
技术重难点: 通用、可扩展的检测流程;复杂的检测流程构建;检测流程的性能与稳定性。
告警列表详情模块
展示生成的告警及详情,供客户及时处理告警。
技术重难点:告警存储设计;告警列表、聚合与统计;接口性能问题。
告警降噪模块
对告警进行降噪、评分。
技术重难点:降噪、评分算法。
威胁情报模块
对上报的海量新事件及各种来源的安全事件进行威胁情报检测。
技术重难点:海量事件;大量情报的存储与匹配;性能与稳定性。
扫描验证模块
批量进行扫描和验证。
技术重难点:扫描验证任务下发;批量上报处理。
白名单模块
标识正常业务行为,避免无用告警。
技术重难点:白名单规则的表达式与匹配及通用可扩展性;对历史告警加白的性能问题。
响应模块
对告警元素进行响应操作。
技术重难点: 与驱动、客户端、前端的交互。
技术与表达
技术设施
技术设施主要包括技术栈和技术选型。
- 技术选型依据:业界主流(Spring, Kafka, Redis, MySQL, Mongo) + 业务体量 + 通用性。
- 是否要采用阿里/百度/腾讯/美团等开源组件?选择 Spring 还是 Dubbo ?我觉得这个不能凭偏好,而是要看业务体量和通用性。如果吃的饭没有阿里那么大,何必造那么大的锅呢?中小公司的技术选型应该更多适配自己的业务体量,尽可能考虑通用性,而不是偏执地向某个大厂的技术栈靠拢。
- 技术选型,通常采用表格法。列是要对比的多种技术,行是技术所具备的特性。仔细研究自己业务所需的特性,再作出选择。
- 技术选型的主要依据有:需求满足度、成熟度、使用场景和主流应用、性能、稳定性、可扩展性(支持自定义)、控制灵活度、开源及协议、安全性、学习成本、开发效率、团队招聘、技术栈一致性与集成、社区活跃度与技术支持等。具体技术组件还需要根据其功用来确定。
清晰表达设计方案
还是有很多程序员不习惯于写文档,觉得写代码才是正事。在我看来,代码和文档都是一回事,都是表达见解的载体形式。程序员的工作究竟是什么呢?写代码?不完全是,—— 实质是思考和表达见解,解决问题。
文档有一些额外的好处:
- 文档的受众面更广,面向主管、测试、产品、运维、前场、客户等很多群体;而代码只是面向机器和程序员;文档能让你的影响力扩散到更远的地方。
- 写文档能够锻炼表达能力,让思路更加清晰明亮。
系统开发套路
系统开发套路是开发经验的总结。适当提炼和总结系统开发套路,能够加速后续的开发进度,也能让新加入的成员更快地上手开发,更好地完成工作。
开发套路包括完成某类功能或扩展能力,需要如何添加代码。基于开闭原则和接口编程的思想,系统的扩展性可以通过定义和实现各种接口来实现。其次是添加 if-else 分支。
类似这样:
小结
程序员往往容易沉溺于功能开发中。一个接一个的功能开发,无休止重复 CRUD 的工作。这其实是一种麻醉。简单重复的工作,并不利于能力的提升。建立系统整体观,运用架构的思维,从系统整体和模块角度去思考系统构建,能够让程序员看得更远,进阶速度更快。