知识体系总结(九)设计原则、设计模式、分布式、高性能、高可用

news2024/11/20 1:27:28

文章目录

  • 架构设计
    • 为什么要进行技术框架的设计
  • 六大设计原则
    • 一、单一职责原则
    • 二、开闭原则
    • 三、依赖倒置原则
    • 四、接口分离原则
    • 五、迪米特法则(又称最小知道原则)
    • 六、里氏替换原则
    • 案例诠释
  • 常见设计模式
    • 构造型
      • 单例模式
      • 工厂模式
        • 简单工厂
        • 工厂方法
      • 生成器模式
    • 行为型
      • 监听者(观察者)模式
      • 中介者模式
      • 代理模式
      • 责任链模式
    • 结构型
      • 适配器(包装)模式
  • 分布式理论
    • CAP
    • 一致性协议
      • 两阶段提交
      • 三阶段提交
  • 高性能
    • 负载均衡
      • 常见负载均衡算法
      • 存在的问题
      • 虚拟节点

架构设计

为什么要进行技术框架的设计

  • 模块化功能:使得程序模块化,即内部高聚合,模块之间低耦合
  • 提高开发效率:开发人员只需要专注于一点(视图显示、业务逻辑、数据处理)
  • 提高测试效率:后期测试时可以迅速根据报错反馈,定位到问题出现的位置。

六大设计原则

六大设计原则是设计模式的理论,设计模式是设计原则的实践。

一、单一职责原则

一个类只负责一个职责,术语叫仅有一个引起变化的原因。一个类应该是一组相关性很高的函数及数据的封装。

二、开闭原则

一个软件实体应该对扩展开放,对修改关闭。
提倡一个类一旦开发完成,后序增加新的功能,不应该通过修改这个类实现,而是通过继承或者接口实现增加新的类。

三、依赖倒置原则

抽象不应该依赖于细节,细节应该依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

也就是说两个模块之间的通信应该通过接口来实现。

在这里插入图片描述

四、接口分离原则

使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。即让调用者依赖的接口尽可能小,接口分离类似于单一职责原则。

五、迪米特法则(又称最小知道原则)

一个软件实体应该尽可能地减少与其他实体发生相互作用。或者说一个类,对自己需要调用的类知道得最少,类的内部应该与被调用者无关,也称迪米特隔离

例如使用一个Thread类下边的run方法,按照迪米特原则,可以把run单独抽离出来,构建一个Runnable接口供userClass使用,这样调用者userClass与Thread之间的交互是最少的。
在这里插入图片描述

六、里氏替换原则

所有引用基类(父类)的地方,必须能够透明的使用其子类的对象。即一个软件系统中,把所有用到某个类的地方都替换为其子类,系统应该仍然可以正常工作。这个原则依赖面向对象的继承特性和多态特性。

案例诠释

  1. 按照单一职责原则构建一个类或者接口
  2. 基于开闭原则继承类或者实现接口,来构建新类。
  3. 基于里式替换原则,所有使用父类的地方可以使用子类来替换。
  4. 与其他类之间交互时,基于依赖倒置原则,使用接口通信。
  5. 接口设计时,基于接口隔离原则,应该设计多个专门实现某种功能的接口
  6. 基于迪米特原则,老师类要实现对同学的点名,应该通过一个用来跟同学交互的班长,分层次实现。

在这里插入图片描述

常见设计模式

构造型

单例模式

饿汉单例:初始化时直接创建一个静态的实例对象,这种方式天生就是线程安全的。
懒汉单例:实际需要使用时才创建,需要利用线程同步机制,有下边三种写法:

  1. 同步代码块:私有化构造函数,静态化实例成员,公开获取单例的静态方法,如果检测到实例未创建,使用synchronized构建同步代码块,因为是静态方法,所以使用类的字节码(类名.class)对象作为synchronized的锁对象。
class SingleInstance {
    private SingleInstance() {
    }
    private static SingleInstance singleInstance;
    public static SingleInstance getInstance() {
        if (singleInstance == null) {
            synchronized (SingleInstance.class) {
                if (singleInstance == null) {
                    singleInstance = new SingleInstance();
                }
            }
        }
        return singleInstance;
    }
}
  1. 使用同步方法,直接给获取单例的静态方法整体上锁。
class Single {
    private Single(){
        
    }
    private static Single single;
    public static synchronized Single GetInstance() {
        if (single == null) {
            single = new Single();
        }
        return single;
    }
}

  1. 静态内部类 + final 内部成员

静态内部类的成员只在初次调用时被初始化,非常符合懒汉单例的方式。

class SingleByInner{
    private SingleByInner() {
		
    }
    static class Inner {
        private static final SingleByInner INSTANCE = new SingleByInner();
    }
    public static SingleByInner getInstance() {
        return Inner.INSTANCE;
    }
}

class SingleByInner{
    private SingleByInner() {
		
    }
    static class Inner {
        private static final SingleByInner INSTANCE = new SingleByInner();
    }
    public static SingleByInner getInstance() {
        return Inner.INSTANCE;
    }
}

工厂模式

简单工厂

  • 简单工厂模式提出是为了实现在创建一个对象时,不向客户暴露内部细节,只提供一个创建对象的通用接口。(基于了迪米特法则/最小知道原则)
  • 简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应用用哪个具体子类来实例化。
  • 这样做能把客户类和具体子类的实现解耦,在业务中我们往往有多个客户类,如果客户类要知道所有子类的细节,一旦子类发生改变,那么所有的客户类都要修改。使用工厂模式则只需要修改工厂类,并在需要子类的客户类使用时修改接口参数即可。

工厂方法

  • 定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到了子类
  • 在简单工厂中,创建对象的是工厂类,而在工厂方法中,是由工厂类的子类来创建对象。

生成器模式

封装一个对象的构造过程,并允许按步骤构造
在这里插入图片描述

行为型

监听者(观察者)模式

监听者用来监听自已感兴趣的事件,当收到自已感兴趣的事件时执行自定义的操作。

监听者模式在Android中有大量的运用,相信大家都不会感到陌生。在Android开发中,Button控件的点击事件就是监听者模式最常见的例子。

当Button被点击,执行了 OnClickListener.onClick。 Activity中给这个Button设置了自己实现的OnClickListener,并复写了onClick方法,就能执行自定义操作了。

中介者模式

用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地互相作用, 从而达到松耦合的目的。

由以下几个部分组成

  • mediator 抽象中介者 - 用于协调各个同事之间的交互
  • Concrete mediator 具体中介者角色 - 依赖于各个同事类
  • Colleague 同事角色(要被封装的对象)

每个同事角色都知道中介者角色,但不与其他同事进行交互,而是通过中介者来调度。

  • 优点是减少类间的依赖,把原来的一对多的依赖关系改变成了一对一的依赖。降低耦合。
  • 缺点是中介者会变得很庞大,逻辑复杂。

代理模式

为其他对象提供一种代理以控制对这个对象的访问。也叫委托模式。
主要有三个角色:

  • Subject抽象主题角色。 可以是抽象类或接口,是一个最普通的业务类型定义,无特殊要求。
  • RealSubject具体主题角色。 也叫被委托角色、被代理角色。是具体业务的执行者。
  • Proxy代理主题角色。 也叫委托类、代理类。负责对真实角色的应用,可以添加自定义的操作,例如预操作和善后处理。

优点:

  • 职责清晰 - 真实角色只负责实现实际的业务逻辑,不用关系其他事务。代理可以完成更多工作。
  • 高扩展性 - 只要实现了接口,具体主题角色的实现可以高度地改变,而不用改代理。

责任链模式

责任链模式是一种行为型设计模式,它用于将多个请求处理器对象连接成一条链,可以让请求沿着这条链不断地传递,直到有一个请求处理器处理完成为止,实现高效灵活的请求处理与分发。

主要涉及三个角色:

  • 抽象处理器(Handler):定义了一个处理请求的接口,并维护了一个后继处理器对象。
  • 具体处理器(ConcreteHandler):实现了处理请求的接口,并决定能否处理该请求。如果不能处理,则将请求转发给后继处理器。
  • 客户端(Client):创建一个请求处理器对象,并将其添加到责任链中。

优点:

  • 降低耦合度:责任链模式将请求的发送者和接收者解耦,请求会从链的开端一直沿着链传递到链的结尾,期间每个节点只需要关注自己的处理逻辑,从而降低了节点之间的耦合度。
  • 灵活性增强、可拓展性好:责任链模式可以动态地增加或删除节点对象,改变链中节点对象的调用顺序,灵活的修改或者拓展系统流程。

缺点:

  • 链太长时,会降低系统性能和效率
  • 请求不一定可以被处理,可能存在到达链的末尾,仍然没有合适的处理节点对其进行处理,这时候需要特殊的处理机制来处理这种情况。
  • 调试困难:如果链中某个节点的调用出现问题,可能会导致整个链的请求无法被处理,导致调试时需要逐一排查。

结构型

适配器(包装)模式

将一个类的接口变换成客户端锁期待的另一种接口,从而使原本因接口不匹配而无法工作在一起的两个类能够在一起工作。

优点:

  • 可以让没有任何关系的类在一起运行
  • 增加了类的透明性
  • 提高了类的复用度

分布式理论

CAP

CAP 也就是 Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性) 这三个单词首字母组合。
在这里插入图片描述

CAP 定理(CAP theorem)指出对于一个分布式系统来说,当设计读写操作时,只能同时满足以下三点中的两个:

  • C:一致性(Consistency) : 所有节点访问同一份最新的数据副本
  • A:可用性(Availability): 非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应)。
  • P:分区容错性(Partition Tolerance) : 分布式系统出现网络分区的时候,仍然能够对外提供服务。

什么是网络分区?

分布式系统中,多个节点之间的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题)某些节点之间不连通了,整个网络就分成了几块区域,这就叫 网络分区。

大部分人解释这一定律时,常常简单的表述为:“一致性、可用性、分区容忍性三者你只能同时达到其中两个,不可能同时达到”。实际上这是一个非常具有误导性质的说法,而且在 CAP 理论诞生 12 年之后,CAP 之父也在 2012 年重写了之前的论文。

当发生网络分区的时候,如果我们要继续服务,那么强一致性和可用性只能 2 选 1。也就是说当网络分区之后 P 是前提,决定了 P 之后才有 C 和 A 的选择。也就是说分区容错性(Partition tolerance)我们是必须要实现的。
简而言之就是:CAP 理论中分区容错性 P 是一定要满足的,在此基础上,只能满足可用性 A 或者一致性 C。

因此,分布式系统理论上不可能选择 CA 架构,只能选择 CP 或者 AP 架构。 比如 ZooKeeper、HBase 就是 CP 架构,Cassandra、Eureka 就是 AP 架构,Nacos 不仅支持 CP 架构也支持 AP 架构。

为啥不可能选择 CA 架构呢?
举个例子:若系统出现“分区”,系统中的某个节点在进行写操作。为了保证 C, 必须要禁止其他节点的读写操作,这就和 A 发生冲突了。如果为了保证 A,其他节点的读写操作正常的话,那就和 C 发生冲突了。

选择 CP 还是 AP 的关键在于当前的业务场景,没有定论,比如对于需要确保强一致性的场景如银行一般会选择保证 CP 。

另外,需要补充说明的一点是:如果网络分区正常的话(系统在绝大部分时候所处的状态),也就说不需要保证 P 的时候,C 和 A 能够同时保证。

一致性协议

两阶段提交

三阶段提交

高性能

负载均衡

负载均衡 指的是将用户请求分摊到不同的服务器上处理,以提高系统整体的并发处理能力以及可靠性。负载均衡服务可以有由专门的软件或者硬件来完成,一般情况下,硬件的性能更好,软件的价格更便宜。

最常见的是四层和七层负载均衡:
在这里插入图片描述

  • 四层负载均衡 工作在 OSI 模型第四层,也就是传输层,这一层的主要协议是 TCP/UDP,负载均衡器在这一层能够看到数据包里的源端口地址以及目的端口地址,会基于这些信息通过一定的负载均衡算法将数据包转发到后端真实服务器。也就是说,四层负载均衡的核心就是 IP+端口层面的负载均衡,不涉及具体的报文内容。
  • 七层负载均衡 工作在 OSI 模型第七层,也就是应用层,这一层的主要协议是 HTTP 。这一层的负载均衡比四层负载均衡路由网络请求的方式更加复杂,它会读取报文的数据部分(比如说我们的 HTTP 部分的报文),然后根据读取到的数据内容(如 URL、Cookie)做出负载均衡决策。也就是说,七层负载均衡器的核心是报文内容(如 URL、Cookie)层面的负载均衡,执行第七层负载均衡的设备通常被称为 反向代理服务器

七层负载均衡比四层负载均衡会消耗更多的性能,不过,也相对更加灵活,能够更加智能地路由网络请求,比如说你可以根据请求的内容进行优化如缓存、压缩、加密。

简单来说,四层负载均衡性能更强,七层负载均衡功能更强! 不过,对于绝大部分业务场景来说,四层负载均衡和七层负载均衡的性能差异基本可以忽略不计的。

在工作中,我们通常会使用 Nginx 来做七层负载均衡,LVS(Linux Virtual Server 虚拟服务器, Linux 内核的 4 层负载均衡)来做四层负载均衡。

常见负载均衡算法

  • 随机法:如果没有配置权重的话,所有的服务器被访问到的概率都是相同的。如果配置权重的话,权重越高的服务器被访问的概率就越大。
  • 轮询法:轮询算法适合于服务器性能相近的集群,其中每个服务器承载相同的负载。加权轮询算法适合于服务器性能不等的集群,权重的存在可以使请求分配更加合理化。
  • 最小连接法:当有新的请求出现时,遍历服务器节点列表并选取其中活动连接数最小的一台服务器来响应当前请求。活动连接数可以理解为当前正在处理的请求数。不过,这种方法实现起来也最复杂,需要监控每一台服务器处理的请求连接数。
  • 一致性 Hash 法:
    将哈希函数输出空间想象为一个环形域:

在这里插入图片描述
不同对象数据通过哈希映射到环上:

在这里插入图片描述
使用相同的哈希映射输入服务器的唯一标识码将机器也映射到这个环上:
在这里插入图片描述
对象与机器处于同一哈希空间中,这样按顺时针转动,:m1存储到了t3中,m3和m4存储到了t2中,m2存储到了t1中。

在这里插入图片描述
当需要增加一台机器t4时:仅需要修改m4-> t2 为
m4 -> t4
数据的移动仅发生在t2和t4之间,其他机器上的数据并未受到影响。
在这里插入图片描述
当删除一台机器t1时,需修改m2->t1 为 m2->t3,数据迁移仅发生在t1和t3之间。
在这里插入图片描述

存在的问题

  • 问题1 机器节点数量少时,数据归属域不均衡
    当集群中的节点数量较少时,可能会出现节点在哈希空间中分布不平衡的问题。如下图所示,图中节点A、B、C分布较为集中,造成hash环的倾斜。数据1、2、3、4、6全部被存储到了节点A上,节点B上只存储了数据5,而节点C上什么数据都没有存储。A、B、C三台机器的负载极其不均衡。
    在这里插入图片描述

  • 问题2 数据迁移时导致负载不均衡
    在极端情况下,假如A节点出现故障,存储在A上的数据要全部转移到B上,大量的数据导可能会导致节点B的崩溃,之后A和B上所有的数据向节点C迁移,导致节点C也崩溃,由此导致整个集群宕机。这种情况被称为雪崩效应。

这两个问题都可以通过虚拟节点来解决。

虚拟节点

每台实际机器(节点),分配大量的虚拟节点,虚拟节点量大,保证了在哈希输入环域上的均衡,只要记录好实际节点与虚拟节点的映射即可。
当增加或者减少机器时,同样增加或减少等多的大量虚拟节点,在虚拟节点上完成数据迁移即可。
在这里插入图片描述
同时还可根据实际机器内存的大小,分配不同数量的虚拟节点(假定每个虚拟节点的负载能力一致),以此用于负载的管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/885987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Kubernetes】Kubernetes之配置资源管理

Secret 和 ConfigMap 一、Secret1. Secret 的作用2. Secret 的类型3. Secret 使用方式及应用场景4. Secret 的实例4.1 创建 Secret4.2 使用方式将 Secret 挂载到 Volume 中,以 Volume 的形式挂载到 Pod 的某个目录下将 Secret 导出到环境变量中 二、 ConfigMap1. Co…

由于找不到mfc140u.dll,无法继续执行代码怎么修复?

当我在使用某个应用程序时遇到了mfc140u.dll缺失的错误提示时,我意识到这是由于该动态链接库文件丢失或损坏所引起的。mfc140u.dll是MFC的一部分,它包含了许多与用户界面、窗口管理、控件等相关的函数和类。这个文件通常用于支持使用MFC开发的应用程序的…

高效服务器DDoS防护,F5安全架构不可少

数字化转型,特别是现代化应用正面临着严峻挑战。如何确保应用的用户体验,用户现有安全架构如何适应现代化应用防护需求,以及 API 安全直接关乎现代化应用的普及和用户的体验,甚至关系到企业数字化能否转型成功。当企业网站或服务器…

HD Supply EDI 项目测试流程

在此前的文章 HD Supply EDI 项目案例中,我们已经为大家介绍了 HD Supply EDI 项目案例,了解了 HD Supply 业务测试场景,本文将为大家介绍 EDI 项目测试流程。 HD Supply EDI 项目连接测试 在HD Supply EDI 项目中,CommerceHub为…

[oneAPI] 手写数字识别-BiLSTM

[oneAPI] 手写数字识别-BiLSTM 手写数字识别参数与包加载数据模型训练过程结果 oneAPI 比赛:https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel DevCloud for oneAPI:https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToo…

[obs] 编译记录

2023.7 obs 最近编译方式经常改。本次使用的是最新的方式编译 2023/7月份版本,记录一下遇到的坑 obs 最新版默认使用 vs2022 才能编译,如果想用 vs2019 编译,改下面这个地方就好了 CMakePresets.json 文件的obs aja 编译有问题 解决方案&a…

【方法】如何给分卷压缩文件添加密码?

在压缩文件的时候,如果文件比较大,或者网盘单个文件限制了大小,很多人会选择将文件压缩成分卷文件。 如果文件还有保密需求,那如何在压缩文件时设置分卷,又同时设置密码保护呢?下面小编来举例看看如何操作…

测试平台开发:(19)自动化测试脚本工具化 2

上一篇:测试平台开发:(18)自动化测试脚本工具化_要开朗的spookypop的博客-CSDN博客 本篇先实现创建自动化脚本的功能,将selenium代码语言转化为文字语言,如下图所示: 例1:比如下面的代码,转化为语言“用谷歌浏览器打开XX页面”: service = ChromeService(executabl…

【Python】基础语法:变量类型和动态类型

文章目录 1. 常量2. 变量3. 动态类型特性 努力经营当下 直至未来明朗 1. 常量 浮点数在内存中表示使用的是IEEE754标准,这套规则下,在内存中表示该浮点数额时候可能会存在微小的误差 在进行运算的时候,最好可以将数字(字面值常…

如何理解“I/O指令是CPU系统指令的一部分”?

I/O指令作用过程(以 I/O端口独立编址方式为例): CPU识别出当前指令是I/O指令,向I/O总线发送相应控制信号和地址信息。 之前迷惑的点:默认以为I/O指令是作用于I/O接口的,进而产生疑问,I/O接口中…

期权行权和不行权的区别

对于期权小白刚入门来说,期权是一种金融衍生品,简单理解期权就是大盘指数为标的物,可以做多和做空,在期权到期日最后一天,你面临持仓合约是选择行权呢还是不行权,下文科普期权行权和不行权的区别&#xff0…

03.Spring Security 如何保护用户密码

1. 前言 上一文我们对Spring Security中的重要用户信息主体UserDetails进行了探讨。中间例子我们使用了明文密码,规则是通过对密码明文添加{noop}前缀。那么本节将对 Spring Security 中的密码编码进行一些探讨。 2. 不推荐使用md5 首先md5 不是加密算法&#xf…

前端跨域的原因以及解决方案(vue),一文让你真正理解跨域

跨域这个问题,可以说是前端的必需了解的,但是多少人是知其然不知所以然呢? 下面我们来梳理一下vue解决跨域的思路。 什么情况会跨域? ​ 跨域的本质就是浏览器基于同源策略的一种安全手段。所谓同源就是必须有以下三个相同点:协议相同、域名…

网络套接字

网络套接字 文章目录 网络套接字认识端口号初识TCP协议初识UDP协议网络字节序 socket编程接口socket创建socket文件描述符bind绑定端口号sockaddr结构体netstat -nuap:查看服务器网络信息 代码编译运行展示 实现简单UDP服务器开发 认识端口号 端口号(port)是传输层协…

Python 3 使用HBase 总结

HBase 简介和安装 请参考文章:HBase 一文读懂 Python3 HBase API HBase 前期准备 1 安装happybase库操作hbase 安装该库 pip install happybase2 确保 Hadoop 和 Zookeeper 可用并开启 确保Hadoop 正常运行 确保Zookeeper 正常运行3 开启HBase thrift服务 使用命…

谈谈召回率(R值),准确率(P值)及F值

通俗解释机器学习中的召回率、精确率、准确率,一文让你一辈子忘不掉这两个词 赶时间的同学们看这里:提升精确率是为了不错报、提升召回率是为了不漏报 先说个题外话,暴击一下乱写博客的人,网络上很多地方分不清准确率和精确率&am…

前端实战系列:【2023酷炫前端特效】HTML蜂巢特效(附完整可执行代码 + 全网唯一!超详细注释分析 (熬夜换来的...),让你看得懂,敲的出代码!

久别重逢非昨日,万语千言不忍谈。 🎯作者主页: 追光者♂🔥 🌸个人简介: 💖[1] 计算机专业硕士研究生💖 🌿[2] 2023年城市之星领跑者TOP1(哈尔滨)🌿 🌟[3] 2022年度博客之星人工智能领域TOP4🌟 🏅[4] 阿里云社区特邀专家博主🏅 🏆…

【等保测评】等保初级测评师试题合集(3w字汇总)

【等保测评】信息安全等级保护初级测评师试题合集 一、法律法规单选多选判断 二、实施指南单选多选 三、定级指南四、基本要求五、测评准则六、信息安全等级测评模拟模拟试题1一、单选二、多选三、判断四、简答 模拟试题2一、单选二、多选三、判断四、简答 模拟试题3一、单选二…

MPLS基础知识

MPLS:多协议标签交换 多协议:可以基于多种不同的3层协议来生成2.5层的标签信息; 包交换—包为网络层的PDU,故包交换是基于IP地址进行数据转发;就是路由器的路由行为; 原始的包交换:数据包进入…

【自动化测试】接口自动化01

文章目录 一、熟悉若requests库以及底层方法的调用逻辑二、接口自动化以及正则和Jsonpath提取器的应用6. 高频面试题:9. 示例:接口关联13. 文件上传示例14. cookie关联的接口 努力经营当下 直至未来明朗 一、熟悉若requests库以及底层方法的调用逻辑 接…