应用架构
单一应用架构ORM
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。
缺点:
1、性能扩展比较难
2、协同开发问题
3、不利于升级维护
垂直应用架构MVC
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展也更方便,更有针对性。
缺点: 公用模块无法重复利用,开发性的浪费
分布式服务架构RPC
RPC(Remote Procedure Call):远程过程调用。
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
分布式系统所依赖的基础设施包括服务框架、消息中间件、数据访问中间件、配置中心、分布式缓存系统、持久化存储(关系数据库、nosql数据库)、搜索引擎、CDN网络、负载均衡系统、运维自动化系统、硬件虚拟化及镜像管理系统、分布式文件系统、日志收集系统、监控系统、离线计算、实时计算、数据仓库等等。
流计算架构SOA
SOA(Service Oriented Architecture):资源调度和治理中心。
当服务越来越多,服务之间的调用和依赖关系也越来越复杂。容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)[ Service Oriented Architecture]是关键。
服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架
分布式服务架构
把一个计算任务分解成若干个计算单元,并分派到不同的计算机中去执行,最终汇总计算结果的过程。
分布式系统(distributed system)是建立在网络之上的软件系统。由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。
首先需要明确的是,只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。因为,分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。
分布式系统 = 分布式计算(computation)+ 分布式存储(storage)。
计算与存储是相辅相成的,计算需要数据,要么来自实时数据(流数据),要么来自存储的数据;而计算的结果也是需要存储的。在操作系统中,对计算与存储有非常详尽的讨论,分布式系统只不过将这些理论推广到多个节点罢了。
那么分布式系统怎么将任务分发到这些计算机节点呢,很简单的思想,分而治之,即分片(Partition)。
对于计算,那么就是对计算任务进行切换,每个节点算一些,最终汇总就行了,这就是MapReduce的思想;
对于存储,每个节点存一部分数据。
当数据规模变大的时候,Partition是唯一的选择,它的好处:
(1)提升性能和并发,操作被分发到不同的分片,相互独立。
(2)提升系统的可用性,即使部分分片不能用,其他分片不会受到影响。
理想的情况下,有分片就行了,但事实的情况却不大理想。原因在于,分布式系统中有大量的节点,且通过网络通信。单个节点的故障(进程crash、断电、磁盘损坏)是个小概率事件,但整个系统的故障率会随节点的增加而指数级增加,网络通信也可能出现断网、高延迟的情况。在这种一定会出现的“异常”情况下,分布式系统还是需要继续稳定的对外提供服务,即需要较强的容错性。最简单的办法,就是冗余或者复制集(Replication),即多个节点负责同一个任务,最为常见的就是分布式存储中,多个节点复杂存储同一份数据,以此增强可用性与可靠性。同时,Replication也会带来性能的提升,比如数据的locality可以减少用户的等待时间。
https://www.cnblogs.com/xybaby/p/6930977.html
分布式要解决什么问题呢?
解决持久化数据太大,单个节点的硬盘无法存储的问题;
解决运算量太大,单个节点的内存、CPU无法处理的问题。
解决这些问题,有两种思路:scale up,scale out。
前者就是提升单个节点的能力,更大的磁盘,更快的CPU,定制的软硬件,然而这意味着更高的价格,而且再怎么scale up也是有上限的。
后者就是把存储、计算任务分担到普通的机器上,通过动态增加节点来应对数据量的增长,但缺点是多个节点的管理、任务的调度比较麻烦,这也是分布式系统研究和解决的问题。只有当数据量达到单机无法存储、处理的情况下才考虑分布式,不然都是自找麻烦。
状态的维护比计算要难很多,所谓状态就是需要持久化的数据。因此主要考虑分布式存储,况且即使是分布式计算,为了节省带宽需要尽量保证data locality,也是需要分布式存储。
现在有一堆数据,可能是结构化或者半结构化,需要将数据分片(segment、fragment、shard),形成一个个的数据子集,存储到一组物理节点上,物理节点之间通过网络通信。那么需要考虑两个问题:
第一:数据如何划分;
第二:数据的可靠性、可用性问题
数据分片是指将数据子集尽可能均衡的划分到各个物理节点上。那么会有哪些挑战呢?
1)如果某个物理节点宕机,如何将该物理节点负责的数据尽快的转移到其他物理节点;
2)如果新增了物理节点,怎么从其他节点迁移数据到新节点;
3)对于可修改的数据(即不是只能追加的数据),比如数据库数据,如果某节点数据量变大,怎么将部分数据迁移到其他负载较小的节点,及达到动态均衡的效果。
4)元数据的管理问题:当数据分布在各个节点,那么当用户使用的时候需要知道具体的数据在哪一个节点上。因此,系统需要维护数据的元数据:即每一个数据所在的位置、状态等信息。当用户需要具体的数据时,先查询元数据,然后再去具体的节点上查询。当数据在节点之间迁移的时候,也需要更新元数据。元数据的管理节点这里称之为meta server。元数据的管理也带来了新的挑战:
(4.1)如何抽取数据的特征(特征是分片的依据,也是用户查询数据时的key),或者支持用户自定义数据特征;
(4.2)如何保证meta server的高性能和高可用,是单点还是复制集
5)分片的粒度,即数据子集的大小,也是数据迁移的基本单位。粒度过粗,不利于数据均衡;粒度过细,管理、迁移成本又会比较大。
RPC
https://www.jianshu.com/p/2accc2840a1b
RPC两个核心模块:通讯,序列化。
RPC是一种进程间通信方式,他是一种技术的思想而不是规范。
它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
为什么要用RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯,由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。RPC就是要像调用本地的函数一样去调远程函数;
Dubbo
Apache Dubbo 提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
组件 | 名称 | 用途 |
---|---|---|
Provider | 服务提供者 | 暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。 |
Consumer | 服务消费者 | 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 |
Registry | 注册中心 | 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者 |
Monitor | 监控中心 | 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心 |
调用关系 | |
---|---|
start | 服务容器负责启动,加载,运行服务提供者。 |
register | 服务提供者在启动时,向注册中心注册自己提供的服务。 |
subscribe | 服务消费者在启动时,向注册中心订阅自己所需的服务。 |
notify | 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 |
invoke | 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 |
count | 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 |
Zookeeper分布式协调服务
https://www.cnblogs.com/sunddenly/p/4033574.html
ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services
ZooKeeper是一种集中服务,用于维护配置信息、命名、提供分布式同步和提供组服务
协调 ~= 锁。分布式协调服务的核心和难点就是来实现分布式锁。
主要用来解决分布式环境当中多个进程之间的同步控制,让他们有序的去访问某种临界资源,防止造成"脏数据"的后果。Zookeeper可以看成是分布式锁
同进程内协调
1)你对一个方法的调用如果成功,那就是成功,如果调用失败,比如抛出异常那就是调用失败。
2)在同一个进程内,如果这个方法先调用先执行,那就是先执行。
3)使用锁让有的线程可以先操作这些资源,然后其他线程等待。
分布式环境中协调
1)由于网络的不可靠,对一个服务的调用失败了并不表示一定是失败的,可能是执行成功了,但是响应返回的时候失败了。
2)由于网络的不可靠,A和B都去调用服务C,A先调用,B后调用,但是服务C不一定先收到A的请求。
3)分布式环境中为了提升可靠性,往往会部署多套服务,如何在多套服务中达到一致性
分布式协调远远比同一个进程里的协调复杂得多,所以Zookeeper这类基础服务就应运而生。
应用场景
(1)数据发布/订阅
数据的发布与订阅,顾名思义就是一方把数据发布出来,另一方通过某种手段获取。
通常数据发布与订阅有两种模式:推模式和拉模式,推模式一般是服务器主动往客户端推送信息,拉模式是客户端主动去服务端请求目标数据(通常采用定时轮询的方式)
Zookeeper采用两种方式互相结合:发布者将数据发布到Zookeeper集群节点上,订阅者通过一定的方法告诉Zookeeper服务器,自己对哪个节点的数据感兴趣,那么在服务端数据发生变化时,就会通知客户端去获取这些信息。
(2)负载均衡
首先在服务端启动的时候,把自己在zookeeper服务器上注册成一个临时节点。zookeeper拥有两种形式的节点,一种是临时节点,一种是永久节点。这两种节点后面的会有较为详细的介绍。注册成临时节点后,再服务端出问题时,节点会自动的从zookeeper上删除,如此zookeeper服务器上的列表就是最新的可用的列表。
客户端在需要访问服务器的时候首先会去Zookeeper获得所有可用的服务端的连接信息。
客户端通过一定的策略(如随机)选择一个与之建立连接。
当客户端发现连接不可用时,会再次从zookeeper上获取可用的服务端连接,并同时删除之前获取的连接列表。
(3)命名服务
提供名称的服务。如一般使用较多的有两种id,一种是数据库自增长id,一种是UUID,两种id都有局限,自增长id仅适合在单表单库中使用,uuid适合在分布式系统中使用但由于id没有规律难以理解。而ZK提供了一定的接口可以用来获取一个顺序增长的,可以在集群环境下使用的id。
(4)分布式协调,通知,心跳服务
在分布式服务系统中,我们常常需要知道哪个服务是可用的,哪个服务是不可用的,传统的方式是通过ping主机来实现的,ping得200的结果说明说明该服务是OK的。
而在使用 zookeeper时,可以将所有的服务都注册成一个临时节点,我们判断一个服务是否可用,只需要判断这个节点是否在zookeeper集群中存在就可以了,不需要直接去连接和ping服务所在主机,减少系统的复杂度和对服务主机的压力。
ZooKeeper数据模型
ZooKeeper的数据结构Znode
ZooKeeper的数据结构是树状结构,树中的每个节点被称为Znode。
ZooKeeper中的时间
ZooKeeper节点属性
ZooKeeper服务中操作
Watch触发器
Zab协议
分布式锁
配置维护、组服务、分布式消息队列、分布式通知/协调
发送消息者成为Producer,消息接受者成为Consumer
数据来源
ZooKeeper 集群同一时刻只会有一个 Leader,其他都是 Follower 或 Observer。