怎样做论坛网站,济南市高新技术官方网站开发区,个人建网站首选什么域名好,手机开发者模式怎么打开文章目录 架构设计为什么要进行技术框架的设计 六大设计原则一、单一职责原则二、开闭原则三、依赖倒置原则四、接口分离原则五、迪米特法则#xff08;又称最小知道原则#xff09;六、里氏替换原则案例诠释 常见设计模式构造型单例模式工厂模式简单工厂工厂方法 生成器模式… 文章目录 架构设计为什么要进行技术框架的设计 六大设计原则一、单一职责原则二、开闭原则三、依赖倒置原则四、接口分离原则五、迪米特法则又称最小知道原则六、里氏替换原则案例诠释 常见设计模式构造型单例模式工厂模式简单工厂工厂方法 生成器模式 行为型监听者观察者模式中介者模式代理模式责任链模式 结构型适配器包装模式 分布式理论CAP一致性协议两阶段提交三阶段提交 高性能负载均衡常见负载均衡算法存在的问题虚拟节点 架构设计
为什么要进行技术框架的设计
模块化功能使得程序模块化即内部高聚合模块之间低耦合提高开发效率开发人员只需要专注于一点视图显示、业务逻辑、数据处理提高测试效率后期测试时可以迅速根据报错反馈定位到问题出现的位置。
六大设计原则
六大设计原则是设计模式的理论设计模式是设计原则的实践。
一、单一职责原则
一个类只负责一个职责术语叫仅有一个引起变化的原因。一个类应该是一组相关性很高的函数及数据的封装。
二、开闭原则
一个软件实体应该对扩展开放对修改关闭。 提倡一个类一旦开发完成后序增加新的功能不应该通过修改这个类实现而是通过继承或者接口实现增加新的类。
三、依赖倒置原则
抽象不应该依赖于细节细节应该依赖于抽象。换言之要针对接口编程而不是针对实现编程。
也就是说两个模块之间的通信应该通过接口来实现。 四、接口分离原则
使用多个专门的接口而不使用单一的总接口即客户端不应该依赖那些它不需要的接口。即让调用者依赖的接口尽可能小接口分离类似于单一职责原则。
五、迪米特法则又称最小知道原则
一个软件实体应该尽可能地减少与其他实体发生相互作用。或者说一个类对自己需要调用的类知道得最少类的内部应该与被调用者无关也称迪米特隔离。
例如使用一个Thread类下边的run方法按照迪米特原则可以把run单独抽离出来构建一个Runnable接口供userClass使用这样调用者userClass与Thread之间的交互是最少的。
六、里氏替换原则
所有引用基类父类的地方必须能够透明的使用其子类的对象。即一个软件系统中把所有用到某个类的地方都替换为其子类系统应该仍然可以正常工作。这个原则依赖面向对象的继承特性和多态特性。
案例诠释
按照单一职责原则构建一个类或者接口基于开闭原则继承类或者实现接口来构建新类。基于里式替换原则所有使用父类的地方可以使用子类来替换。与其他类之间交互时基于依赖倒置原则使用接口通信。接口设计时基于接口隔离原则应该设计多个专门实现某种功能的接口基于迪米特原则老师类要实现对同学的点名应该通过一个用来跟同学交互的班长分层次实现。 常见设计模式
构造型
单例模式
饿汉单例初始化时直接创建一个静态的实例对象这种方式天生就是线程安全的。 懒汉单例实际需要使用时才创建需要利用线程同步机制有下边三种写法
同步代码块私有化构造函数静态化实例成员公开获取单例的静态方法如果检测到实例未创建使用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;}
}使用同步方法直接给获取单例的静态方法整体上锁。
class Single {private Single(){}private static Single single;public static synchronized Single GetInstance() {if (single null) {single new Single();}return single;}
}
静态内部类 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也崩溃由此导致整个集群宕机。这种情况被称为雪崩效应。
这两个问题都可以通过虚拟节点来解决。
虚拟节点
每台实际机器节点分配大量的虚拟节点虚拟节点量大保证了在哈希输入环域上的均衡只要记录好实际节点与虚拟节点的映射即可。 当增加或者减少机器时同样增加或减少等多的大量虚拟节点在虚拟节点上完成数据迁移即可。 同时还可根据实际机器内存的大小分配不同数量的虚拟节点假定每个虚拟节点的负载能力一致以此用于负载的管理。