软件的复杂度和它的规模成指数关系
一个复杂度为 100 的软件系统,如果能拆分成两个互不相关、同等规模的子系统,那么每个子系统的复杂度应该是 25,而不是 50。如果让你来设计一个淘宝,你会一头雾水,但是如果让你来做一个登录页面,你就会非常清晰了。
组件内聚原则
组件内聚原则主要讨论哪些类应该聚合在同一个组件中,以便组件既能提供相对完整的功能,又不至于太过庞大。(复用发布等同原则、共同封闭原则、共同复用原则)
复用发布等同原则
软件复用的最小粒度应该等同于其发布的最小粒度。也就是说,如果你希望别人以怎样的粒度复用你的软件,你就应该以怎样的粒度发布你的软件。比如,Spring 早期的版本把所有功能整合在一个 jar 包里面,使用者必须完全依赖整个 jar 包,而后面的版本进行了细粒度的拆分,以便用户可以更细粒度地进行依赖。
版本号约定建议
版本号格式:主版本号.次版本号.修订号。比如:1.2.3。
主版本号升级,表示组件发生了不向前兼容的重大修订。
次版本号升级,表示组件进行了重要功能修订或者 bug 修复,但是组件是向前兼容的。
修订号升级,表示组件进行了不重要的功能修订或 bug 修复。
共同封闭原则
我们应该将那些会同时修改,并且为了相同目的而修改的类放到同一组件中。而将不会同时修改,并且不会为了相同目的而修改的类放到不同的组件中。比如:某个组件修改了,而我的组件和被修改组件不相干,不应该受到牵连。
共同复用原则
共同复用原则是说,不要强迫一个组件的用户依赖他们不需要的东西。也就是说,我们应该将互相依赖,共同复用的类放在一个组件中。共同复用和共同封闭原则是相互冲突的。
组件耦合原则
组件内聚原则讨论的是组件应该包含哪些功能和类,而组件耦合原则讨论组件之间的耦合关系应该如何设计。(无循环依赖原则、稳定依赖原则、稳定抽象原则)
无循环依赖原则
无循环依赖原则说,组件依赖关系中不应该出现环。如果组件 A 依赖组件 B,组件 B 依赖组件 C,组件 C 又依赖组件 A,就形成了循环依赖。
稳定依赖原则
组件的依赖关系必须指向更稳定的方向。较少变更的组件是稳定的,也就是说,经常变更的组件是不稳定的。根据稳定依赖原则,不稳定的组件应该依赖稳定组件,而不是反过来。
稳定抽象原则
一个组件的抽象化程度应该与其稳定性程度一致。也就是说,一个稳定的组件应该是抽象的,而不稳定的组件应该是具体的。
XSS 攻击
防御手段:消毒,过滤恶意字符。
SQL 注入攻击
防御手段:消毒,过滤非法字符是一种简单粗暴的手段。预编译。
黑客获取表结构的手段:错误回显、盲注、开源
CSRF 攻击
防御手段:表单 token,Referer 检查,验证码(识别出来到底是人还是机器人)
Web 应用防火墙
开源实现 ModSecurity,最宝贵的就是识别攻击的正则表达式。
网站安全漏洞扫描
和电脑安全漏洞扫描一样,网站也需要安全漏洞扫描。
单向散列加密
密文不可逆的,相当于一个指纹。常用在用户密码的保护。我们并不需要知道原始密码到底是什么,我们只要知道密码对不对就行了。
任何一个系统都不能做到取回密码的功能,只能做到重置密码。能做到取回密码的功能的网站,说明系统本身就是脆弱的了。
对称加密
场景:电商支持信用卡支付,电商网站需要跟银行进行交互,此时需要通过对称加密保存信用卡号、手机号和安全码。
非对称加密
场景:https 握手、数字签名、区块链
秘钥安全管理与加解密服务系统架构
秘钥管理,比如写在配置文件或者代码里面,是非常不安全的,对于有源码权限的人来说,加密算法、秘钥都是可见的,那就没有秘密可言了。主要是为了防自己人,真的出了问题了,也能自证清白。
反垃圾邮件
先批量通过人工标记的方式标注一批邮件,再经过分类算法进行训练,得到分类模型。分类算法加载最新分类模型,对待处理邮件进行处理,就可以得出邮件是正常邮件或垃圾邮件的概率。主要是利用贝叶斯分类算法进行分类,如根据“茶叶”这个词分别出现在垃圾邮件和非垃圾邮件的概率,可以推断出一封邮件包含了“茶叶”关键字,这封邮件是垃圾邮件的概率。分类算法训练,就是要计算出这些:P(A|B)、P(A)、P(B)。
布隆过滤器黑名单
电子商务风险控制
反欺诈、反黄牛、反洗钱、反黑客盗号、反竞争对手恶意下单占用库存等等。风控的手段包括机器自动识别和人工识别。机器自动识别的方式主要有规则引擎和机器学习。
规则引擎
当交易某些指标满足一定条件的时候,就会被认为具有高风险的欺诈可能性。比如:
-
用户来自欺诈高发地区
-
交易金额超过某个数值
-
和上次登录地址距离差距很大
-
用户登录地与收货地不符
-
用户第一次交易
大型网站在运营过程中,结合业界最新发现,会总结出数以千计此类高风险交易的规则。如果来业务逻辑中进行实现,会充沛大量的 if-else,并且要经常修改发布。
机器学习
规则引擎技术虽然简单,但是随着规则逐渐增加,出现规则冲突,难以维护的情况,而且随着规则数量的增多,性能越来越差。大型互联网应用更倾向于使用机器学习模型进行风控。
可用性指标
网站年度可用性指标=(1-网站不可用时间/年度总时间)X 100%
网站不可用时间(故障时间)= 故障修复时间点 - 故障发现(报告)时间点
故障分管理
故障处理流程及考核
引起故障的原因
-
硬件故障
-
软件 bug
-
系统发布
-
并发压力
-
网络攻击
-
外部灾难
高可用系统架构思路
解耦
-
高内聚、低耦合的组件设计原则
-
面向对象基本设计原则
-
面向对象设计模式
-
领域驱动设计建模
隔离
-
业务与子系统隔离
-
微服务与中台架构
-
生产者与消费者隔离
-
虚拟机与容器隔离
异步
-
多线程编程
-
反应式编程
-
异步通信网络编程
-
事件驱动异步架构
重试
备份(冗余)
-
集群设计
-
数据库复制(CAP 原理)
Failover(失效转移)
-
数据库主主失效转移
-
负载均衡失效转移
失效转移的情况,需要关注的点是幂等
事务补偿
-
传统事务的 ACID
-
分布式事务 BASE
事务补偿:通过执行业务逻辑逆操作,使得事务回滚到事务前的状态
熔断
断路器三状态:关闭(服务正常调用)、打开(服务直接返回失败)、半开(部分正常调用)。
限流
限流是指对进入系统的用户请求进行流量限制,如果访问量超过了系统的最大处理能力,就会丢弃一部分的用户请求,保证整个系统可用,保证大部分用户是可以访问系统的。
限流的几种算法:
-
计数器(固定窗口、滑动窗口)
-
令牌桶算法
-
漏桶算法
计数器(固定窗口)算法:
计数器(滑动窗口)算法:
令牌桶算法:
漏桶算法:
请求进来先放到漏桶里面,有个另外的线程以固定速度从漏桶取出请求进行处理。
自适应限流
没有提前人工评估,实时自动评估 QPS。业务流量的不确定性与技术方案的自适应性天生一对。
降级
有一些系统功能是非核心的,但是它却给系统产生了非常大的压力,比如电商里面的确认收货这个功能,即便我们不去确认收货,系统也会超时自动确认收货。但实际上确认收货这个操作逻辑非常重,因为它会给数据库造成非常大的压力,它要修改订单状态,完成支付确认,并进行评价等一系列操作。比如淘宝双 11 的时候,就可以将确认收货、评价这些非核心的功能暂时关闭。将宝贵的机器资源留给正在购物的人。资源有限的情况下,尽量把机器资源留给那些高价值的操作(比如:下单购物)去。
异地多活
将数据中心分布在多个不同地点的机房里,这些机房都可以对外提供服务,用户连接任何一个机房都能得到正常的服务。异地多活的难点是数据一致性。
高可用系统的运维策略
发布高可用
自动化测试
在系统演化的早期,功能不确定,系统也不稳定,自动化测试的各种准备也不足,此时手工测试比较合适。但是随着时间推移,系统不断演化变得稳定了,此时采用自动化测试成本就比较低了。
自动化部署
持续部署三步走:
1)持续集成,向公共分支提交代码并触发自动化测试。
2)持续交付,除了跑单元测试及打包,持续交付还会将软件部署到测试环境。
3)持续部署,代码在没有人工干预的情况下,被测试、构建、部署并推送生产环境。
持续部署的流程:
预发布验证
即使经过非常严格的测试,软件部署到线上还是不可避免地会出现各种问题,甚至服务启动失败。
自动化发布
对于单体系统来说比较重要,对于微服务而言,一般来说各发布各的,比较灵活。
灰度发布
对于大规模的服务集群比较有用。
网站运行监控
绝对不允许没有监控的系统裸奔上线。(监控数据采集、用户行为日志采集、服务器性能监控、业务运行数据报告)当指标异常时,可以通过告警和自动控制的方式进行处理。
监控系统架构
高可用价值观
保持简单,使问题易于发现,快速解决。
目标明确,解决特定环境下的具体问题。
价值回归,成本收益要合理。原文转载架构师训练营第十一周学习总结_极客大学架构师训练营_CATTY_InfoQ写作平台