一、架构演进
1、单体架构:
在软件设计的时候经常提到和使用经典的3层模型,即表现层,业务逻辑层,数据访问层。虽然在软件设计中划分了3层模型,但是对业务场景没有划分,一个典型的单体架构就是将所有的业务场景的表现层,业务逻辑层,数据访问层放在一个工程中最终经过编译,打包,部署在一台服务器上。此时服务架构如图
优点:容易开发、部署和测试,
缺点:系统耦合性高、技术选型单一、开发效率低下
2、微服务架构:
1.通过服务实现组件化:开发者不再需要协调其它服务部署对本服务的影响。 2.按业务能力来划分服务和开发团队:开发者可以自由选择开发技术,提供 API 服务 3.去中心化:每个微服务有自己私有的数据库持久化业务数据,每个微服务只能访问自己的数据库,而不能访问其它服务的数据库 某些业务场景下,需要在一个事务中更新多个数据库。这种情况也不能直接访问其它微服务的数据库,而是通过对于微服务进行操作。 数据的去中心化,进一步降低了微服务之间的耦合度,不同服务可以采用不同的数据库技术(SQL、NoSQL等)。在复杂的业务场景下,如果包含多个微服务,通常在客户端或者中间层(网关)处理。 4.基础设施自动化(devops、自动化部署):的Java EE部署架构,通过展现层打包WARs,业务层划分到JARs最后部署为EAR一个大包,而微服务则打开了这个黑盒子,把应用拆分成为一个一个的单个服务,应用Docker技术,不依赖任何服务器和数据模型,是一个全栈应用,可以通过自动化方式独立部署,每个服务运行在自己的进程中,通过轻量的通讯机制联系,经常是基于HTTP资源API,这些服务基于业务能力构建,能实现集中化管理
二、分布式系统
名词概念:
分布式和集群
分布式和集群在通常情况下不做严格区分,正如同并发和并行一样,应用情况下很少会去考究它的区别,许多大公司面试也直接问分布式集群怎样怎样,一般都拿等同来讲了。在这里只在概念上做一下区别,使大家更合理的去理解,没有对错之分。
分布式:一个电商系统,用户模块部署在server1, 订单模块部署在server2, 促销模块部署在server3, 商品模块部署在server4,他们之间通过远程rpc实现服务调用,这就叫分布式。强调的是不同功能模块,单独部署在不同的server上,所有server加起来是一个完整的系统。
集群:更多强调的是灾备,一个电商系统,完整的部署在server1上一个,完成的部署在server2上一个,server1宕机后,server2仍然可以正常提供请求服务,这叫集群。同样对于某一功能模块,比如用户模块部署在server1上,同样部署在server2上,也叫做集群。分布式系统的每个功能模块节点,都可以用多机做成集群。
抽象问题具体化:拿做菜示例,假如一个厨师做菜要经历切菜,炒菜两个功能,饭店为了提高速度招了两个厨师,每个厨师的工作一样,都是切菜,炒菜,这是集群。还有另一种方法提高效率,饭店招了一个切菜师傅,配合厨师,厨师不管切菜,只管炒菜了,和切菜师傅共同配合把菜做好,这叫分布式。
Nginx作用是反向代理和负载均衡。
反向代理:是指请求真实是到server1的,但是系统中为了统一或者做比如单点登录,会在server2服务器上安装一个nginx,里面配置到server1的反向代理,那么之后请求url就可以写server2的地址,发出后到server2, server2会转发到server1上,类似一种代理的模式。
负载均衡:是指如果一个系统的请求很多,我们可以把请求转发到不同的服务器上,用来分流。就类似于接了一个水管放水,水流量很大时候,水压大很可能会让一个水管爆炸,这时候接三个水管,就没问题了(这三个水管就是一个集群)。类似的在nginx服务器中配了3个tomcat服务器,每个tomcat服务器上都部署了整个系统,那么当请求数大的时候,可以分发到不同的tomcat。(其实这里每个tomcat上部署同一个功能模块也叫集群)
Java在分布式下的通信
RPC(远程过程调用):对于分布式系统来讲,tomcat1上部署了用户模块,tomcat2上部署了订单模块,当用户下单时,请求到tomcat2,这时候可能要判断这个用户是否是vip,或者是否有优惠券,这些方法是在tomcat1用户模块上的,那么tomcat2调用tomcat1的服务获取这些信息,就叫rpc调用。
常见的rpc框架:轻量级的hessian, 阿里dubbo(当当dubbox), 新浪Motan, apache的Thrift,google的grpc, 百度的brpc, 腾讯的tars。
rpc调用底层涉及到对象的序列化,反序列化,http/tcp传输,网络异步传输netty。
消息中间件(MQ)
mq消息中间件在分布式系统中的作用有很多,但是经常用到的还是异步解耦。
比如天猫下单流程,当用户支付后,后台接口执行的操作可能包括:1 验签,2 支付密码校验,3 扣库存,4 用户积分增加等等操作,其实我们希望的是2操作执行成功后立即给用户结果提示,而不是等到后续各个操作完成后才去提示,因为后续的操作往往大部分是rpc调用,方法执行时间相对较长。另外对于下单支付这个操作,3和4是后续业务的需要,在设计上不能和下单支付本身出现强耦合度。所以这里我们可以引入mq解决,也就是说1和2执行完成后,生产者只需要通知下3和4,把后续的操作扔给消息队列,立即返回。这里的mq起到的作用一个是异步调用,一个是解耦。
NoSQL(非关系型数据库)
NoSQL是所有非关系型数据库的统称,在分布式系统中用到很多,主要用来提高QPS(query per second)。
Redis: 我们讲缓存,或者内存数据库,小巧强大,什么数据适合放在redis也就是缓存中,一个是经常查询的,需要频繁磁盘io的,例如有个快件系统,有个需求是当快件状态为异常时候,需要发送邮件提醒给系统管理员。接口入参是快件id,通常做法我们需要拿到id,去数据库查状态,然后发送,但是快件基数很大时候每天的问题件也可能会很多,接口调用频繁时候就需要改进做法,这时我们可以把快件状态信息放在redis里面,key是快件id, value是快进状态,每次进入接口时候直接redis里面取status就可以,速度很快。另一个是查询数据缓慢的,可以放在缓存中。
MongoDB: 可称为分布式文件数据库,可用来存储海量数据,它是NoSQL里面最像关系型数据库的,它的数据的存储形式可以就理解为json格式。之前曾经两次用到过mongoDB,一次是系统里面有个实时监控设备电流电压的功能,硬件设备实时会把数据同步到数据库里面,我们系统2-3s需要去拉次列表。另一个系统是一个轻型的行业IM工具,每天会有很大的聊天数据存储,我们直接用了mongoDB存储,后来系统相当稳定,从来没有出现过性能瓶颈。
CAP原理
CAP 原则又称 CAP 定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则表明,这三个要素最多只能同时实现两点,不可能三者兼顾。
什么是分区?
一个分布式系统里面,节点组成的网络在正常状态下应该是连通的,也就是所有节点出于同一分区中。然而软件、硬件或者网络等故障不可避免,使得分布式系统中的节点之间不连通了,整个网络就分成了几块区域。当系统数据无法在不同分区间传输时,系统就是不可用的,这样的系统就是分区不容忍的系统。
另外,在分布式系统中,分区容忍性是必须要具备的特性,是不可放弃的,分布式系统中,要么选择 CP,要么选择 AP,没有 CA 这种选择。
BASE原理
BASE原理是CAP原理的延伸,相对于CAP,BASE原理的实现相对轻松,能够实现许多CAP实现不了的业务,
基本可用(Basically Available):
基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。 软状态(Soft State):
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。MySQL Replication 的异步复制也是一种体现。 最终一致性(Eventual Consistency):
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。
三、SpringCloud
Spring Cloud 优缺点
优点:集大成者,Spring Cloud 包含了微服务架构的方方面面。 约定优于配置,基于注解,没有配置文件。 轻量级组件,Spring Cloud 整合的组件大多比较轻量级,且都是各自领域的佼佼者。 开发简便,Spring Cloud 对各个组件进行了大量的封装,从而简化了开发。 开发灵活,Spring Cloud 的组件都是解耦的,开发人员可以灵活按需选择组件。 缺点:项目结构复杂,每一个组件或者每一个服务都需要创建一个项目。 部署门槛高,项目部署需要配合 Docker 等容器技术进行集群部署,而要想深入了解 Docker,学习成本高。 Spring Cloud 的优势是显而易见的。因此对于想研究微服务架构的同学来说,学习 Spring Cloud 是一个不错的选择。