zoukankan      html  css  js  c++  java
  • spring cloud组件之Eureka注册中心:通过自动注册、发现、状态监控来管理服务地址

    Eureka:解决服务地址的管理。自身不提供服务(不注册自己到Eureka中,如果是集群则要注册,因为其他Eureka服务器也要发现这台Eureka)也不消费服务(不来取服务)。默认情况下要注册和拉取的

    在刚才的案例中,user-service对外提供服务,需要对外暴露自己的地址consumer-demo(调用者)需要记录服务提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目可能会拆分出十几,甚至几十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦,这与DevOps的思想是背道而驰的。

    Eureka负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。(即发现是通过服务提供方的名字获取实例集合,然后从实例集合中取出一个实例,再从实例中获取IP和端口)

    同时,服务提供方Eureka之间通过 “心跳” 机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。

    这就实现了服务的自动注册、发现、状态监控。

    Eureka:就是服务注册中心(Eureka Server可以是一个集群),对外(服务提供方和服务消费方)暴露自己的地址

    提供者:启动向Eureka注册自己信息(地址,提供什么服务)

    消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新

    心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

    Eureka详解

    基础架构

    Eureka架构中的三个核心角色:

    1、服务注册中心(没有集群时,不需注册和发现)

    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server

    2、服务提供者(只需注册,不需要发现)

    提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的user-service

    3、服务消费者(不仅要注册还要发现)

    消费应用从注册中心获取服务集合,从而得知每个服务方的信息(ip和port),知道去哪里调用服务方。本例中就是我们实现的consumer-demo

    搭建eureka-server工程

    1、创建一个Maven的java工程 eureka-server

    zwh-springcloud右键→new→Module→maven→ArtifactId: eureka-server →next→Module name: eureka-server,Content root: C:UsersmiracleIdeaProjectsspringcloud_2020zwh-springcloudeureka-server→finish

    2、导入依赖坐标:spring-cloud-starter-netflix-eureka-server

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

    3、编写启动类,添加@EnableEurekaServer

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class,args);
        }
    }

    4、编写配置文件application.yml,配置eureka的地址,这个地址是其他服务注册的地址,也是获取服务名的地址

    server:
      port: 10086
    spring:
      application:
        name: eureka-server
    eureka:
      client:
      #Eureka服务地址,如果是集群的话,需要制定集群其他Eureka地址 service
    -url: defaultZone: http://127.0.0.1:10086/eureka fetch-registry: false #默认为true register-with-eureka: false #默认为true

    如果是eureka-server集群的话,则fetch-registry和register-with-eureka均为true

    5、启动服务,访问:http://127.0.0.1:10086

    搭建服务提供方工程,服务注册

    注册服务,就是在服务(提供者)添加Eureka的客户端依赖eureka-client,服务在启动时,如果eureka.client.register-with-eureka=true,则客户端代码会自动把服务注册到EurekaServer中

    1、添加依赖,我们在user-service中添加Eureka客户端依赖:spring-cloud-starter-netflix-eureka-client

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

    2、在启动类上通过添加 @EnableDiscoveryClient开启Eureka客户端发现功能。可以不用添加该注解,因为服务提供方不需要发现。

    @SpringBootApplication
    @MapperScan("com.zwhxpp.user.mapper")
    @EnableDiscoveryClient  #开启Eureka客户端发现功能
    public class UserApplication {
        public static void main(String[] args) {
            SpringApplication.run(UserApplication.class, args);
        }
    }

    3、在配置文件中添加了spring.application.name属性来指定应用名称,将来会作为服务的id使用。

    spring:
      application:
          name: user-service
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka  #告诉服务器Eureka在哪里,才能将服务注册到Eureka中

    搭建服务消费方工程,服务发现

    在服务消费方添加Eureka客户端依赖eureka-client,开启发现功能且eureka.client.fetch-registry=true,则会从EurekaServer服务的列表拉取只读备份,然后缓存在本地

    我们可以使用DiscoveryClient的方法根据服务名称获取对应的服务地址列表来模拟。

    1、添加依赖:spring-cloud-starter-netflix-eureka-client

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

    2、在启动类上通过添加 @EnableDiscoveryClient开启Eureka客户端发现功能

    @SpringBootApplication
    @EnableDiscoveryClient  #开启Eureka客户端发现功能
    public class ConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class,args);
        }
    }

    3、新增配置文件

    server:
      port: 8080
    spring:
      application:
        name: consumer-demo
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka

    4、修改Controller,用工具类DiscoveryClient类的方法,根据服务名称,获取服务实例。

    import org.springframework.cloud.client.discovery.DiscoveryClient;

    当注册服务有多个的时候,我们会用负载均衡的方式从ServerInstance的集合中取出一个(Eureka-client中已经集成了Ribbon),而现在是取第一个

    5、重启 consumer-demo 项目;然后再浏览器中再次访问 http://localhost:8080/consumer/8 ;在代码中debug跟进查看最终拼接要访问的URL:

    服务提供方)服务注册

    服务注册的条件:eureka.client.register-with-eureka=true

    服务注册的方式:主机名注册或ip注册

    服务提供者在启动时,会检测配置属性中的: eureka.client.register-with-eureka=true 参数是否正确,事实上默认就是true。如果值确实为true,则会EurekaServer发起一个Rest请求,并携带自己的元数据信息EurekaServer会把这些信息保存到一个双层Map结构中

    1、第一层Map的Key就是服务id,一般是配置中的 spring.application.name 属性

    2、第二层Map的key是服务的实例id。一般host+ serviceId + port,例如: localhost:user-service:8081

    3、值则是服务的实例对象,也就是说一个服务,可以同时启动多个不同实例,形成集群。

    默认注册时使用的是主机名或者localhost,如果想用ip进行注册,可以在服务提供方 user-service 中添加prefer-ip-address配置如下:(服务地址使用ip方式)

    eureka:
      instance:
        prefer-ip-address: true
        ip-address: 127.0.0.1

    修改完后先后重启 user-service 和 consumer-demo ;默认注册时使用的是主机名,将从eureka获取的实例的主机名改成ip地址,这样,在调用服务的时候就已经变成ip地址;

    需要注意的是:不是在eureka中的控制台服务实例状态显示。即在控制台显示的仍然是主机名,只是在调用服务的时候将主机名改为了ip地址,如下所示:

     

     

    服务提供方)服务续约(30s,90s)

    在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renew);

    有两个重要参数可以修改服务续约的行为;可以在 user-service (服务提供方)中添加如下配置项:

    eureka:
      instance:
        lease-expiration-duration-in-seconds: 90 #默认90秒
        lease-renewal-interval-in-seconds: 30 #默认30秒

    lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒

    lease-expiration-duration-in-seconds:服务失效时间,默认值90秒

    lease:租约租约过期时间90秒,90秒之内没有续约就过期。租约续约时间30

    也就是说,默认情况下每隔30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳(续约)EurekaServer就会认为该服务宕机,会定时(eureka.server.eviction-interval-timer-in-ms设定的时间)从服务列表中移除,这两个值在生产环境不要修改,默认即可

    修改这两个参数的值如下进行测试:

    设置好了之后,重启user-service,然后关闭user-service,按照配置,每隔5秒钟会去续约,如果不续约,再等15秒,如果还没有续约,则会允许剔除,即是可以剔除而不是一定会剔除。但是剔除是在eureka上面剔除的,eureka默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除而现在没有剔除,因为它认为有可能是网络故障造成的,会触发了Eureka的自我保护机制,只有设置了eureka.server.eviction-interval-timer-in-ms(失效剔除)才会真正剔除。

    服务消费方)获取服务列表(30s)

    获取服务列表的条件:eureka.client.fetch-registry=true

    获取服务列表的频率:默认30s

    当服务消费者启动时,会检测 eureka.client.fetch-registry=true 参数的值,如果为true,则会从EurekaServer服务的列表拉取只读备份,然后缓存在本地。并且 每隔30秒 会重新拉取并更新数据。可以在 consumer-demo项目中通过下面的参数来修改:(获取服务地址的频率)

    eureka:
      client:
        registry-fetch-interval-seconds: 30

    服务下线

    当服务(提供方)进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线”。服务中心接受到请求之后,将该服务置为下线状态

    Eureka Server)失效剔除(60s)

    先判断心跳是否续约,如果未续约,则可能失效剔除。

    有时我们的服务(提供方)可能由于内存溢出或网络故障等(非正常原因)使得服务不能正常的工作,而服务注册中心并未收到“服务下线”的请求。相对于服务提供者的“服务续约”操作,服务注册中心在启动时会创建一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除,这个操作被称为失效剔除。

    可以通过 eureka.server.eviction-interval-timer-in-ms 参数对其进行修改,单位是毫秒

    eureka:
      server:
        eviction-interval-timer-in-ms: 60000

    Eureka Server)自我保护

    先判断心跳是否续约,如果未续约,则可能自我保护。

    我们关停一个服务,很可能会在Eureka面板看到一条警告:

     

    这是触发了Eureka的自我保护机制。当服务未按时进行心跳续约时,Eureka会统计服务实例最近15分钟心跳续约的比例是否低于了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka在这段时间内不会剔除任何服务实例,直到网络恢复正常。产环境下这很有效,保证了大多数服务依然可用,不过也有可能获取到失败的服务实例,因此服务调用者必须做好服务的失败容错。

    开发阶段,启动自我保护模式是没有意义的,服务停止了就是停止了,不是因为网络的原因,因为在我们自己的机器上基本不可能出现网络的原因,建议开发是关闭自我保护模式

    自我保护模式是默认打开的。

    可以通过下面的配置来关停自我保护:

    eureka:
    server:
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 60000

    上述配置,先判断心跳是否续约,如果未续约,则会失效剔除,而不会自我保护,因为自我保护已关闭。

    在生产环境,打开自我保护,而不是失效剔除。

  • 相关阅读:
    走出软件作坊
    [Flash入门基本动画]第8课
    [Flash入门基本动画]第6课
    数据中心十项节能妙招
    全面实施虚拟化的五个步骤
    Javascript的匿名函数
    TSQL调试器重返SQL Server 2008
    SQL Server 2008(BI)PPT下载
    通过数据中心整合和虚拟化实现高密度服务器配置
    [Flash入门基本动画]第7课
  • 原文地址:https://www.cnblogs.com/zwh0910/p/14455616.html
Copyright © 2011-2022 走看看