Spring Cloud 与 K8s 下的微服务组件

SpringBoot 与 SpringCould 是什么?它们的出现是为了解决什么问题?

Spring Boot:是一种服务开发技术;是为了达到简化项目的目的。

Spring Cloud:分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶;是为了解决大型项目中,各种出现的问题,提高系统的整体性能。

在对 Boot 和 Cloud 版本选择注意事项:

  建议严格按照官方版本采用 Json 串中的来选择。也可以在下图的链接里,找到当前 Cloud 推荐使用的 Boot 版本。
在这里插入图片描述

故,在本次的学习中,版本选择如下:

  • Cloud:Hoxton.SR4
  • Boot:2.2.5.RELEASE
  • Java:1.8
  • Cloud Alibaba:??

Cloud 中的模块及实例

在这里插入图片描述


Eureka: 服务治理、注册、发现

Eureka:类似ZK的功能,其服务架构与 dubbo 的对比如下:
在这里插入图片描述
Eureka 的两个组件:

  • Eureka Server:微服务中的各个节点到 Server 中去注册自己的信息。
  • Eureka Client:一个 Java 客户端,用于简化与 Server 的交互。Client 会以 30 秒为周期向 Server 端发送心跳,Server 在 90s 没有收到某一个 Client 的心跳时,将会移除该节点。

Eureka 集群

Q:为什么我们需要 Eurake 集群?

A:为保障服务注册、服务调用的高可用性

搭建 Eureka 注册中心集群,各节点间 互相注册,相互守望,实现 负载均衡 + 故障容错 的功能。

Dubbo 是一个 RPC 调用方式的分布式服务组件之一,Eureka 提供的是 REST API 的调用方式。

Eureka 在启动类使用 @EnableEurekaServer 标识该应用为注册中心,在启动类使用 @EnableEurekaClient 标识该应用为服务提供方或消费方

1. 注册中心配置文件

server:
  port: 7001
spring:
  application:
    name: eureka-server7001  #eureka服务端的实例名称,当与 hostname 同时存在时,采用applicationName
      #在消费、提供方的应用中,该名称为Eureka中Application的值,若provider为集群,则name值应当一致,才能让消费方通过一个name调用到多个提供方节点应用

eureka:
  instance:
    hostname: eurekaServer7001.com #eureka服务端的实例名称
  client:
    register-with-eureka: false     #false表示不向注册中心注册自己。
    fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      #集群指向其它eureka
      defaultZone: http://localhost:7002/eureka/
      #单机就是7001自己
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

2. 服务提供方配置文件

server:
  port: 8001
spring:
  application:
    #在消费、提供方的应用中,该名称为Eureka中Application的值,若provider为集群,则name值应当一致,才能让消费方通过一个name调用到多个提供方节点应用
    name: eureka-provider7002

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    serviceUrl:
      #defaultZone: http://localhost:7001/eureka/
      defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka
  instance:
    #在eurakeServer中采用IP形式的链接地址
    preferIpAddress: true
    #定义实例ID格式,即eureka中节点的显示名称
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}

3. 服务消费方配置文件

server:
  port: 9001
spring:
  application:
    name: eureka-consumer7003

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    serviceUrl:
      #defaultZone: http://localhost:7001/eureka/
      defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka/

Eureka 自我保护机制

在这里插入图片描述
什么是自我保护机制?

  当 Eurekaserver 在一定时间(默认90秒)内没有收到实例的心跳,便会把该实例从注册表中删除。但是,如果 Server 在 15 分钟内,心跳失败的比例低于 85%,那么 Server 便会将当前的这些实例保护起来,不让实例过期。

在自我保护机制下:
1. Server 不会注销任何服务实例,但如果保护期间内实例出现问题,那么消费方的调用就会失败,所以客户端必须要有容错机制。
2. Server 仍然能够接受新实例的注册和查询请求,但是不会同步新的实例到其它 Server 上。当网络稳定后,Server 实例便会与其他节点 Server 节点同步信息。

为什么需要自我保护机制?

  为防止 EurekaServer 在网络不通的情况下,将正常的 EurekaClient 实例错误剔除的操作。自我保护模式是一种应对网络异常的安全保护措施。

关闭自我保护机制
  在实际开发中,我们会不断的重启服务,所以需要 Eurake 服务端及时的删除失效的服务。在生产环境不推荐使用。

  1. 在服务注册端:
eureka:
	server:
	  enable-self-preservation: false  # 关闭自我保护机制 保证不可用服务及时清除
	  eviction-interval-timer-in-ms: 3000  # 驱逐计时器扫描失效服务的间隔时间,默认 60*1000 毫秒

eureka.server.eviction-interval-timer-in-ms 不建议修改,它只是驱逐计时器扫描的间隔时间,当手动关闭 Eureka Client 后,注册中心也并不会立马注销此节点,同样要等到约 90s 后收不到客户端心跳才会将其移除。
2. 在服务提供方:

eureka:
  server:
	lease-renewal-interval-in-seconds: 1 # eureka客户端租赁续约间隔 单位秒 默认30
	lease-expiration-duration-in-seconds: 3 # eureka客户端租赁期满时间 默认90
  1. 在服务消方:
eureka:
  client:
	#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
	register-fetch-interval-seconds: 30 # 消费方缓存服务列表清单的更新时间,默认为30s

DiscoveryClient 源码阅读:

DiscoveryClient 需要做的事情(可在类的头部找到注释):
a:向server注册实例
b:向server服务续约
c:关闭服务时,取消租约
d:查询server中的服务列表

  我们在配置属性名 eureka.client.serviceUrl.defaultZone 后,会使用到 EndpointUtils 中的函数 getServiceUrlsMapFromConfig

    /**
     * Get the list of all eureka service urls from properties file for the eureka client to talk to.
     *
     * @param clientConfig the clientConfig to use
     * @param instanceZone The zone in which the client resides
     * @param preferSameZone true if we have to prefer the same zone as the client, false otherwise
     * @return an (ordered) map of zone -> list of urls mappings, with the preferred zone first in iteration order
     */
    public static Map<String, List<String>> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone) {
        Map<String, List<String>> orderedUrls = new LinkedHashMap<>();
        String region = getRegion(clientConfig);
        String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
        if (availZones == null || availZones.length == 0) {
            availZones = new String[1];
            availZones[0] = DEFAULT_ZONE;
        }
        logger.debug("The availability zone for the given region {} are {}", region, availZones);
        int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);

        String zone = availZones[myZoneOffset];
        List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
        if (serviceUrls != null) {
            orderedUrls.put(zone, serviceUrls);
        }
        int currentOffset = myZoneOffset == (availZones.length - 1) ? 0 : (myZoneOffset + 1);
        while (currentOffset != myZoneOffset) {
            zone = availZones[currentOffset];
            serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
            if (serviceUrls != null) {
                orderedUrls.put(zone, serviceUrls);
            }
            if (currentOffset == (availZones.length - 1)) {
                currentOffset = 0;
            } else {
                currentOffset++;
            }
        }

        if (orderedUrls.size() < 1) {
            throw new IllegalArgumentException("DiscoveryClient: invalid serviceUrl specified!");
        }
        return orderedUrls;
    }
  1. 先执行了 getRegion(clientConfig) 函数获取了一个 Region,可以从函数中发现,每一个应用只属于一个 Region,默认为 default ,也可以通过 eureka.client.Region 来设置。
/**
     * Get the region that this particular instance is in.
     * @return - The region in which the particular instance belongs to.
     */
    public static String getRegion(EurekaClientConfig clientConfig) {
        String region = clientConfig.getRegion();
        if (region == null) {
            region = DEFAULT_REGION;
        }
        region = region.trim().toLowerCase();
        return region;
    }
  1. 再执行 getAvailabilityZones(String region) 函数,默认使用 defaultZone ,即配置的 eureka.client.serviceUrl.defaultZone 的值。也可以通过eureka.client.availability-zones 来设置,按,分隔。由此可以知道一个 Region 可以对应多个 Zone 。
	public String[] getAvailabilityZones(String region) {
		String value = this.availabilityZones.get(region);
		if (value == null) {
			value = DEFAULT_ZONE;
		}
		return value.split(",");
	}

3.在获取了 Region 和 Zone 后,才开始加载 Eureka Server 的具体地址,函数 getServiceUrlsMapFromConfig 中通过如下的逻辑,加载位于哪一个 Zone 的

        int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);

        String zone = availZones[myZoneOffset];
        List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);

服务调用 Ribbon与OpenFeign

SpringCloud 服务调用: Ribbon与OpenFeign


服务熔断、降级组件:Hystrix与Sentinel

SpringCloud 服务熔断、降级组件:Hystrix与Sentinel


分布式配置中心 Config

是什么?有什么优势?
Config 为微服务架构中的微服务提供集中化的外部配置方式,通过客户端获取项目中,共用的配置中心资源,完成各个子项目的配置。

关于@RefreshScope在Spring中的使用

@Bean默认使用的单例饿汉式加载,即在 spirng 应用启动时,就会装载到 IOC 容器中。

@RefreshScope 标注在类上,完成对类成员变量的刷新;@RefreshScope 标注在返回 Bean 的方法上,完成对 Bean 的重新加载。但其前提是客户端本地已经感知到了配置的变化(即向客户端执行 curl -X POST http://ip:port/project-name/actuator/refresh)

k8s下的微服务组件

在这里插入图片描述

k8s下的服务网关

  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值