一、构建大型网站:分布式改造

1、为什么要做分布式化
随着业务的扩展和流量的爆发式增长,该系统很快达到了瓶颈,是不是一定要对它做分布式改造呢?其实我们早期也尝试用过一些高端的服务器(IOE),但一方面价格昂贵,另一方面这样也阻挡不了瓶颈的到来,分布式改造成为必由之路。
分布式改造必须先解决以下几个问题:
第一,应用需要微服务化。即将大量粗粒度的应用逻辑拆小做服务化改造
第二,必须先建立分布式服务框架。必须具备分布式配置系统、分布式RPC框架、异步消息系统、分布式数据层、分布式文件系统、服务的发现、注册和管理。
第三,必须解决状态一致性问题。
2、典型的分布式架构
分布式架构与传统的单机架构最大的区别在于分布式架构能解决两个方向的扩展问题:一是横向扩展,二是纵向扩展。
横向扩展,主要用来解决应用架构上的容量问题。由于单台服务器能支撑的服务能力始终是有限的,所以我们在架构上就必须做到能够支持横向服务能力的扩展。
纵向扩展,主要解决业务的扩展问题。当业务不断扩展时,业务逻辑的复杂度也会不断上升,所以在架构上要能根据功能的划分进行纵向层次的划分。
需要的分布式中间件:
首先要有一个统一的负载均衡系统(LB/LVS)帮助平均分配外部请求的流量,将这些流量分配到后端的多台机器上。
请求达到服务层,就需要解决服务之间的系统调用。包括同步调度的分布式RPC框架、异步调度的分布式消息框架、解决静态配置信息的分布式配置框架。
请求到达数据层。需要解决以下问题:第一,屏蔽不同数据库的差异性,使底层数据库的切换不影响上次应用代码。第二,屏蔽应用层代码对数据分布的感知,使对数据的分区或分片不会影响应用代码的编写。
服务化和分布式化:
服务化改造更多的是从业务架构的角度出发,目的是将业务做更细粒度的功能拆分,使业务逻辑更加清晰、边界更加清楚且易于维护;服务化的另一个好处是收敛业务逻辑,通过接口标准化提供统一的访问方式。
分布式化更多的是从系统架构层面的角度出发,更多的是看访问请求路径,即一个请求必须先访问什么再访问什么一次访问要经过哪些步骤才能最终有结果等。因此,这两个是不同层面的工作。
3、分布式配置框架
分布式配置框架可以说是其他分布式框架的基础,因为在分布式系统中要做到所有机器节点都完全对等几乎是不可能的,必然有某些机器或集群存在某些差异,单同时又要保证程序代码是一份,所以解决这些差异的唯一办法就是差异化配置——配置框架就承担着这些个性化的定制功能。
分布式配置框架一般有一下两种管理方式:
拉取模式和推送模式。
一般而言,如果对配置下发延时率比较敏感而且Client数据不是太大(千级别)时,推荐推送模式;而当Client数据在万级别以上时推荐使用拉取模式。
4、分布式RPC框架
服务注册
服务发现
服务调度和负载均衡
统一的SDK封装:服务框架需要提供一个统一的客户端和服务端的标准接口规范,这样可以减少业务开发的重复工作量。例如SDK会统一封装通信协议、失败重试以及封装一些隐式参数传递(trace信息)。
Java通过提供一个统一的jar包,封装了服务发布和调用的接口,业务层只需要做些简单的配置就能方便调用服务。
5、分布式消息框架
实时消息
开源的RocketMQ、Kafka等
异步解耦
可以分开调用者和被调用者的处理逻辑,降低系统耦合,解决处理员之间的差异、数据结构之间的差异以及生产消费和消费者的速度差异。
主要保证两点
最终的一致性:一致性要求不能丢消息,保证消费最终可达,如果最终不可达要反馈给发送方。
多消费端
一个消息是被多个订阅者消费是典型的一种应用场景,多消费端非常适合用在单一事情触发的场景中。
典型问题:
确认消息会否被消费(需要增加消费确认标识)
消息队列需要有容错能力(当某个消息失败后,可以恢复重新投递消息)
延时消息
典型的应用场景是比如预订一张电影票的订单产生后,用户在15分钟后仍然没有付款,那么系统会要求在15分钟后取消该订单,释放座位。
6、分布式数据层
主要解决数据的分库分表、主备切换以及读写分离等问题。
读写分离要注意读写一致性的问题。
7、分布式文件系统
当前开源的分布式文件系统很多,像开源的TFS、FastDFS、GFS等。它们主要解决的是数据的高可用性和高性能问题。
8、应用的服务化改造
应用分层设计
应用分层设计很有必要。例如最起码要对数据库的访问统一抽象出来形成数据层,而不是直接在代码里面写SQL。
通常从垂直方向划分应用,分成服务层、业务逻辑层和数据层,每一层尽量做到解耦:上层依赖下层,而下层不要反向依赖上层。
应用分层最核心的目的是每个层都会封装一些信息、完成一些特定的功能需求,层与层之间通过接口交互,而且交互的数据是清晰和固定的,做到隔离和交互。可以从以下两个方向判断分层是否合理。
第一,如果我要增加一些新需求或者修改某些需求时,是否能清楚地知道要到哪层去完成,换句话说,这些分层的职责是否清晰。
第二,如果每个层对我的接口不变,那么每个层内部的修改是否会导致其他层也发生修改,即每个层是否做到了收敛。
微服务化
微服务化,是从水平划分的角度尽量把服务分得更细,每个业务只负责一个功能单元,这样可以把这些微服务组合成更大的功能模块。也就是有目的地拆小应用,形成单一职责从而提升系统可维护性、扩展性和开发效率。
9、分布式化遇到的典型问题
集群管理
例如Zookeeper的Leader选举
共享锁
通过使用Zookeeper实现
队列管理
两种类型队列:同步队列和FIFO方式进行入队和出队操作
通过使用Zookeeper实现
10、分布式消息通道服务的设计
这个没有接触过。
例如:打车App每天要上传大量的位置信息。
11、典型的分布式集群设计思路
当前的分布式集群管理中通常由两种设计思路:一种是Master/Slaver模式;一种是无对等的设计思路。
12、总结
从刚开始的单应用单层级的结构转换成多应用多层级的分布式应用需要解决前面我们提高的众多问题,而最核心的是要解决以下问题:
第一,纵向业务逻辑的分层拆分,要方便不同工种的程序开发人员的协作。例如前端和后端开发人员的协作效率。
第二,横向不同业务系统的拆分,例如商品和会员系统独立。
第三,系统的横向和纵向的拆分必须首先解决好系统之间的连接问题,而这些系统之间的如何连接就是分布式系统必须解决的问题。