Eureka(服务注册和发现)——Eureka的简介和原理 & Eureka的使用和分析 & 心跳续约策略,服务的下线和剔除

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

  • 服务注册中心
    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server。
  • 服务提供者
    提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的spring-provider。
  • 服务消费者
    消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中
    就是我们实现的spring-consumer。

有趣故事

Eureka的故事来源于人人追求真善美的古希腊,“Eureka”是希腊语,意思是“我发现了!”

这个有魔力的单词是来源于阿基米德。在公元前200多年,他在洗澡时发现了证明王冠是否纯金的方法(黄金密度),他激动地一边大喊“Eureka!”一边跳出澡盆奔去王宫,连衣服都忘了穿。后来人们用Eureka这个词来形容洞察浮现的瞬间。

SMS、库存、积分服务器,服务迁移变更等需要修改相应的URL地址,怎么不修改URL地址?

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

这就好比是 网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦(没有人告诉哪些车私家车可以拉人),而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。

此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息(联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。

此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到你面前,为你服务,完美!

Eureka做什么?

Eureka就好比是滴滴中心,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。

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

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

Eureka是啥?

Eureka简介

在这里插入图片描述

Spring Cloud Eureka 是对Netflix公司的Eureka的二次封装,它实现了服务治理的功能,Spring Cloud Eureka提供服务端与客户端,服务端即是Eureka服务注册中心,客户端完成微服务向Eureka服务的注册与发现。服务端和客户端均采用Java语言编写。

在这里插入图片描述

一个消费者和一个生产者

在这里插入图片描述

多个消费者与多个生产者

在这里插入图片描述

下图显示了Eureka Server与Eureka Client的关系

在这里插入图片描述

  • Eureka Server是服务端,负责管理各个微服务结点的信息和状态。
  • 在微服务上部署Eureka Client程序,远程访问Eureka Server将自己注册在Eureka Server。
  • 微服务需要调用另一个微服务时从Eureka Server中获取服务调用地址,进行远程调用。
原理
  • 服务提供方启动后将注册到注册中心,提供IP, 名字,什么服务等信息,
  • 服务调用方作为客户端注册到注册中心后,拉取注册中心的服务列表,在通过负载均衡调用对应的服务提供方。
  • 注册中心可以建立集群,生成多台eureka,注册中心为了监测各个服务的心跳,将在每30S 向所注册的服务发起请求判断
  • 服务是否挂掉,如果挂掉90S后将会将服务从注册中心剔除。
  • 一个服务可以监测多台服务实例,从而可实现均衡负载。

Eureka使用Hello案例

注册中心Eureka

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

eureka的配置文件

在这里插入图片描述

server:
  port: 9001 # eureka默认端口号为8761
eureka:
  client:
    # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址
    service-url:
      defaultZone: http://127.0.0.1:${server.port}/eureka
    # 不把自己注册到eureka服务列表
    register-with-eureka: false
    # 拉取eureka服务信息
    fetch-registry: false #false表示自己就是注册中心,不需要从注册中心获取注册列表信息
  instance:
    #客户端在注册时使用自己的IP而不是主机名
    prefer-ip-address: true
    # 实例id
    instance-id: ${spring.cloud.ip-address}:${spring.application.name}:${server.port}

logging:
  level:
    root: debug

配置说明:

register-with-eureka: false false表示不向注册中心注册自己

fetch-registry: false false表示自己就是注册中心,不需要从注册中心获取注册列表信息

service-url 设置eureka server交互的地址查询服务和注册服务都需要用到这个地址(单机用)

在这里插入图片描述

主启动类

在eureka-server的主启动类上开启eureka服务**@EnableEurekaServer**

在这里插入图片描述

package com.tianju.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer // 声明当前springboot应用是一个eureka服务中心
public class EurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApp.class);
    }
}


浏览器访问

启动eureka-server子项目,在浏览器上访问localhost:9001

在这里插入图片描述

查看日志

在这里插入图片描述

搭建生产者Provider

引入依赖

在这里插入图片描述

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

<!-- 在provider的pom文件中添加监控依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

配置yml文件

在这里插入图片描述

server:
  port: 10010

eureka:
  client: #客户端注册到eureka列表中
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka
  instance:
    prefer-ip-address: true #显示访问url 客户端在注册时使用自己的IP而不是主机名
# # 实例id
# instance-id: ${spring.cloud.ip-address}:${spring.application.name}:${server.port}
    instance-id: provider-10010  #注册中心显示出来的微服务名称

# 应用名称
spring:
  application:
    name: springCloud-provider

info:
  app.name: SpringCloud
  company.name: tianju
  build.artifactId: $project.artifactId$
  build.version: $project.version$

在这里插入图片描述

主启动类

在这里插入图片描述

package com.tianju.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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


在这里插入图片描述

@EnableEurekaClient和@EnableDiscoveryClient区别

在使用Spring Cloud feign使用中在使用服务发现的时候提到了两种注解:
一种为@EnableDiscoveryClient;
一种为@EnableEurekaClient,用法上基本一致

在这里插入图片描述

spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等等),

@EnableDiscoveryClient基于spring-cloud-commons;
@EnableEurekaClient基于spring-cloud-netflix。

其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient, 如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

注解@EnableEurekaClient上有@EnableDiscoveryClient注解,可以说基本就是EnableEurekaClient有@EnableDiscoveryClient的功能,另外上面的注释中提到,其实@EnableEurekaClient注解就是一种方便使用eureka的注解而已,可以说使用其他的注册中心后,都可以使用@EnableDiscoveryClient注解,但是使用@EnableEurekaClient的情景,就是在服务采用eureka作为注册中心的时候,使用场景较为单一。

查看日志

在这里插入图片描述

修改配置信息,变成了20s

lease-renewal-interval-in-seconds: 20 #心跳时间

在这里插入图片描述

server:
  port: 10010

eureka:
  client: #客户端注册到eureka列表中
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka
  instance:
    prefer-ip-address: true #显示访问url 客户端在注册时使用自己的IP而不是主机名
# # 实例id
# instance-id: ${spring.cloud.ip-address}:${spring.application.name}:${server.port}
    instance-id: provider-10010  #注册中心显示出来的微服务名称
    lease-renewal-interval-in-seconds: 20   #心跳时间
    lease-expiration-duration-in-seconds: 60 #下线时间

# 应用名称
spring:
  application:
    name: springCloud-provider

info:
  app.name: SpringCloud
  company.name: tianju
  build.artifactId: $project.artifactId$
  build.version: $project.version$

搭建消费者consumer

引入依赖配置等雷同

在这里插入图片描述

注册到eureka

在这里插入图片描述

主启动类

在这里插入图片描述

package com.tianju.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

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

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}


在生产端提供controller

在这里插入图片描述

在消费端调用生产者

在这里插入图片描述

package com.tianju.consumer.controller;

import com.netflix.appinfo.InstanceInfo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/consumer")
@Slf4j
public class ConsumerController {

    @Resource
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/getId/{id}")
    public String getMsg(@PathVariable("id") String id) {
        List<ServiceInstance> instances = discoveryClient.getInstances("springCloud-provider");
        ServiceInstance instance = instances.get(0);
        String host = instance.getHost();
        int port = instance.getPort();
        log.debug("消费者拼出路径+端口:"+ host+":"+port);

        // 获取ip和端口信息,拼接成服务地址
        String baseUrl = "http://" + instance.getHost() + ":" +
                instance.getPort() + "/provider/get/" + id;
        String consumer = restTemplate.getForObject(baseUrl, String.class);

        log.debug("采用restTemplate调用生产者:"+baseUrl);
        return "消费者调用生产者获得消息:"+consumer;
    }
}


在这里插入图片描述

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

plate调用生产者:"+baseUrl);
return “消费者调用生产者获得消息:”+consumer;
}
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/c8d067e94e82495d8e4f520e12467021.png)


[外链图片转存中...(img-0Evh6Wwc-1715252694396)]
[外链图片转存中...(img-9AoNLjNc-1715252694396)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值