SpringCloud学习笔记

原理

CAP原理

分布式系统中,多个节点之前的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题)某些节点之间不连通了,整个网络被分成了几块区域,这就叫网络分区

  • 一致性(Consistence) : 所有节点访问同一份最新的数据副本
  • 可用性(Availability): 非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应)
  • 分区容错性(Partition tolerance) : 分布式系统出现网络分区的时候,仍然能够对外提供服务

BASE原理

BASE强调牺牲高一致性,从而获取可用性,数据允许在一段时间内不一致,只要保证最终一致性就可以了。

  • 弱一致性:系统不能保证后续访问返回更新的值。需要在一些条件满足之后,更新的值才能返回。从更新操作开始,到系统保证任何观察者总是看到更新的值的这期间被称为不一致窗口

  • 最终一致性:这是弱一致性的特殊形式。存储系统保证如果没有对某个对象的新更新操作,最终所有的访问将返回这个对象的最后更新的值


概念

分布式和集群

  • **集群:**一台服务器无法负荷高并发的数据访问量,就设置多台服务器一起分担压力,是在物理层面解决问题。
  • **分布式:**将一个复杂的问题拆分成若干简单的小问题,将一个大型的项目架构拆分成若干个微服务来协同完成,在软件设计层面解决问题。

微服务优点

  • 各个服务相互独立,只需要对外提供的接口正常即可,而不限制框架和语言的选择

Spring Cloud 就是微服务系统架构的一站式解决方案,在平时我们构建微服务的过程中需要做如 服务发现注册配置中心消息总线负载均衡断路器数据监控 等操作,而 Spring Cloud 为我们提供了一套简易的编程模型,使我们能在 Spring Boot 的基础上轻松地实现微服务项目的构建。

Spring Cloud 总体架构


服务注册中心

实现服务注册与服务发现

Eureka

服务端:引入相关依赖并配置访问Eureka的地址

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

核心

Eureka Server:提供服务注册服务

Eureka Client:要注册的微服务可以通过Eureka Client进行注册,以及进行服务发现@EnableDiscoveryClient获得Server的服务信息

  • 服务注册
  • 服务续约:Eureka 客户会每隔30秒(默认情况下)发送一次心跳来续约
  • 服务下线:客户端正常下线
  • 服务剔除:如果 Eureka Server 在90秒没有收到 Eureka 客户的续约,它会将实例从其注册表中删除
  • 获取注册列表信息:该注册列表信息定期(每30秒钟)更新一次,并缓存到消费者本地

集群

防止单点故障,实现负载均衡和故障容错

服务端节点互相注册,互相守望

使用@LoadBalanced注解还可以实现RestTemplate负载均衡的能力,默认引入了Ribbon

server:
  port: 7001
spring:
  application:
    name: cloud-eureka-service
eureka:
  instance:
    # eureka服务端的实例名称
    hostname: eureka7001.com
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
    fetch-registry: false
    service-url:
      # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka/s

image-20210524234359751


自我保护

  • 当一个 server 节点出现了网络分区等不可抗力原因,那么它会因此收不到 client 的续约心跳,如果网络波动比较大,也就可能导致 server 因为一次网络波动剔除了所有或者绝大部分 Client
  • 默认是15分钟内收到的续约低于原来的85%(这是设置的续约配置比例)那么就会开启 自我保护 。这阶段 Eureka Server 不会剔除其列表中的实例,即使过了 90秒 也不会。
  • 属于CAP里面的AP

Zookeeper

在linux中启动服务端

注意存在服务端zk与pom中版本不一致问题,zookeeper版本jar包冲突

服务注册创建的是临时节点

server:
  # 8004表示注册到zookeeper服务器的支付服务提供者端口号
  port: 8004
spring:
  application:
    # 服务别名---注册zookeeper到注册中心的名称
    name: cloud-provider-payment
  cloud:
    zookeeper:
      # 默认localhost:2181
      connect-string: localhost:2181

Consul

基于go语言,下载exe文件运行

server:
  # consul服务端口
  port: 8006
spring:
  application:
    name: cloud-provider-payment
  cloud:
    consul:
      # consul注册中心地址
      host: localhost
      port: 8500
      discovery:
        hostname: 127.0.0.1
        service-name: ${spring.application.name}

注册中心异同

CAP原理不同

image-20210525000441963

image-20210525000600362


负载均衡

Ribbon

集中式LB:Nginx是服务端负载均衡,客户端所有请求交给nginx实现转发请求

进程内LB:Ribbon是本地负载均衡,会在注册中心中获取注册信息服务列表之后选择合适的服务器

  1. Ribbon 是 Netflix 发布的均衡负载器,是一个用于对 HTTP 请求进行控制的负载均衡客户端

  2. 负载均衡+RestTemplate调用实现负载均衡

  3. 在注册中心对 Ribbon 进行注册之后,通过@Bean创建LB类选择不同的负载均衡算法(轮循、随机、加权轮询、加权随机等)自动帮助服务消费者调用接口

  4. 还可以根据具体需求自定义 Ribbon 负载均衡算法,去掉注解@LoadBalanced 。既可以实现IRule 接口,也可在Controller里面实现

@Configuration
public class MySelfRule {

    @Bean
    public IRule myRule() {
        // 定义为随机
        return new RoundRobinRule();
    }
}

---
  
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB() {
		List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
  	if (instances == null || instances.size() <= 0) {
    	return null;
  	}
  	//自定义的负载均衡策略
 	 	ServiceInstance instance = loadBalancer.instances(instances);
  	URI uri = instance.getUri();
  	return restTemplate.getForObject(uri + "/payment/lb", String.class);
}

OpenFeign

使用 Ribbon 进行负载均衡,Feign 也是 Netflix 提供的,Feign 是一个声明式、模板化的 Web Service 客户端,让编写Web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可。

相比于 Ribbon + RestTemplate 的方式,Feign 可以大大简化代码开发,自带负载均衡配置项,支持服务调用。

  1. 支持超时控制,客户端默认等待1秒
  2. 支持日志打印,了解http请求的细节
  3. 结合hystrix,支持服务熔断

![image-20210526004005615]

@RestController
@Slf4j
public class OrderController {
    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") long id) {
        return paymentFeignService.getPaymentById(id);
    }
}

服务熔断 Hystrix

服务雪崩:调用服务链某一处阻塞从而导致整个系统崩溃

熔断机制是应对雪崩效应的微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。


服务降级

服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示,fallback

程序运行异常、超时、服务熔断触发服务降级、线程池/信号量也会导致服务降级。

  1. @HystrixCommand注解设置自身调用超时时间的峰值,峰值内可以正常运行, 超过了需要有兜底的方法处理,做服务降级fallback

image-20210526005440407

  1. 结合Feign客户端实现与业务代码的解耦

image-20210526005649159

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OTBZi0ik-1623904934154)(E:\java\笔记\photo\SpringCloud.assets\image-20210526005659009.png)]


服务熔断

类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示

熔断关闭-熔断打开-熔断半开

  1. 当满足一定的阈值的时候(默认10秒钟超过20个请求次数)
  2. 当失败率达到一定的时候(默认10秒内超过50%的请求次数)
  3. 到达以上2个阈值,断路器将会开启
  4. 当开启的时候,所有请求都不会进行转发,进行服务降级
  5. 一段时间之后(默认5秒),这个时候断路器是半开状态,会让其他一个请求进行转发. 如果成功,断路器会关闭,若失败,继续开启.重复4和5

image-20210526010239552

image-20210526010459475

image-20210526010626668

image-20210526010812072


图形化的监控信息hystrixDashboard,查看请求成功失败的信息

新版本Hystrix需要在主启动MainAppHystrix8001中指定监控路径,并在页面填写监控路径


服务网关GateWay

  • Gatway会根据注册中心注册的服务列表, 以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能

  • 可以进行流量控制、日志记录、请求路由、请求过滤

  • Gateway使用的是Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架,非阻塞异步AIO

image-20210526174435006

image-20210526174344170


特性

路由转发+执行过滤器链

  • 动态路由:路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成
  • 断言Predicate:断言为true则匹配该路由。Predicate就是为了实现一组匹配规则, 让请求过来找到对应的Route进行处理

image-20210526175313295

  • 过滤器:可以在请求被路由前pre或者之后post对请求进行修改

    通过implments GlobalFilter,OrderId来自定义过滤器

@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("come in global filter: {}", new Date());

        ServerHttpRequest request = exchange.getRequest();
        String uname = request.getQueryParams().getFirst("uname");
        if (uname == null) {
            log.info("用户名为null,非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        // 放行
        return chain.filter(exchange);
    }

    /**
     * 过滤器加载的顺序 越小,优先级别越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
 
 

工作流程

工作流程


配置中心Config

Spring Cloud Config 通过服务端可以为多个客户端提供配置服务,既可以将配置文件存储在本地,也可以将配置文件存储在远程的 Git 仓库,创建 Config Server,通过它管理所有的配置文件。

config客户端动态刷新问题,@RefreshScope修饰业务类,通过curl手动刷新,避免每次更新配置都要重启客户端微服务

img


消息总线Bus

分布式自动刷新配置功能:SpringCloud Bus配合Springcloud Config使用可以实现配置的动态刷新

ConfigClient实例都监听MQ中的同一个topic(默认是SpringcloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到topic中,这样其它监听同一个topic的服务就能得到通知,然后去更新自身的配置。

既可以全局通知也可以定点通知

image-20210527003439293


消息驱动Stream

  • 屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型
  • 通过定义绑定器Binder作为中间件,实现了应用程序与消息中间件细节之间的隔离

Binder:很方便的连接中间件,屏蔽差异

Channel:通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过channel对队列进行配置

Source和Sink:简单的可理解为参照对象是Springcloud Stream自身,从Stream发布消息就是输出,接受消息就是输入

image-20210527004309225


分组消费与持久化

微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次。不同的组是可以重复消费的,同一个组内会发生竞争关系,只有其中一个可以消费。

分组后消费者宕机恢复后还可以继续消费宕机期间产生的未被消费的消息

image-20210527004914665


Sleuth分布式链路跟踪

在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每个前段请求都会形成条复杂的分布式服务调用链路,链路中的任何环出现高延时或错误都会引起整个请求最后的失败。

image-20210527010406412

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值