一、微服务架构解决问题
Spring Cloud 组件多,功能完备 Http
Dubbo +Zookeeper功能非完备,组件少 RPC通信
最大的问题 网络是不可靠的
1.客户端通过API网关访问多服务
2.服务与服务通信
? 同步通信
? HTTP(Apache Http Client)
? RPC(Dubbo 支持Java,Apache Thrift,gPRC)
? 异步通信
? 消息队列kafka RabbitMQ RocketMQ
3.服务如何管理
? 服务注册与发现
? 基于客户端的服务注册与发现
? Zookeeper
? 基于服务器端的服务注册与发现
? Eureka
4.服务挂了
? 重试机制
? 服务熔断
? 服务降级
? 服务限流
二、Zookeeper 分布式协调服务
主要是用来解决分布式环境中多个进程之间的同步控制,让他们有序的访问某种临界资源,防止造成“脏数据”的后果
分布式锁
1.在分布式系统环境下,一个方法在同一时间只能呗一个机器的一个线程执行
2.高可用的获取锁与释放锁
3.高性能的获取锁与释放锁
4.具备可重入特性(由多于一个任务并发使用,而不必担心数据错误)
5.具备锁失效机制,防止死锁
6.具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
分布式锁实现
1.Memcached:利用add命令
2.Redis:利用setnx命令
3.Zookeeper:利用顺序临时节点,来实现分布式锁和等待队列
4.Chubby:利用Paxos一致性算法
三、核心功能与组件角色
1.组件
? 提供者
? 消费者
2.通信模型
? BIO 同步并阻塞
? NIO 异步并阻塞框架的抽象封装游戏服务器,物联网服务器
? AIO 异步非阻塞
四、常见面试题
? 1.什么是微服务
? 2.微服务之间是如何独立通讯的
? 3.SpringCloud和Dubbo有哪些区别
? 4.SpringBoot和SpringCloud,请你谈谈对他们的理解
? 5.什么是服务熔断,什么是服务降级
? 6.微服务的优缺点是什么,在项目开发中遇到的坑
? 优点
? [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iVPB6hpa-1657620920494)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220706201629039.png)]
? 缺点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hzf6lal9-1657620920496)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220706201955032.png)]
微服务技术栈有哪些
? [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eHI9kj8Q-1657620920497)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220706202031252.png)]
? eureka和zookeeper都可以提供服务注册与发现的功能,这俩的区别
五、SpringCloud
①基于Springboot提供了一套微服务解决方案
包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做出高度抽象封装之外,还有一些选型中立的开源组件
SpringCloud利用SpringBoot的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用SpringBoot的开发风格做到一键启动和部署。
SpringBoot并没有重复造轮子,它只是将目前各家公司开发的比较成熟,经得起实际考研的服务框架组合起来,通过SpringBoot风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂,易部署和易维护的分布式系统开发工具包
SpringCloud是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。
②SpringCloud和SpringBoot的关系
- SpringBoot专注于快速方便的开发单个个体微服务。-Jar
- SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等集成服务。
- SpringBoot可以离SpringClooud独立使用,开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系
- SpringBoot专注于快速、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架
③dubbo和Spring区别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-92SxO3Bx-1657620920498)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220706204742089.png)]
六、Eureka
? 不要乱导入依赖包,注意各版本之间的冲突问题
? Springboot 2.4.0
? Springcloud 2020.0.5
? spring-cloud-starter-netflix-eureka-server 2.2.5.RELEASE
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.5</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.0</version>
</dependency>
还得需要配置,否则启动不了
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
启动报错gson
解决问题加上一下exclude
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class,GsonAutoConfiguration.class})
七、作为服务注册中心,Eureka比Zookeeper好在哪里
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A (可用性)、P(容错性由于分区容错性P在分布式系统中是必须要保证的,因此我们只能在A和C之间进行权衡。
- Zookeeper保证的是CP
- Eureka保证的是AP
1.Zookeeper保证的是CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30~120s,且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得z水k集群失去master节点是较大概率会发生的事件,虽然服务最终能够恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
2.Eureka保证的是AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其他节点中
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪
3.ACID和CAP
ACID(Mysql,Oracle,sqlServer)
? A 原子性
? C 一致性
? I 隔离性
? D 持久性
CAP(redis,mongdb)
? C 强一致性
? A 可用性
? P 分区容错性
CAP的三进二:CA,AP,CP
八、ribbon负载均衡
注意这个大坑!!!!
因为老版本的springcloud 继承ribbon是需要引入 ribbon的jar包才可以使用ribbon 后来Netflix 旗下的框架 包括ribbon停止了维护 故 springcloud 3.0之后自己做了兼容不需引入ribbon的jar包就可以做负载均衡
所以新版本不需要导入ribbon包,用官方推荐的Spring Cloud LoadBalancer!!!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g7sLpn82-1657620920499)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220709160136706.png)]
spring-cloud-starter-netflix-eureka-client//此包下面自带Spring Cloud LoadBalancer,不需要手动导入其他包
官方自带轮询和随机负载均衡
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
此方法开启默认轮询负载均衡
其他类不需要添加任何注解
自定义负载均衡
第一步
首先有一个类实现ReactorServiceInstanceLoadBalancer
private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
public CustomLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider) {
this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
}
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable();
return supplier.get().next().map(this::getInstanceResponse);
}
以上必须有并且是实现choose方法
private Response<ServiceInstance> getInstanceResponse
这个方法用来自定义负载均衡的方法
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances){
if (instances.isEmpty()) {
return new EmptyResponse();
}
count++;
if(count>=4){
count=0;
index++;
}
int size = instances.size();
if(index>=size){
index=0;
}
ServiceInstance instance=instances.get(index);
return new DefaultResponse(instance);
}
此方法每四次换一个服务id,超过服务id长度,index置零
第二步
一个配置类CustomLoadBalancerConfiguration,类名随意
@Configuration
public class CustomLoadBalancerConfiguration {
@Bean
public ReactorServiceInstanceLoadBalancer customLoad(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider){
return new CustomLoadBalancer(serviceInstanceListSupplierProvider);
}
}
返回自己自定义负载均衡类名CustomLoadBalancer
第三步
在启动类上面添加注解
@LoadBalancerClient(name = "springcloud-provide-dept",configuration = CustomLoadBalancerConfiguration.class)
name:服务名
configuration:自定义配置类名
如果配置了自定义负载均衡,然后又想使用官方轮询方式,把配置类的configuration注解去掉,再把启动类上的LoadBalancerClient注解去掉即可
九、fegin
在消费者的dao接口添加FeginClient注解value属性值为服务提供的name,在controller和原来普通的返回this.service.方法名()面向接口编程
十、Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
作用
服务熔断
熔断机制是对应雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ykUDWWyZ-1657620920499)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220711143823278.png)]
单个服务降级
在方法上添加@HystrixCommand,属性fallbackMethod,错误时调用的方法
在启动类增加@EnableHystrix
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "getHystrix")
public Dept get(@PathVariable("id") Long id){
if(deptService.queryById(id)==null){
throw new RuntimeException();
}
return deptService.queryById(id);
}
public Dept getHystrix(@PathVariable("id") Long id){
Dept dept = new Dept();
dept.setDname("id不存在");
dept.setDeptno(id);
dept.setDb_source("id不存在");
return dept;
}
多个服务降级
在类上添加@DefaultProperties 注解
- groupKey:默认情况下指定的每个 Hystrix 命令使用默认组密钥,除非命令显式指定组密钥。默认为空字符串
- threadPoolKey:默认情况下指定的每个 Hystrix 命令使用默认线程池密钥,除非命令显式指定了线程池密钥。默认为空字符串
- commandProperties:将用于为每个 Hystrix 命令的命令属性指定默认属性,除非在 @HystrixCommand 中显式指定命令属性。
- threadPoolProperties:将用于为每个 Hystrix 命令的线程池属性指定默认值,除非在 @HystrixCommand 中显式指定线程池属性。
- ignoreExceptions:定义应该被忽略的异常。如果 raiseHystrixExceptions 包含 RUNTIME_EXCEPTION,则这些可以被包装在 HystrixRuntimeException 中。
- raiseHystrixExceptions:当包含 RUNTIME_EXCEPTION 时,任何未被忽略的异常都会被包装在 HystrixRuntimeException 中。
- defaultFallback:为给定类中的每个命令指定默认回退方法。类中的每个命令都应该有一个与默认回退方法返回类型兼容的返回类型。注意:默认回退方法不能有参数。
@DefaultProperties(defaultFallback = "fallBack")
也要在方法上添加@HystrixCommand不用添加任何属性
类中的每个命令都应该有一个与默认回退方法返回类型兼容的返回类型!!!
commandProperties
启用断路器 @HystrixProperty(name = “circuitBreaker.enabled”, value = “true”) 设置请求次数 @HystrixProperty(name = “circuitBreaker.requestVolumeThreshold”, value = “10”) 设置时间窗口期 @HystrixProperty(name = “circuitBreaker.sleepWindowInMilliseconds”, value = “10000”) 设置失败率 @HystrixProperty(name = “circuitBreaker.errorThresholdPercentage”, value = “60”)
如上设置的值,如果在10秒内,失败率达到请求次数(10)的百分之60,也就是6次就会 打开断路器;否则断路器依然关闭
当断路器开启时,所有的请求都不会转发,而是直接调用fallback方法;在一段时间后(默认5秒),断路器处于半开状态,尝试将请求转发,如果得到正确的响应。则将断路器关闭,恢复正常调用;否则断路器状态再次打开,重新计时后再进入半开状态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LLmLcvE2-1657620920500)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220711181952614.png)]
全局配置
在yml中添加hystrix配置
在HystrixCommandProperties类中的构造器可查看对应配置的路径信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ufYARyy3-1657620920501)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220711184333110.png)]
例如circuitBreaker.sleepWindowInMilliseconds
即对应的yml配置为
hystrix:
command:
default:
circuitBreaker:
sleepWindowInMilliseconds: 10000
同理以上四个配置为
hystrix:
command:
default:
circuitBreaker:
sleepWindowInMilliseconds: 10000
enabled: true
requestVolumeThreshold: 10
errorThresholdPercentage: 60
十一、Hystrix:dashboard流量监控
需要的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
yml中需要配置才能显示流量图
hystrix:
dashboard:
proxy-stream-allow-list: "*"
在启动类上添加@EnableHystrixDashboard注解
服务提供者需要开启服务熔断并且在启动类配置
@Bean
public ServletRegistrationBean registrationBean(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
在url输入
服务提供者的ip和端口/actuator/hystrix.stream
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6tLwS9Ii-1657620920501)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220711211459303.png)]
如果一直显示ping没有data,在消费者端提交一个数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uJWllSBU-1657620920502)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220711211529439.png)]
url输入服务提供者的ip和端口/actuator/hystrix.stream点击Monitor Stream显示流量图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PE1xzqw7-1657620920503)(C:\Users\OMEN\AppData\Roaming\Typora\typora-user-images\image-20220711211602538.png)] vletRegistrationBean registrationBean(){ ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet()); registrationBean.addUrlMappings(“/actuator/hystrix.stream”); return registrationBean; }
在url输入
服务提供者的ip和端口/actuator/hystrix.stream
[外链图片转存中...(img-6tLwS9Ii-1657620920501)]
如果一直显示ping没有data,在消费者端提交一个数据
[外链图片转存中...(img-uJWllSBU-1657620920502)]
url输入服务提供者的ip和端口/actuator/hystrix.stream点击Monitor Stream显示流量图
[外链图片转存中...(img-PE1xzqw7-1657620920503)]
|