Spring Cloud 学习笔记:Eureka 服务注册与发现

服务治理

在传统的 rpc 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。

服务注册与发现

在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址、通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者)以该别名的方式去注册中心获取到实际的服务通讯地址,然后再实现本地 RPC 远程调用。

Eureka

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

  • Eureka Server:提供服务的注册于发现
  • Service Provider:将自身服务注册到Eureka中,从而使消费方能够找到
  • Service Consumer:服务消费方从Eureka中获取注册服务列表,从而找到消费服务

在这里插入图片描述

Eureka Server & Eureka Client

Eureka 包含两个组件:Eureka ServerEureka Client
Eureka Server 提供服务注册服务,各个节点启动后会在 Eureka Server 中进行注册,这样 Eureka Server 中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client 是一个 Java 客户端, 用于简化 Eureka Server 的交互,客户端同时也具备一个内置的,使用轮负载算法的负载均衡器。在应用启动后将会向 Eureka Server 发送心跳(默认周期为30秒)。如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳, Eureka Server 将会从服务注册表中把这个服务节点移除掉(默认周期为90秒)。

Spring Cloud 整合

新建module cloud-eureka-server7001
pom.xml

<dependencies>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--引入自己定义的api通用包,可以使用payment支付Entity-->
        <dependency>
            <groupId>com.hangzhou.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--boot web actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--一般通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

application.yml

server:
  port: 7001

eureka:
  instance:
    hostname: eureka7001.com #eureka服务端的实例名称
  client:
    #false表示不向注册中心注册自己
    register-with-eureka: false
    #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka/
  server:
    # 关闭自我保护机制,保证不可用服务及时被清除
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000

EurekaMain7001

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

启动服务
在这里插入图片描述

服务注册

修改 module cloud-provider-payment8001 & cloud-consumer-order80
pom.xml

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

application.yml

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

在主方法 Main 中添加注解 @EnableEurekaClient

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

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

启动服务
在这里插入图片描述

Eureka集群

试想当注册中心只有一个的时候,一旦出现故障会导致整个微服务环境不可用。而解决办法就是搭建 Eureka 注册中心集群,实现负载均衡和故障容错。Eureka集群的原理:互相注册相互守望
在这里插入图片描述

集群搭建

修改配置文件 hosts
在这里插入图片描述
新建 module cloud-eureka-server7002
application.yml

server:
  port: 7002

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

EurekaMain7002

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

启动服务
在这里插入图片描述

服务注册进 Eureka 集群

修改各个服务的 application.yml 文件

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

页面显示
在这里插入图片描述

服务集群注册进 Eureka 集群

新建 module cloud-provider-payment8002
在这里插入图片描述
在两个 module 的 controller 层添加端口号的加以区别:
在这里插入图片描述
页面显示
在这里插入图片描述
但是通过80去访问却发现 servicePort 一直都是8001,注册进来的8002却没有调用到
在这里插入图片描述
这是因为在80端的代码服务端口号是写死的,将它改成微服务名称
在这里插入图片描述
修改完成后再访问却返回错误页面
在这里插入图片描述
因为现在对外暴露的不再是地址和端口,只认微服务名称了,可是微服务并不知道下面有几个,找不到这个主机名称,需要使用@LoadBalanced 注解开启 RestTemplate 负载均衡功能(Ribbon 负载均衡功能)

@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

再通过80端口去访问服务发现 servicePort 是轮循访问
在这里插入图片描述
在这里插入图片描述

自我保护机制

在这里插入图片描述
默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与 Eureka 之间无法正常通行,以上行为可能变得非常危险了。因为微服务本身其实是健康的,此时本不应该注销这个服务。Eureka 通过自我保护机制来解决这个问题。当 Eureka Server 节点在短时间内丢失过多客户端时(可能发生了网络分区故障), 那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server 就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该 Eureka Server 节点会自动退出自我保护模式。
在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该 Eureka Server 节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息也不盲目注销任何可能健康的服务实例。一句话:好死不如赖活着。
综上,自我保护模式是一种应对网络异常的安全保护措施。即使某时刻某一个微服务不可以用了 ,eureka 不会立刻清理,依旧会对该微服务的信息进行保存。使用自我保护模式,可以让Eureka集群更加的健壮和稳定。
在 Spring Cloud 中, service 端可以使用禁用自我保护模式(不推荐关闭自我保护机制)。

eureka.server.enable-self-preservation=true

页面显示
在这里插入图片描述
client 端可以设置相关信息Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)

eureka.instance.lease-renewal-interval-in-seconds=30

Eureka 服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时剔除服务

eureka.instance.lease-expiration-duration-in-seconds=90

actutor 微服务信息完善

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
微服务名称修改

在服务的 application.yml 文件中修改

eureka:
    instance:
    instance-id: payment8001

eureka:
    instance:
    instance-id: payment8002

在这里插入图片描述

访问路径显示 IP 地址

在这里插入图片描述
application.yml

eureka:
    instance:
    prefer-ip-address: true  #访问路径可以显示IP地址

在这里插入图片描述

微服务健康

在这里插入图片描述

Discovery 服务发现

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

@RestController
@Slf4j
public class PaymentController {
/**
 * 服务发现 获取服务信息
 */
@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-PROVIDER-SERVICE");
    for(ServiceInstance instance : instances){
        log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
    }
    return this.discoveryClient;
}
}

在 Main8001 主程序开启 @EnableDiscoveryClient 注解

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

url 页面显示:
在这里插入图片描述
控制台输出:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值