SpringCloud 入门1:Netflix Eureka的架构,自我保护机制,缓存机制·,服务注册中心搭建,负载均衡,双节点搭建

简介

Spring Cloud 是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地 简化了分布式系统基础设施 的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot 的开发风格做到一键启动和部署。

Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

  • Spring Cloud Netflix
    整个框架的基础,各项服务依赖与它,与各种Netflix OSS组件集成,组成微服务的核心。

  • Netflix Eureka
    服务中心,云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。 提供服务的地方

  • Netflix Hystrix
    熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。对不稳定的节点进行下线,转发请求

  • Netflix Zuul
    Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。可以用于拦截各种恶意请求。

  • Netflix Archaius
    配置管理API,包含一系列配置管理API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。可以实现动态获取配置, 原理是每隔60s(默认,可配置)从配置源读取一次内容,这样修改了配置文件后不需要重启服务就可以使修改后的内容生效,前提使用archaius的API来读取。

  • Spring Cloud Config
    配置中心,配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git以及Subversion。

  • Spring Cloud Bus
    事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与 Spring Cloud Config 联合实现热部署。

  • Spring Cloud Cluster
    Spring Cloud Cluster 将取代 Spring Integration。提供在分布式系统中的集群所需要的基础功能支持,如:选举、集群的状态一致性、全局锁、tokens等常见状态模式的抽象和实现。
    如果把不同的帮派组织成统一的整体,Spring Cloud Cluster已经帮你提供了很多方便组织成统一的工具。

Netflix Eureka

Eureka是Netflix开源的一款提供服务注册发现的产品,它提供了完整的 Service Registry 和 Service Discovery 实现。也是springcloud体系中最重要最核心的组件之一。

服务中心又称 注册中心(类似于京东的杰夫),管理各种服务功能包括服务的注册、发现、熔断、负载、降级等,比如dubbo admin后台的各种功能。

  • 传统的分布式,项目A调用项目B
    在这里插入图片描述
    有了服务中心后:
    在这里插入图片描述

  • 传统分布式,项目A调用项目B,项目B在调用项目C
    在这里插入图片描述
    有了注册中心之后:
    在这里插入图片描述

通过服务中心来获取服务你不需要关注你调用的项目IP地址,由几台服务器组成,每次直接去服务中心获取可以使用的服务去调用既可。

由于各种服务都注册到了服务中心,就有了去做很多高级功能条件。比如

  • 几台服务提供相同服务来做均衡负载
  • 监控服务器调用成功率来做熔断,移除服务列表中的故障点;
  • 监控服务调用时间来对不同的服务器设置不同的权重等等。

Netflix 与 Eureka 的关系

Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现。

  • Eureka 采用了 C-S 的设计架构。
  • Eureka Server 作为服务注册功能的服务器,它是服务注册中心
  • 而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server,并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。
  • Spring Cloud 的一些其他模块(比如 Zuul )就可以通过 Eureka Server 来发现系统中的其他微服务,并执行相关的逻辑。

Eureka 由两个组件组成:Eureka 服务器和 Eureka 客户端。

  • Eureka 服务器用作服务注册服务器。
  • Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
  • Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。
    在这里插入图片描述

Eureka 的基本架构

Eureka 采用了 C-S 的设计架构。

  • Eureka Server 作为服务注册功能的服务器,它是服务注册中心。
  • 而系统中的其他微服务,则使用 Eureka Client 连接到 Eureka Server 并维持心跳连接
  • 这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。
  • Spring Cloud 的一些其他子模块(例如 Gateway)就可以通过 Eureka Server 来发现系统中的其他微服务,并执行相关的业务逻辑。一个 Eureka 的高可用架构图如下:
    在这里插入图片描述

具体步骤:

  • 节点直接同步: 服务启动后向 Eureka 注册,Eureka Server 会将注册信息向其他 Eureka Server 进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
  • 当服务注册中心 Eureka Server 检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为 DOWN 状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。将本地缓存也置为无效
  • 服务提供者在启动后,周期性(默认30秒)向 Eureka Server 发送心跳,以证明当前服务是可用状态。Eureka Server 在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例

eureka的自我保护机制

  • 在默认配置中,Eureka Server 在默认 90s 没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。网络延迟导致心跳延迟收到

  • 为了解决这个问题,Eureka 有自我保护机制,通过在Eureka Server配置如下参数,可启动保护机制。

    eureka.server.enable-self-preservation=true
    
  • 它的原理是,当 Eureka Server 节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。

如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

  • Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
  • Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
  • 当网络稳定时,当前实例新的注册信息会被同步到其它节点中。

Eureka 的缓存功能

  • Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。
  • 所以即便 Eureka 集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过 Eureka客户端缓存来获取现有的服务注册信息。
  • 甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解 决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息。

服务注册中心的搭建

  • 1、pom 中添加依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
  • 2、添加启动代码中添加 @EnableEurekaServer 注解

    @SpringBootApplication
    @EnableEurekaServer
    public class SpringCloudEurekaApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringCloudEurekaApplication.class, args);
        }
    }
    
  • 3、配置文件

在默认设置下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,在 application.properties 添加以下配置:

spring.application.name=spring-cloud-eureka
server.port=8000
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
  • eureka.client.register-with-eureka :表示是否将自己注册到Eureka Server,默认为true。
  • eureka.client.fetch-registry :表示是否从Eureka Server获取注册信息,默认为true。
  • eureka.client.serviceUrl.defaultZone :设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。默认是http://localhost:8761/eureka;多个地址可使用 , 分隔。

启动工程后,访问:http://localhost:8000/,可以看到下面的页面,其中还没有发现任何服务:
在这里插入图片描述

双节点的搭建

注册中心这么关键的服务,如果是单点话,遇到故障就是毁灭性的。在一个分布式系统中,服务注册中心是最重要的基础部分,理应随时处于可以提供服务的状态。

  • 为了维持其可用性,使用集群是很好的解决方案。Eureka 通过互相注册的方式来实现高可用的部署,所以我们只需要将 Eureke Server 配置其他可用的 serviceUrl 就能实现高可用部署。
    具体步骤如下:

  • 1、创建 application-peer1.properties,作为 peer1 服务中心的配置,并将serviceUrl 指向 peer2:

    spring.application.name=spring-cloud-eureka
    server.port=8000
    eureka.instance.hostname=peer1
    eureka.client.serviceUrl.defaultZone=http://peer2:8001/eureka/
    
  • 2、创建 application-peer2.properties,作为 peer2 服务中心的配置,并将serviceUr l指向 peer1

    spring.application.name=spring-cloud-eureka
    server.port=8001
    eureka.instance.hostname=peer2
    eureka.client.serviceUrl.defaultZone=http://peer1:8000/eureka/
    
  • 3、host转换

    在hosts文件中加入如下配置

    127.0.0.1 peer1  
    127.0.0.1 peer2
    
  • 4、打包启动

    依次执行下面命令

    #打包
    mvn clean package
    # 分别以peer1和peeer2 配置信息启动eureka
    java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
    java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
    

依次启动完成后,浏览器输入: http://localhost:8000/效果图如下:
在这里插入图片描述

根据图可以看出peer1的注册中心DS Replicas已经有了peer2的相关配置信息,并且出现在available-replicas中。

  • 我们手动停止peer2来观察,发现peer2就会移动到unavailable-replicas一栏中,表示peer2不可用。

到此双节点的配置已经完成。

eureka集群使用

在生产中我们可能需要 三台或者大于三台的注册中心 来保证服务的稳定性,配置的原理其实都一样,将注册中心分别指向其它的注册中心。
这里只介绍三台集群的配置情况,其实和双节点的注册中心类似,每台注册中心分别又指向其它两个节点即可,使用application.yml来配置。

  • application.yml配置详情如下:

    ---
    spring:
      application:
        name: spring-cloud-eureka
      profiles: peer1
    server:
      port: 8000
    eureka:
      instance:
        hostname: peer1
      client:
        serviceUrl:
          defaultZone: http://peer2:8001/eureka/,http://peer3:8002/eureka/
    ---
    spring:
      application:
        name: spring-cloud-eureka
      profiles: peer2
    server:
      port: 8001
    eureka:
      instance:
        hostname: peer2
      client:
        serviceUrl:
          defaultZone: http://peer1:8000/eureka/,http://peer3:8002/eureka/
    ---
    spring:
      application:
        name: spring-cloud-eureka
      profiles: peer3
    server:
      port: 8002
    eureka:
      instance:
        hostname: peer3
      client:
        serviceUrl:
          defaultZone: http://peer1:8000/eureka/,http://peer2:8001/eureka/
    

    分别以peer1、peer2、peer3的配置参数启动eureka注册中心。

    java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
    java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
    java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer3
    
  • 依次启动完成后,浏览器输入: http://localhost:8000/效果图如下:
    在这里插入图片描述

服务的提供

我们假设服务提供者有一个 hello 方法,可以根据传入的参数,提供输出“hello xxx,this is first messge”的服务

  • 1、pom 包配置
    创建一个 springboot 项目,pom.xml 中添加如下配置:

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
  • 2、配置文件
    application.properties 配置如下:

    spring.application.name=spring-cloud-producer
    server.port=9000
    eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
    
  • 3、启动类
    启动类中添加 @EnableDiscoveryClient 注解

    @SpringBootApplication
    @EnableDiscoveryClient
    public class ProducerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ProducerApplication.class, args);
        }
    }
    
  • 4、controller
    提供 hello 服务

    @RestController
    public class HelloController {
    
        @RequestMapping("/hello")
        public String index(@RequestParam String name) {
            return "hello "+name+",this is first messge";
        }
    }
    

    添加 @EnableDiscoveryClient 注解后,项目就具有了服务注册的功能。启动工程后,就可以在注册中心的页面看到 SPRING-CLOUD-PRODUCER 服务。
    在这里插入图片描述

服务调用

  • 1、pom 包配置 和服务提供者一致

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
  • 2、配置文件
    application.properties 配置如下:

    spring.application.name=spring-cloud-consumer
    server.port=9001
    eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
    
  • 3、启动类
    启动类添加 @EnableDiscoveryClient和 @EnableFeignClients 注解。

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class ConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class, args);
        }
    
    }
    
    • @EnableDiscoveryClient :启用服务注册与发现
    • @EnableFeignClients:启用feign进行远程调用
      Feign 是一个声明式 Web Service 客户端。
    • 使用 Feign 能让编写 Web Service 客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。
    • Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和 HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡
  • 4、feign调用实现

    @FeignClient(name= "spring-cloud-producer")
    public interface HelloRemote {
        @RequestMapping(value = "/hello")
        public String hello(@RequestParam(value = "name") String name);
    }
    

    name:远程服务名,及spring.application.name配置的名称
    此类中的方法和远程服务中contoller中的方法名和参数需保持一致。

  • 5、web层调用远程服务
    将 HelloRemote 注入到controller层,像普通方法一样去调用即可。

    @RestController
    public class ConsumerController {
    
        @Autowired
        HelloRemote HelloRemote;
    
        @RequestMapping("/hello/{name}")
        public String index(@PathVariable("name") String name) {
            return HelloRemote.hello(name);
        }
    
    }
    

    到此,最简单的一个服务注册与调用的例子就完成了。

测试

简单调用

依次启动 spring-cloud-eurekaspring-cloud-producerspring-cloud-consumer 三个项目

  • 先输入: http://localhost:9000/hello?name=neo 检查spring-cloud-producer服务是否正常
    返回: hello neo,thisisfirst messge
    说明spring-cloud-producer正常启动,提供的服务也正常。

  • 浏览器中输入:http://localhost:9001/hello/neo
    返回: hello neo,thisisfirst messge
    说明客户端已经成功的通过feign调用了远程服务hello,并且将结果返回到了浏览器。

负载均衡
  • 以上面spring-cloud-producer为例子修改,将其中的 controller 改动如下:

    @RestController
    public class HelloController {
    
        @RequestMapping("/hello")
        public String index(@RequestParam String name) {
            return "hello "+name+",this is producer 2  send first messge";
        }
    }
    
  • 在配置文件中改动端口:

    spring.application.name=spring-cloud-producer
    server.port=9003
    eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
    

打包启动后,在 eureka 就会发现两个服务提供者,如下图:

在这里插入图片描述
然后在浏览器再次输入: http://localhost:9001/hello/neo进行测试:

  • 第一次返回结果: hello neo,thisisfirst messge
  • 第二次返回结果: hello neo,thisisproducer2send first messge

不断的进行测试下去会发现两种结果交替出现,说明两个服务中心自动提供了服务均衡负载的功能。如果我们将服务提供者的数量在提高为N个,测试结果一样,请求会自动轮询到每个服务端来处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值