在解释原理之前,先看最经典的业务场景,比如开发电商网站,实现支付订单的功能,流程如下:
- 创建一个订单之后,如果用户立刻支付了这个订单,我们需要将订单状态更新为“已支付”
- 扣除相应的商品库存
- 通知仓储中心发货
- 为用户的购物增加相应的积分
以上,微服务的应用场景和核心竞争力:
- 减少耦合:每个微服务都专注于单一功能,并通过定义良好的界面清楚地表达服务边界。由于体积小、复杂性低,小型开发团队可以完全控制每个微服务,易于保持高可维护性和开发效率。
- 独立部署:由于微服务具有独立的运行过程,每个微服务也可以独立部署。当微服务发生变化时,无需编译和部署整个应用程序。由微服务组成的应用程序相当于一系列平行发布过程,使发布更有效率,降低生产环境风险,最终缩短应用程序交付周期。
- 灵活的选择:在微服务架构下,技术选择是分散的。每个团队都可以根据自己的服务需求和行业发展的现状自由选择最合适的技术栈。由于每个微服务都相对简单,升级技术栈的风险较低,甚至完全重建微服务也是可行的。
- 容错机制:当一个构建出现故障时,在传统的单一过程架构下,故障很可能在过程中扩散,形成整体不可用的应用程序。在微服务架构下,故障将被孤立在单个服务中。如果设计良好,其他服务可以通过重新测试和平稳退化来实现应用水平的容错。
- 灵活扩展:单体架构应用程序也可以实现水平扩展,即将整个应用程序完全复制到不同的节点。当不同的应用组件在扩展需求上存在差异时,微服务架构反映了其灵活性,因为每个服务都可以根据实际需要独立扩展。
:
- 背景分析:Dubbo,是阿里巴巴服务治理的核心框架,广泛应用于中国互联网公司;Spring Cloud是知名的Spring家族产品。阿里巴巴是一个商业公司,虽然也开源了很多的顶级的项目,但从整体战略上来讲,仍然是服务于自身的业务为主。Spring专注于企业级开源框架的研发,广泛应用于中国和世界。开发通用、开源、稳定的开源框架是他们的主营业务。
- 活动对比:Dubbo是一个非常优秀的服务治理框架,在服务治理、灰度发布、流量分配等方面做得比较Spring Cloud幸运的是,除了当当网,它还增加了rest除了支持,已经两年多没有更新了。使用过程中出现问题,提交GitHub的Issue很少有回复。相反Spring Cloud自发展以来,仍在快速发展,从GitHub可以看到提交代码的频率和发布版本的时间间隔。Spring Cloud即将发布2.0版,后期会更加完善稳定。
- 平台架构:Dubbo框架只关注服务之间的治理。如果我们需要使用配置中心和分布式跟踪,我们需要集成这些内容,以便实际使用Dubbo难度会增加。Spring Cloud服务治理的服务治理的方方面面,更多Spring Boot这位将军的支持非常方便和简单。
- 技术前景:Dubbo中小企业也从中受益匪浅。经过这么多年的发展,互联网产业也涌现出了更先进的技术和理念,Dubbo有点可惜。Spring 推出Spring Boot/Cloud也是因为很多原因。Spring随着最初的轻量级框架的不断发展,配置文件越来越混乱,逐渐偏离了最初的概念。随着这么多年的发展,微服务、分布式链路跟踪等新技术理念的出现,Spring迫切需要一个框架来改善以前的开发模式,因此会出现Spring Boot/Cloud项目,我们现在来访Spring会发现官网Spring Boot和Spring Cloud前两个已经放在首页最突出的三个项目中,可见Spring重视这两个框架。Dubbo实现如下:
:
原则:负责服务注册和发现,即微服务名称注册Eureka,就可以通过Eureka在不修改服务调用的配置文件的情况下,找到微服务。
分析:Spring Cloud封装了Netflix公司开发的Eureka模块用于实现服务的注册和发现c-s设计架构,Eureka Server作为服务注册功能的服务器,他是服务注册中心。使用系统的其他微服务Eureka客户端连接Eureka Server并维持心跳。通过这种方式,系统的维护人员可以通过Eureka Server监控系统中各微服务是否正常运行。Spring Cloud其他一些模块(如Zuul)就可以通过Eureka Server发现系统中的其他微服务,并执行相关逻辑。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中注册, 这样Eureka Server所有可用服务节点的信息都将存储在服务注册表中,服务节点的信息可以在界面中直观地看到。
Eureka Client是一个Java客户端, 用于简化Eureka Server客户端也有内置的交互, 使用轮询(round-robin)负载算法的负载平衡器。启动应用程序后,向前移动Eureka Server发送心跳(默认周期为30秒)证明当前服务是可用的。如果Eureka Server一定时间(默认90秒)未收到客户心跳,Eureka Server该服务节点将从服务注册表中删除。
如果超过85%的节点在15分钟内没有正常的心跳,那么Eureka认为客户端和注册中心有网络故障,此时会出现以下情况:
- Eureka由于长期没有收到心跳,应过期的服务不再从注册列表中删除
- Eureka新服务的注册和查询请求仍然可以接受,但不会同步到其他节点(即确保当前节点仍然可用)
- 当网络稳定时,当前实例的新注册信息将同步到其他节点
因此, Eureka它可以很好地处理一些节点因网络故障而失去联系的情况,而不是像ZooKeeper使整个注册服务瘫痪。
着名的CAP理论指出,分布式系统不能同时满足C(一致性),A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C权衡两者。
在向注册中心查询服务列表时,我们可以容忍注册中心在几分钟前返回注册信息,但不能直接接受服务down掉不可用。也就是说,服务注册功能对可用性的要求高于一致性。但是ZooKeeper当这种情况发生时,Master当节点因网络故障与其他节点失去联系时,剩余节点将重新进行leader选举。问题是,选举leader时间太长,30 ~ 120s,整个选举期间ZooKeeper集群不可用,导致选举期间注册服务瘫痪。在云部署的环境中,由于网络问题ZooKeeper集群失去Master节点很有可能发生。虽然服务可以最终恢复,但由于选举时间长,长期注册是不可容忍的。
Eurek优先考虑设计中的可用性。Eureka每个节点都是平等的,几个节点不会影响正常节点的工作,剩下的节点仍然可以提供注册和查询服务。而Eureka客户端在某个方向Eureka如果注册或连接失败,只要有一个,它将自动切换到其他节点Eureka仍然可以保证注册服务的可用性(保证可用性),但发现的信息可能不是最新的(不保证强一致性)。
除此之外,Eureka还有一种自我保护机制,见上。
Eureka它可以很好地处理一些节点因网络故障而失去联系的情况,而不是像ZooKeeper使整个注册服务瘫痪。
Eureka作为一个简单的服务注册中心,它比ZooKeeper由于注册服务更重要的是可用性,我们可以接受短期内无法达到一致性的情况。
在微服务架构中,业务将分为独立的服务,基于服务和服务的通信HTTP RESTful的。Spring Cloud服务调用有两种方式,一种是Ribbon RestTemplate,另一种是Feign。
基于Netflix Ribbon一套利用轮询策略实现客户端负载均衡的工具。
客户端负载平衡:负载平衡Zuul当网关向服务应用程序发送请求时,如果一个服务启动多个例子,它将通过Ribbon通过一定的负载均衡策略发送给服务实例。Spring Cloud中的Ribbon,在发送请求之前,客户端将有一个服务器地址列表,通过负载平衡算法(如简单轮询、随机连接等)选择
- 负载均衡:用于将工作负载分布多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。
- 使用负载均衡带来的好处很明显:当集群里的1台或者多台服务器down的时候,剩余的没有down的服务器可以保证服务的继续使用;将访问压力分配到各个服务器,不会由于某一高峰时刻导致系统cpu急剧上升。
- 负载均衡有好几种实现策略,常见的有:随机(Random),轮询(RoundRobin),一致性哈希(ConsistentHash),哈希(Hash),加权(Weighted)
- Ribbon的默认策略是轮询
传统情况下在Java代码里访问RESTful服务,一般使用Apache的HttpClient,不过此种方法使用起来太过繁琐。Spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。
Feign是一个声明式http客户端。使用Feign能让编写http客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解,避免了调用目标微服务时,需要不断的解析/封装json数据的繁琐。Spring Cloud中Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。
在使用Ribbon+ RestTemplate时,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。利用RestTemplate对http请求的封装处理,形成了-套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。
在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可), 即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量。
Ribbon通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,Feign是一个声明式的Web服务客户端, 使得编写Web服务客户端变得非常容易,只需要创建一个接口, 然后在上面添加注解,像调用本地方法一样调用它就可以,而感觉不到是调用远程方法。SpringCloud中Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。
Nginx是客户端所有请求统一交给Nginx,由Nginx进行实现负载均衡请求转发,属于服务器端负载均衡。既请求由Nginx服务器端进行转发。客户端负载均衡Ribbon,Ribbon是从Eureka注册中心服务器端上获取服务注册信息列表,缓存到本地,然后在本地实现轮询负载均衡策略。既在客户端实现负载均衡。
Nginx适合于服务器端实现负载均衡,比如:Tomcat,Ribbon适合与在微服务中RPC远程调用实现本地服务负载均衡,比如:Dubbo、Spring Cloud中都是采用本地负载均衡。
Zuul
假如当前有十几个微服务服务,订单,商品,用户等等,显然是客户端不需要和每个服务逐一打交道,这就需要有一个统一入口,它就是服务网关。API网关所有的客户端请求通过这个网关访问后台的服务。他可以使用一定的路由配置来判断某一个URL由哪个服务来处理。并从Eureka获取注册的服务来转发请求。
Zuul包含了对请求的路由和过滤两个最主要的功能,是各种服务的统一入口,同时还会用来提供监控、授权、安全、调度等等。
路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。
过滤器功能:则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
Zuul和Eureka进行整合:将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
注意:Zuul服务最终还是会注册进Eureka,提供代理+路由+过滤三大功能。
Zuul的核心是一系列的filters,其作用可以类比Servlet框架的Filter,或者AOP。
过滤器之间没有直接进行通信,而是通过Request Context(上下文)进行数据传递。
Zuul的过滤器是由Groovy写成,这些过滤器文件被放在Zuul Server上的特定目录下面,Zuul会定期轮询这些目录,修改过的过滤器会动态的加载到Zuul Server中以便过滤请求使用。
Zuul负载均衡:Zuul拦截对应的API前缀请求做转发,转发到对应的serverId上,在Eureka服务上同一个serverId可以对应多个服务,也就是说用同一个服务节点不同的端口注册两个实例,但是serverId是一样Zuul做转发的时候会结合eureka-server起到负载均衡的效果。
过滤器的种类:
- PRE(前置):这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现鉴权、限流、参数校验调整等。
- ROUTING(路由):这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST(后置):这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端、日志等。
- ERROR(错误):在其他阶段发生错误时执行该过滤器。
Zuul虽然在性能上和Nginx没法比,但它也有它的优点。Zuul提供了认证鉴权,动态路由,监控,弹性,安全,负载均衡等边缘服务,在团队规模不大的情况下,没有专门负责路由开发时,使用Zuul当网关是一个快速上手的好方案。
Nginx和Zuul是可以配合使用的,发挥各自的优点,使用Nginx作为负载均衡实现高并发的请求转发,Zuul用作网关。
Zuul支持Ribbon和Hystrix,也能够实现客户端的负载均衡。我们的Feign不也是实现客户端的负载均衡和Hystrix的吗?既然Zuul已经能够实现了,那我们的Feign还有必要吗?
可以这样理解:
Zuul是对外暴露的唯一接口相当于路由的是controller的请求,而Ribbonhe和Fegin路由了service的请求。
Zuul做最外层请求的负载均衡,而Ribbon和Fegin做的是系统内部各个微服务的service的调用的负载均衡。
Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避兔的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。Hystrix的出现就是为了解决雪崩效应。
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的”雪崩效应”。
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当删除链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。
我们只需要在服务接口上添加Hystrix标签,就可以实现对这个接口的监控和断路器功能。
Hystrix Dashboard监控面板,提供了一个界面,可以监控各个服务上的服务调用所消耗的时间等。
使用Hystrix监控,我们需要打开每一个服务实例的监控信息来查看。而Turbine可以帮助我们把所有的服务实例的监控信息聚合到一个地方统查看。这样就不需要挨个打开一个个的页面一个个查看。
签名机制,为防止接口数据篡改和重复调用,增加接口参数校验机制,sig签名算法为MD5(appKey+appSecret+timestamp),appKey是分配给客户端的ID,appSecret是分配给客户端的密钥,timestamp为unix时间戳,请求的URL有效时间为15分钟。
Token机制,用户在登录之后会返回一个access_ token,客户端在访问需要登录之后才能访问的资源,需要在在Authorization头部使用Bearer模式新增token,如head(“Authorization”,” Bearer token”)。
- 资源隔离(线程池隔离和信号量隔离)机制:限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其它服务调用。
- 限流机制:限流机制主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。
- 熔断机制:当失败率达到阀值自动触发降级(如因网络故障、超时造成的失败率真高),熔断器触发的快速失败会进行快速恢复。
- 降级机制:超时降级、资源不足时(线程或信号量)降级、运行异常降级等,降级后可以配合降级接口返回托底数据。
- 缓存支持:提供了请求缓存、请求合并实现。
- 通过近实时的统计/监控/报警功能,来提高故障发现的速度。
- 通过近实时的属性和配置热修改功能,来提高故障处理和恢复的速度。
Config
Spring Cloud Config是一个解决分布式系统的配置管理方案。微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统 中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、 动态的配置管理设施是必不可少的。Spring Cloud提供了ConfigServer来解决这个问题,我们每一个微服务自 己带着一个application.yml 上百个配置文件的管理。
- 不方便维护,多人同时对配置文件进行修改,冲突不断,很难维护
- 配置内容安全和权限,主要是针对线上的配置来说,一般不对开发公开,只有运维有权限所以需要将配置文件隔离,不放到项目代码里
- 更新配置项目需要重启,每次更新配置文件都需要重启项目,很耗时。使用了配置中心后,即可实现配置实时更新congfig Server和Config Client结合Spring Cloud Bus实现配置自动刷新。
- 配置文件存储在远端Git(比如GitHub,Gitee等仓库),config-server从远端Git拉取配置文件,并保存到本地Git。
- 本地Git和config-server的交互是双向的,因为当远端Git无法访问时,会从本地Git获取配置文件。
- config-client(即各个微服务),从config-server拉取配置文件。
- Config Server:提供配置文件的存储、以接口的形式将配置文件的内容提供出去。
- Config Client:通过接口获取数据、并依据此数据初始化自己的应用。
总结如下
最后
小编精心为大家准备了一手资料
**点击这里免费领取**以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术
【附】架构书籍赠送
- BAT面试的20道高频数据库问题解析
- Java面试宝典
- Netty实战
- 算法
以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术
【附】架构书籍赠送
- BAT面试的20道高频数据库问题解析
- Java面试宝典
- Netty实战
- 算法
[外链图片转存中…(img-RnZzX2KW-1625222807548)]
[外链图片转存中…(img-lRRHna5H-1625222807549)]