参考视频:
https://www.bilibili.com/video/BV1jJ411S7xr?p=22
1、微服务优缺点
优点:
- 符合单一职责原则
- 每个服务足够内聚、足够小,能聚焦一个指定的业务功能
- 开发简单,开发效率高,一个服务可能值专注干一件事
- 微服务是松耦合的
- 能使用不同语言开发
- 易于和第三方集成,利用集成工具jenkins、hudson、bamboo
- 微服务只是业务逻辑的代码,不会和HTML、CSS混合
- 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一的数据库
缺点:
- 需要处理分布式系统的复杂性
- 多服务运维难度,随着服务的增加,运维压力增大
- 系统部署依赖
- 数据一致性
- 服务间通信成本
- 性能监控
2、微服务框架选型
- Spring Cloud NetFlix
通信方式:HTTP
服务注册与发现:Eureka
熔断机制:Hystrix - Apache Dubbo Zookeeper
- Spring Cloud Alibaba
微服务之间是如何独立通讯的?
RPC(Dubbo)、HTTP(SpringCloud)
3、什么是SpringCloud
基于SpringBoot的微服务解决方案,包括服务注册与发现、配置中心、全链路监控、服务网关、负载均衡、熔断器等组件,Spring Cloud提供了快速构建分布式系统的工具:配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话。
4、SpringBoot和SpringCloud谈谈对他们的理解
springboot专注于快速开发单个个体微服务,将服务打包成jar包发布到服务器上
springcloud专注于全局的微服务协调整理框架,将springboot开发的单个微服务整合并管理起来,为各个微服务之间提供:配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等服务。
5、传统互联网架构
用户访问网站:
- 访问CDN
- 负载均衡Lvs、Nginx
- 微服务集群(Tomcat服务器,与分布式文件系统打交道)【服务的消费者】
- 向注册中心获取服务
- 获取服务之前,服务提供者向注册中心注册服务
- 请求数据时先访问消息队列MQ,实现异步处理、流量削峰
- 访问数据库之前先访问缓存(Redis、Elastic、Search),如果数据没有再访问数据库
- mysql水平拆分读,竖直拆分写(主从复制、读写分离,主从之间保持数据一致性)
微服务架构:
6、SpringCloud和Dubbo有哪些区别?
- SpringCloud抛弃了Dubbo的RPC通信,采用HTTP的REST方式,虽然牺牲了服务调用的性能,但是比RPC更灵活,依赖只是依靠HTTP的链接,不存在代码级别的强依赖
- SpringCloud可以与Spring其他项目完美融合,具备更高的稳定性
- SpringCloud提供了微服务架构下的一站式解决方案,而Dubbo只是一款RPC框架
7、参考文档
- 中文API文档:https://www.springcloud.cc/spring-cloud-dalston.html
- SpringCloud中文网:https://www.springcloud.cc/
- https://www.springcloud.cc/spring-cloud-netflix.html
8、微服务技术栈
9、Eureka
(1)包含两个组件
- Eureka Server:提供服务注册服务,各节点启动后在Eureka Server中进行注册(类似于zookeeper)
- Eureka Client:java客户端,具备内置的使用轮询负载算法的负载均衡器,启动后会向Eureka Server发送心跳,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,则Eureka Server将会从服务注册表中把这个服务节点移除。
(2)三大角色
- Eureka Server:注册中心,提供服务注册与发现,类似于zookeeper
- Service Provider:将自身服务注册到Eureka中
- Service Consumer:服务消费者从Eureka中获取注册服务列表,找到消费服务
(3)自我保护机制
如果某时刻有个微服务不可用了,eureka不会马上清理该服务,依旧会对该微服务的信息进行保存。
通过在server端的配置文件中使用eureka.server.enable-self-preservation=false
可以关闭自我保护模式
默认情况下,EurekaServer在一定时间内(90s)没有接受到这个微服务的心跳,EurekaServer会注销该实例,当网络分区故障时,微服务本身是健康的,但是与Eureka之间无法正常通信,此时Eureka会通过自我保护机制解决这个问题(EurekaServer节点在短时间内失去过多客户端),保护服务注册表中的信息,不再删除服务注册表中数据。
(4)配置注册中心步骤:
①导入eureka依赖
②配置application.yml
hostname:服务端实例名称
defaultZone:注册中心的地址,主机名为上面的hostname,port为上面的server.port
③注册中心(server)主启动类中使用注解@EnableEurekaServer
(5)注册服务步骤:
①服务提供者添加依赖
②注册服务提供者到注册中心,编写配置eureka,目的service-url是eureka注册中心的地址
spring.application.name就是注册的服务的名称
③在服务提供者主启动类中添加注解@EnableEurekaClient启动自动注册
(6)集群配置(高可用)
- )开启多个Eureka Server(Server端需要在启动文件添加注解@EnableEurekaServer)
- )相互关联(在每个Eureka Server的配置文件中,在配置Eureka时在defaultZone中添加其他注册中心的地址)(这里将erueka7002.com在c盘的host文件中与localhost建立了映射关系)
- ) 服务向集群发布(在Eureka Client端的配置文件中,添加集群中所有节点的网址)
- )消费者利用Rest API模板,访问远程http服务,只需要提供服务提供者的链接地址
(7)eureka和zookeeper的区别?
CAP原则:C:强一致性;A可用性;P:分区容错性
CAP理论:一个分布式系统不可能同时满足一致性、可用性和分区容错性三个需求
其中分区容错性是分布式系统中必须要保证的,其中Zookeeper保证的是CP;Eureka保证的是AP
- Zookeeper(CP):可以容忍注册中心返回的是几分钟前的注册信息,但是不能接受服务直接宕机不可用,存在一种情况当master节点挂掉后其余节点进行leader选举,在这期间整个zk集群都是不可用的,注册服务瘫痪。
- Eureka(AP):优先保证可用性,各个节点都是平等的,几个节点挂掉不会影响正常节点工作,剩余节点可以提供注册和查询服务,并且还有自我保护机制,但是可能查询的信息不是最新的。
summary:Eureka可以很好应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper使整个注册服务瘫痪。
10、Ribbon
(1)Ribbon是Netflix发布的开源项目,为客户端提供负载均衡工具,提供了一系列完成的配置:连接超时;重试等。
负载均衡:将用户的请求平摊到多台服务器上,达到系统的高可用。
常见的负载均衡软件:Nginx,Lvs
负载均衡分类:
- 集中式:如Nginx,负责把访问请求通过某种策略转发至服务的提供方
- 进程式:如Ribbon,消费方从服务注册中心获得有哪些地址可用,再从这些地址中选出合适的服务器(消费者选服务器)
(2)使用负载均衡步骤:(Ribbon和Eureka整合以后,客户端可以直接调用服务【通过服务名】,不用关心IP地址)
- 服务消费者添加Ribbon、Eureka依赖
- application.yml文件中添加Eureka配置(不需要向Eureka注册自己),编写去哪个地方获取配置文件service-url-defaultZone
- 在配置类中添加注解@LoadBalanced(此配置类提供给消费者Restful模板)
- 在消费者的Controller类中,使用Restful模板的url不应该是固定的,而是可供选择的,所以使用服务名来访问,因为这个服务之前在集群中注册给了三个Eureka Server节点。
- 新建多个服务提供者,连接不同的数据库(数据库内容都相同,数据库名不同),同时向多个注册中心注册,但是服务的名称需要相同
- 启动服务消费者,可以看到每次访问的数据库不同(访问的服务提供者不同)(Ribbon默认使用轮询算法)
(3)自定义负载均衡策略步骤
①建立自己的负载均衡类,用@Configuration,且该类不能在主启动类的同一级文件夹中,可以放在上一级,在该类中用@Bean注解自定义的负载均衡算法(KuangRandomRule类,此类需要继承AbstractLoadBalancerRule抽象负载均衡策略)
②在消费者主启动类中添加@RibbonClient注解,标注自定义负载均衡类configuration的类名和要进行负载均衡的微服务名称name
11、Feign负载均衡
利用接口和注解调用微服务(类似于在Dao接口上注解@Mapper,现在只需要在微服务接口上注解@FeignClient)
使用步骤:
①添加feign依赖
②在服务提供类中使用@FeignClient注解,编写接口,注解中value的值为微服务的名字
③在服务消费者的控制类中注入上面编写的接口,通过接口对服务进行调用,区别于使用Ribbon时使用微服务名进行调用。
④在服务消费者的主启动类中添加@EnableFeignClient注解,并注明需要扫描的包含接口的包名
12、Hystrix服务熔断与服务降级
分布式系统面临的问题:复杂分布式体系结构中应用程序有数十个依赖关系,每个依赖关系在某一时刻都可能失败。
(1)服务雪崩:多个微服务之间调用的时候,假设微服务A调用微服务B和C,B和C又调用其他微服务,如果B和C的链路上某个微服务调用时间过长或者不可用,则对微服务A的调用就会占用越来越多的资源,引起系统崩溃。在高并发情况下,单一的后端依赖可能会导致所有服务器上的所有资源都很快饱和,导致服务之间延迟增加、线程和其他资源紧张,最终会导致系统故障,所以需要对故障和延迟进行隔离和管理,以便在单个依赖关系失败时不会取消整个应用程序。
(2)服务熔断(在服务端操作):是对服务雪崩的一种微服务链路保护机制。当链路的某个微服务不可用或者响应时间太长,会进行服务降级,进而熔断该节点微服务的调用,快速返回错误的响应信息,当检测到该节点微服务响应正常后恢复调用链路。
Hystrix:一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里会有许多依赖不可避免的会调用失败,比如超时、异常。Hystrix可以保证在一个依赖出错的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性。当某个服务出现故障后,通过故障监控,向调用方返回一个服务预期的、可处理的备选响应(备用的服务),而不是长时间等待或者抛出调用方法无法处理的异常,这样可以保证服务调用方的线程不会被长时间占用,避免故障在分布式系统中的蔓延和雪崩。Hystrix会监控微服务的调用状况,当失败调用达到一定阈值,启动熔断机制,注解时@HystrixCommand。
(3)Hystrix服务熔断使用步骤:
①添加依赖
②在服务提供者的控制类controller中使用注解@HystrixCommand,如果被注解的方法出现异常超过一定次数,直接使用下面的备选方法,备选方法中可以使用返回一个正确的且告知没有对应信息的值。
③在服务提供者的主启动类添加注解@EnableCircuitBreaker,添加对熔断的支持
(4)服务降级(在客户端操作,由客户选择不去访问被降级的服务)
例如有三个服务器A、B、C,在某一时段有大量的用户访问服务器A导致A服务器资源不够,而B和C几乎没有用户访问,则利用服务降级关闭服务器B、C中的服务,将服务器运行A中的服务,以提高资源的利用率,等高并发结束后再重新开启原来B、C中的服务。在服务降级过程中用户只能选择服务A。
(5)服务降级实现步骤:
①编写服务降级的类,实现FallbackFactory类,如果该服务已经被关闭了,会返回一个信息,告知服务不可用,但是不影响用户访问其他服务
②在FeignClient接口中绑定编写好的服务降级类fallbackFactory
③在服务消费者配置文件中开启服务降级
总结:
服务熔断:在服务端操作,当某个服务超时或者异常时引起服务熔断
服务降级:在客户端操作,从网站整体负载考虑,当服务发生熔断或者关闭时,服务将不再被调用,此时在客户端,可以编写一个FallbackFactory,返回一个默认的值。(虽然会导致服务水平下降,但是比直接挂掉可用性强)
(7)Dashboard流监控
可视化监控面板
①消费者端添加依赖,配置文件中添加端口号9001
②消费者端启动注解@EnableHystrixDashboard
③每个服务端添加被监控的依赖
④在服务端主启动类添加Servlet bean,使得能被监控,
⑤进入消费者的监控页面http://localhost:端口号/hystrix
此端口号是消费者服务器的端口号
⑥监控页面显示:
13、Zuul路由网关
Zuul包含了对请求的路由和过滤两个功能。
- 路由:将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础
- 过滤:负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
Zuul和Eureka整合后,将Zuul注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,以后的访问微服务都是通过Zuul跳转后获得。
实现步骤:
①添加依赖
②配置文件
可以直接使用路径dept代替原来微服务的名称,防止微服务暴露
原路径:
现路径:
可以使原路径无法访问:
用通配符隐藏全部的微服务名称,也可以增加prefix添加前缀需求:
总结:
- 实现路由:
- 实现过滤:
③主启动类添加注解@EnableZuulProxy