• SpringCloud注册中心Eureka



    前言

    Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、Eureka基础知识

    1.什么是服务治理

    服务治理是随着微服务一起出现的。因为每个服务都有自己独立的资源,服务与服务之间的交互就变得复杂多了,因此服务治理应运而生。
    怎么知道其他服务(服务发现)
    服务怎么管理(服务注册)
    服务之间怎么调用(服务调用)
    服务调用之间出现问题(熔断,降级,限流)
    等等
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.什么是服务注册与发现

    在服务注册与发现中,有一个注册中心。服务提供者会把自己的信息(服务地址通信地址接口地址)以别名的方式注册到注册中心中,服务消费者,以该别名的方式在注册中心获取到实际的服务通信地址,然后再实现本地RPC调用RPC远程服务。

    Eureka系统架构图:
    Eureka采用了CS的设计架构
    在这里插入图片描述

    3.Eureka的两大组件

    Eureka Server和Eureka Client

    • Eureka Server提供服务注册服务
      各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
    • EurekaClient通过注册中心进行访问
      Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

    二、Eureka 单机实操

    1.Eureka Server服务端安装

    生成Eureka Server 服务端,也就是注册中心

    (1)创建cloud-eureka-server7001模块
    (2)修改pom文件
     <dependencies>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-actuatorartifactId>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    Eureka Server版本问题

    
    
    <dependency>
        <groupid>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-eurekaartifactId>
    dependency>
    
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (3)写yml
    server:
      port: 7001
    
    eureka:
      instance:
        hostname: localhost #eureka服务端的实例名称
      client:
        #false表示不向注册中心注册自己。
        register-with-eureka: false
        #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          #设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    (4)写主启动类
    package com.heng;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaMain7001 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaMain7001.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (5)测试运行

    启动之后,浏览器输入http://localhost:7001/
    在这里插入图片描述

    2.cloud-provid-8001payment微服务入驻Eureka Server

    cloud-provid-8001payment是提前创建的微服务支付模块

    (1)修改cloud-provid-8001payment的pom文件

    添加spring-cloud-starter-netflix-eureka-client依赖

     <dependency>
         <groupId>org.springframework.cloudgroupId>
         <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
      dependency>
    
    • 1
    • 2
    • 3
    • 4
    (2)修改yml文件

    添加eureka client配置

    eureka:
      client:
        #表示是否将自己注册进Eurekaserver默认为true。
        register-with-eureka: true
        #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
        fetchRegistry: true
        service-url:
          defaultZone: http://localhost:7001/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    (3)主启动类添加Eureka注解
    package com.heng;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8001.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (4)测试运行

    启动cloud-provider-8001payment和cloud-eureka-server7001工程
    浏览器访问http://localhost:7001/
    在这里插入图片描述

    三、Eureka 集群实操

    1.Eureka运行原理

    在这里插入图片描述
    由架构图我们可以发现,可以实现注册中心集群和某个微服务集群

    为什么要搭建集群环境?
    只有一个注册中心,当它出现故障会导致整个服务环境不可用
    怎么搭建集群环境?
    相互注册,相互守望

    2.修改映射在本地模拟Eureka集群

    (1)找到C:\Windows\System32\drivers\etc路径下的hosts文件

    在这里插入图片描述
    点击进去发现是空白,而且无法保存—>权限不足

    在这里插入图片描述
    修改 hosts文件并保存
    在这里插入图片描述

    通过ping 测试本地映射
    在这里插入图片描述

    (2)创建cloud-eureka-server7002工程

    参考cloud-eureka-server7001上面的创建过程

    (3)修改两个注册中心的配置文件
    • 修改cloud-eureka-server7001配置文件
    server:
      port: 7001
    
    eureka:
      instance:
        hostname: eureka7001.com    #eureka服务端的实例名称
      client:
        #false表示不向注册中心注册自己。
        register-with-eureka: false
        #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          #设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
          #相互注册,集群指向其他eureka
          defaultZone: http://eureka7002.com:7002/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 修改cloud-eureka-server7002配置文件
    server:
      port: 7002
    
    eureka:
      instance:
        hostname: eureka7002.com #eureka服务端的实例名称
      client:
        #false表示不向注册中心注册自己。
        register-with-eureka: false
        #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (4)测试运行

    启动两个注册中心
    浏览器 输入http://eureka7002.com:7002;
    在这里插入图片描述
    http://eureka7001.com:7001
    在这里插入图片描述

    3.支付微服务注册Eureka集群

    • 只需要将支付服务的配置文件defaultZone改成两个注册中心的地址
    eureka:
      client:
        #表示是否将自己注册进Eurekaserver默认为true。
        register-with-eureka: true
        #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
        fetchRegistry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 测试:先启动两个注册中心,再启动支付服务
      在这里插入图片描述
      可以发现两个注册中心都存在支付服务

    4.支付微服务集群配置

    参考cloud-provicer-8001payment支付服务,创建cloud-provicer-8002payment支付服务
    修改两个支付服务的控制层,通过查询端口号,我们可以知道调用了那个支付服务

    public class PaymentController {
        @Value("${server.port}")
        private String serverPort;//添加serverPort
    
        @Resource
        private PaymentService paymentService;
        @PostMapping(value = "/payment/create")
        public CommonResult create(@RequestBody Payment payment){
            int i = paymentService.create(payment);
            log.info("*****插入结果:"+i);
            if(i>0){
                return new CommonResult(200,"插入数据成功"+serverPort,i);
            }else {
                return new CommonResult(444,"插入数据失败",null);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注意:import org.springframework.beans.factory.annotation.Value;
    增加订单微服务模块

    • 建module
    • 改pom
    • 写yml
    • 主启动
    • 控制层
    public class OrderController
    {
        public static  final  String PAYMENT_URL="http://CLOUD-PAYMENT-SERVICE";
        
        @Resource
          private RestTemplate restTemplate;
    
        @GetMapping("/consumer/payment/create")
        public CommonResult<Payment> create(Payment payment){
            return  restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
        }
    
        @GetMapping("/consumer/payment/get/{id}")
        public  CommonResult<Payment> getPayment(@PathVariable("id") Long id){
            return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 通过创建RestTemplate对象,远程访问Http服务
    package com.heng.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class ApplicationContextConfig {
    
        @Bean
        @LoadBalanced   //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
        public RestTemplate getRestTemplate(){
            return  new RestTemplate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    控制层代码:

    测试:
    先启动两个注册中心,再启动两个支付服务,最后启动订单服务
    在这里插入图片描述
    在这里插入图片描述
    浏览器访问:http://localhost/consumer/payment/get/31
    在这里插入图片描述
    再次刷新后
    在这里插入图片描述

    四、Eureka 自我保护机制

    1. 自我保护机制概述

    在这里插入图片描述
    如上图红色的字体所示,说明了Eureka 进入了保护模式

    什么是自我保护机制?

    默认情况下EurekaClient每30秒向EurekaServer端发送心跳包
    如果Eureka在server端在一定时间内(默认90秒)没有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务
    如果网络不通或延迟导致EurekaClient出现宕机,此时如果换做别的注册中心如果一定时间内没有收到心跳会将剔除该服务,这样就出现了严重失误,因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的

    2. 如何禁止自我保护

    默认自我保护机制是开的

    • 关闭cloud-eureka-server7002注册中心的自我保护机制(修改配置)
    eureka:
      ...
      server:
        #关闭自我保护机制,保证不可用服务被及时踢除
        enable-self-preservation: false
        #每隔多久ms触发一次服务剔除
        eviction-interval-timer-in-ms: 2000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    出现以下红字,说明自我保护机制已经关闭
    在这里插入图片描述

    • 支付服务8002客户端设置(修改配置)
    eureka:
      ...
      instance:
        #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
        lease-renewal-interval-in-seconds: 1
        #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
        lease-expiration-duration-in-seconds: 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 测试
      先启动7002注册中心,再启动8002服务
      然后关闭8002服务,发现8002服务马上就被删除了

    五、微服务信息完善

    1.服务名称修改(改配置)

    eureka:
       ...
      instance:
        instance-id: payment8002 
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    2.访问信息有ip提示(改配置)

    eureka:
       ...
      instance:
        instance-id: payment8002 
        prefer-ip-address: true  #添加
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    六、服务发现Discovery

    对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息

    • 修改8002控制层(添加代码)
      import org.springframework.cloud.client.discovery.DiscoveryClient;
        @Resource
        private DiscoveryClient discoveryClient;
    
        @GetMapping(value = "/payment/discovery")
        public Object discovery()
        {
            //获得注册中心有哪几个微服务注册进来了
            List<String> services = discoveryClient.getServices();
            for (String element : services) {
                log.info("*****element: "+element);
            }
            //具体的微服务下有那几个
            List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
            for (ServiceInstance instance : instances) {
                log.info(instance.getServiceId()+"\t"+"主机名称:"+instance.getHost()+"\t"+"端口号:"+instance.getPort()+"\t"+"url:"+instance.getUri());
            }
            return this.discoveryClient;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 修改启动类(增加注解)
    @SpringBootApplication
    @EnableEurekaClient
    @EnableDiscoveryClient  #增加的
    public class PaymentMain8002 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8002.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

  • 相关阅读:
    港陆证券:服装家纺公司上半年投资并购力度加大
    Vue 的h()
    【微信小程序开发】宠物预约医疗项目实战-登录实现
    91. 解码方法
    pandas合并操作
    Linux安装MySQL8.0并部署数据库教程
    信号源是什么 都有什么功能
    了解 Android Kotlin 中 DataStore 的基本概念以及为什么应该停止在 Android 中使用 SharedPreferences
    spring boot 自定义配置文件并提示及NestedConfigurationProperty注解作用
    利用pycharm调试ssh远程程序,并实时同步文件
  • 原文地址:https://blog.csdn.net/qq_45637894/article/details/126210995