是什么
集群是个物理形态,分布式是个工作方式。
分布式与集群的关系
分布式中的每一个节点都可以做集群,而集群并不一定就是分布式的,因为具体实现目的不同。
对于分布式来讲是将一个业务分拆多成个不同功能模块部署在不同的服务器上,不同模块相互配合调用完成整体业务。而对于集群来讲,则是把某个拆分的模块部署在多个服务器上。以负载均衡的方式响应请求。
分布式与集群的个各自优势
分布式与集群目的都是提高效率,但各有侧重。
分布式是以缩短单个任务的执行时间来提升效率,而集群则是通过提高单位时间内执行的任务数来提升效率。一个是保质,一个是保量。
比如一个整体请求需要3个模块协作完成响应,每个模块需要运行一个小时且三者并无前后依赖关系,对于单模块系统来讲可能花费3个小时,分布式完成响应则只需需要花费一个小时。
集群的保量可以理解为,3个请求共同调用一个模块,如果每个模块响应需要花费1个小时,那么单模块需要花费3个小时才可以完成全部响应,如果采用集群的方式则同样只需花费1个小时。
总结来说
好的设计应该是分布式和集群的结合,先分布式再集群,具体实现就是拆分整体为模块,然后针对每个子模块进行集群部署,如果一个模块如果出了问题会有集群中的其它模块进行响应,从而保证了整个系统运行不会受到影响。
提到分布式就不得不提到微服务,微服务的概念与分布式比较相似,但又不完全一样。
微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。
简单的说就是一个微服务就是一个实现某个业务小Module
。
使用分布式的目的很简单就是扩展增强整体网站的用户容纳能力,利用更多的机器,响应更多的请求,处理更多的数据。
首先需要明确的是,只有单个节点提升性价比过低时,我们才需要考虑分布式系统。因为,分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。
无论是微服务还是SOA,都面临着服务间的远程调用。远程调用方式主要有两种分别是HTTP和RPC
HTTP其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用HTTP协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。现在热门的Rest风格,就可以通过HTTP协议来实现。
RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。比如说两台服务器A,B,一个应用部署在A服务器上,A服务器想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。而RPC就是完成两台服务器接口的通讯工作。
执行流程
RPC两个核心模块:通讯,序列化。
关于RPC和HTTP参看:
关于SpringCloud和Dubbo如何选择参看:
Spring提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便。
RestTemplate并没有限定Http的客户端类型,而是进行了抽象,目前常用的3种都有支持:
Spring Cloud
是一个微服务框架的规范,注意,只是规范,他不是任何具体的框架,而是一个基于SpringBoot
的大的容器,它将市面上较好的微服务框架集成进来,从而简化了开发者的代码量。
API gateway
API Gateway(APIGW / API 网关),顾名思义,是出现在系统边界上的一个面向 API 的、串行集中式的强管控服务,这里的边界是企业 IT 系统的边界,可以理解为企业级应用防火墙,主要起到隔离外部访问与内部系统的作用。
Spring Boot Apps
基于
SpringBoot
写的的系统功能模块
Metrics Store
度量存储
Databases
连接数据库
Message Broker
消息中间者,负责翻译转换发送者和接收者之间消息协议。
Config Service
在
springboot
项目中允许通过在启动器上使用@EnableConfigServer
注解来使配置文件内的配置生效
Service Resgister
服务注册与发现,比如
zookeeper
用来管理模块内的API
Circuit breaker Dashboard
断路器仪盘表,分布式系统可能不可靠。请求可能会遇到超时或完全失败。断路器可以帮助缓解这些问题,spring cloud断路器为您提供了三种流行的选择:Resilience4J、Sentinel或Hystrix。
Spring Cloud Sleuth
Spring Cloud Sleuth实现了一种分布式的服务链路跟踪解决方案,通过使用Sleuth可以让我们快速定位某个服务的问题。简单来说,Sleuth相当于调用链监控工具的客户端,集成在各个微服务上,负责产生调用链监控数据。Spring Cloud Sleuth只负责产生监控数据,通过日志的方式展示出来,并没有提供可视化的UI界面。
详解:分布式链路追踪之Spring Cloud Sleuth+Zipkin最全教程! - bucaichenmou - 博客园 (cnblogs.com)
Spring Cloud 解决的问题
Spring Cloud技术栈
企业微服务架构
无业务基础服务相当与工具类,业务型基础服务则相当与每个部门,那么每个部门则都可以调用无业务基础服务的功能模块而不用自己重写。
微服务解决的核心问题
微服务架构
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
传统分布式架构需要对外暴露自己的地址,而调用者需要记录提供者的地址。如果地址出现变更,还需要及时更新。服务少没有关系,但是在日益复杂的互联网环境,服务多起来,此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦,这与DevOps的思想背道而驰。
简单的可以理解为:用户,滴滴,私家车,三者的关系。
服务治理主要的点是在服务的自动注册、发现、状态监控。
常用的服务治理框架:
在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自己服务器的信息 比 服务地址通讯地址等以别名方式注册到注册中心上。
另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,让后在实现本地RPC调用远程。
框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心存放服务地址相关信息(接口地址)
CAP
CPA理论:一个分布式系统不可能同时满足CAP。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡,最多只能同时较好的满足两个。
因此,根据CAP原理将NoSQL
数据库分成三大类:
分析:
如果 C(一致性)是第一需求,那么A(可用性)的性能就不能保证。因为在数据同步保持请求结果相同的时候,或消耗时间,这时可用性就会降低,在数据同步的时候,不能保证能正常接收请求。
如果 A (可用性)是第一需求,那么 C (一致性) 就不能保证。只要有一个服务在,就能正常接受请求,但是对与返回结果便不能保证,原因是,在分布式部署的时候,数据一致的过程不可能想切线路那么快。
在实际环境中,我们往往对同一个服务进行集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?
一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。
LB负载均衡(Load Balance)是什么?
简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA (高可用)。
常用的负载均衡器有:
Ribbon本地负载均衡客户端VS Nginx服务端负载均衡区别
nginx是客户端所有请求统一交给nginx,由nginx进行实现负载均衡请求转发,属于服务器端负载均衡。即请求有nginx服务器端进行转发。
Ribbon是从注册中心服务器端上获取服务注册信息列表,缓存到本地,然后在本地实现负载均衡策略。即在客户端实现负载均衡。
Ribbon——负载均衡 + RestTemplate调用。
大型复杂的分布式系统中,高可用相关的技术架构非常重要。高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用的服务,从而足以应对分布式系统环境中的各种各样的问题,避免整个分布式系统被某个服务的故障给拖垮。比如:
要解决这些棘手的分布式系统可用性问题,就涉及到了高可用分布式系统中的很多重要的技术,包括:资源隔离、限流与过载保护、熔断、优雅降级、容错、超时控制、监控运维等。
微服务中,服务间调用关系错综复杂,一个请求可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路
如图,一次业务请求,需要调用A、P、H、I四个服务,这四个服务又可能调用其它服务。
如果此时,某个服务出现异常:
例如微服务I发生异常,请求阻塞,用户不会得到响应,则Tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞:
服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。
服务降级是指在在请求面临压力时优先保证核心服务,而非核心服务不可用或弱可用。
用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息)。
服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。
熔断机制目的为了保护服务,在高并发的情况下,如果请求达到一定极限(可以自己设置阔值)如果流量超出了设置阈值,让后直接拒绝访问,保护当前服务。使用服务降级方式返回一个友好提示,服务熔断和服务降级一起使用。用个比较形象的比喻服务熔断机制就像家庭用电的短路保护器。
因为默认情况下,只有一个线程池会维护所有的服务接口,如果大量的请求访问同一个接口,达到Tomcat 线程池默认极限,可能会导致其他服务无法访问。
解决服务雪崩效应:使用服务隔离机制(线程池方式和信号量),使用线程池方式实现
隔离的原理: 相当于每个接口(服务)都有自己独立的线程池,因为每个线程池互不影响,这样的话就可以解决服务雪崩效应。可搭配服务降级使用。
每个服务接口,都有自己独立的线程池,每个线程池互不影响。
为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间。
用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理。
使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,当请求进来时先判断计数器的数值,若超过设置的最大线程个数则拒绝该请求,若不超过则通行,这时候计数器+1,请求返回成功后计数器-1。
服务限流就是对接口访问进行限制,常用服务限流算法令牌桶、漏桶。计数器也可以进行粗暴限流实现。
在前面了解了Ribbon的负载均衡策略,可以使用RestTemplate
大大简化远程调用时的代码:
String user = this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
如果止步于此,可能以后需要编写类似的大量重复代码,格式基本相同,无非参数不一样。有没有更优雅的方式,来对这些代码再次优化呢?
可以使用如下框架:
Feign 和 Openfeign 的区别
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。
Feign 最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由社区进行维护,更名为 Openfeign。
OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequesMapping
等等。OpenFeign的@Feignclient
可以解析SpringMVC的@RequestMapping
注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
关于Feign 和 Openfeign可参看:花一个周末,掌握 SpringCloud OpenFeign 核心原理
微服务下,一个系统被拆分为多个服务,但是像安全认证,流量控制,日志,监控等功能是每个服务都需要的,没有网关的话,我们就需要在每个服务中单独实现,这使得我们做了很多重复的事情并且没有一个全局的视图来统一管理这些功能。
网关为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
一般情况下,网关一般都会提供请求转发、安全认证(身份/权限认证)、流量控制、负载均衡、容灾、日志、监控这些功能。但权限校验、流量控制、请求转发这些都可以通过过滤器实现。最终网关最主要做了一件事情:请求过滤。
常用的网关技术:
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行。(大量的配置文件)
当一个系统中的配置文件发生改变的时候,我们需要重新启动该服务,才能使得新的配置文件生效,所以我们需要实现微服务中的所有系统的配置文件的统一管理,而且还可以实现当配置文件发生变化的时候,系统会自动更新获取新的配置。(集中式的、动态的配置管理设施)
在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
简而言之,是当配置文件发生变更时,需要周知所有订阅的服务器,配置信息已经变更了。
在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每一个前段请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败。
分布式追踪正在被越来越多的应用所采用。分布式追踪可以通过对微服务调用链的跟踪,构建一个从服务请求开始到各个微服务交互的全部调用过程的视图。用户可以从中了解到诸如应用调用的时延,网络调用(HTTP,RPC)的生命周期,系统的性能瓶颈等等信息。
参看:一文读懂微服务监控之分布式追踪
Spring Cloud Stream
为一些供应商的消息中间件产品提供了个性化的自动化配置实现,并引入了发布-订阅、消费组、分区这三个核心概念。通过使用 Spring Cloud Stream,可以有效简化开发人员对消息中间件的使用复杂度,让系统开发人员可以有更多的精力关注于核心业务逻辑的处理。但是目前 Spring Cloud Stream 只支持 RabbitMQ 和 Kafka 的自动化配置。
Spring Cloud NetFlix,一站式解决方案,但已停止维护
技术梗概
服务注册与发现——Eureka
服务网关——Zuul
服务调用——Feign
服务降级——Hystrix
服务配置——Config
服务总线——Bus
Spring Cloud Netflix项目进入维护模式 - 时间朋友 - 博客园 (cnblogs.com)
半自动需要整合别人的框架
由 Alibaba 开源的一款一站式分布式框架
服务注册中心: Alibaba Nacos
服务配置中心: Alibaba Nacos
消息总线/事件驱动: Alibaba Nacos 整合了RocketMQ
服务调用:Apache Dubbo RPC
服务限流与降级:Alibaba Sentinel,整合ribbon+openFeign
分布式事务:Seata
链路追踪:Sleuth +Zinkin(自配)
服务网关:SpringCloud GateWay