Spring Cloud 之注册中心 Eureka 精讲

🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝

🍓 更多文章请点击
在这里插入图片描述在这里插入图片描述

文章目录

  • 一、Eureka简介
  • 二、 Eureka 注册中心
    • Eureka的作用-图解
    • 2.1 首先基于Spring Boot创建父工程
      • 2.1.1 需要注意(重要)
      • 2.1.2 本项目引入主要配置
        • 第一种 (选择一种即可,区别不大)
        • 第二种
    • 2.2 搭建Eureka-Server
    • 2.3 搭建Eureka-Client(服务注册)
    • 2.4 服务拉取准备工作
      • 2.4.1 需求
      • 2.4.2 数据库表数据展示
      • 2.4.3 `消费者端`
      • 2.4.4 `提供者端`
      • 2.4.5 注册成功
  • 三、服务启动测试
    • 3.1 原始http全路径调用 及 存在问题
    • 3.2 使用Eureka注册中心的服务名调用
  • 四、总结
    • 4.1 Eureka的作用
    • 4.2 在Eureka架构中,微服务角色有两类:

在这里插入图片描述

一、Eureka简介

Spring Cloud官网:https://spring.io/projects/spring-cloud
Eureka官网:https://github.com/Netflix/eureka

Spring Cloud 是目前用于开发微服务的主流框架之一,我们都知道在微服务架构中最为基础、核心的模块,就是服务注册与发现。

Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现 服务注册和发现Eureka Server 作为 服务注册中心,系统中的 其他微服务,使用 Eureka 的 客户端 连接到 Eureka Server,并通过 心跳连接 检测服务的 存活状态

Eureka 包含两个组件:Eureka ServerEureka Client

  • Eureka Server: 作为 服务注册中心,提供 服务注册和发现,提供服务注册服务,各个节点启动后,会在 EurekaServer 中进行注册,这样 EurekaServer 中的服务注册表中将会存储所有可用服务节点的信息。

  • Eureka Client: 所有注册到 服务中心 的服务。是一个 Java 客户端,用于简化 Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询 (round-robin) 负载算法的负载均衡器。在应用启动后,将会向 Eureka Server 发送心跳 (默认周期为 30 秒)。

    • Service Provider: 把 自身的服务 注册到 Eureka Server,从而使 服务消费方 能够找到。
    • Service Consumer: 从 Eureka Server 获取 服务注册列表,从而能够 消费服务。

二、 Eureka 注册中心

在微服务架构中往往会有一个注册中心,每个微服务都会向注册中心去注册自己的地址及端口信息,注册中心维护着服务名称与服务实例的对应关系。首先我们注册中心服务端:eureka-server,这必须是一个独立的微服务。下面我们来搭建搭建 eureka-server。

原始http服务调用 -存在问题:

  • 如果有多个服务提供者,消费者如何选择?
  • 消费者如何获取服务提供者地址信息?
  • 如何知晓服务提供者是否健康?

请看下图

(纯手工绘制有点瑕疵)Eureka的作用 图解:

Eureka的作用-图解

在这里插入图片描述

2.1 首先基于Spring Boot创建父工程

以Maven模块化项目方式创建,便于各个微服务的项目管理。
在这里插入图片描述

2.1.1 需要注意(重要)

来自Spring Cloud官方文档 :https://spring.io/projects/spring-cloud

概述了Spring Cloud的版本与Spring Boot的版本对应关系,需要注意最新更新可查看官方文档

在这里插入图片描述

2.1.2 本项目引入主要配置

父项目Pom文件

可以看到下文中:Spring Boot的版本是2.7.1
因此根据上图Spring Cloud 的版本为:2021.0.1
在这里插入图片描述

第一种 (选择一种即可,区别不大)


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/>
    </parent>
    
	<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <hutool.version>5.8.2</hutool.version>
    </properties>
    
    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <!-- springCloud -->
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

第二种

不引入parent也可以这样配置


	<properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.7.1</spring-boot.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <hutool.version>5.8.2</hutool.version>
    </properties>
    
    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    
 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
 </dependencyManagement>

两种都可以

2.2 搭建Eureka-Server

  1. 在父工程基础上 创建eureka-server模块`
  2. 引入spring-cloud-starter-netflix-eureka-server依赖
        <!--eureka 服务端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
  1. 在启动类上添加@EnableEurekaServer注解
  2. 添加配置
server:
  port: 10086
spring:
  application:
    name: eureka-server
  main:
    allow-bean-definition-overriding: true
eureka:
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:10086/eureka/
  #  register-with-eureka: false # 不注册自己
  #  fetch-registry: false #不拉取服务

  1. 启动服务
    然后访问:http://localhost:10086/
    看到如下页面则成功
    在这里插入图片描述

2.3 搭建Eureka-Client(服务注册)

将provider-service注册到Eureka-Server中步骤如下:

  1. 在父工程基础上 创建provider-service模块(服务提供者)
  2. 引入spring-cloud-starter-netflix-eureka-client依赖,注意后缀是client
        <!--eureka 客户端 -->
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
  1. 添加配置
server:
  port: 20086
spring:
  application:
    name: provider-service
  main:
    allow-bean-definition-overriding: true
eureka:
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:10086/eureka/
  1. 同理创建consumer-service模块(服务消费者)

  2. 最终项目结构如下图所示:

    我这里创建了个common公共包,无要求,非必须
    在这里插入图片描述

2.4 服务拉取准备工作

2.4.1 需求

需求:根据订单id查询订单的同时查询对应用户信息一起返回

消费者中提供订单信息 提供者提供用户信息 数据在各自对应数据库中

2.4.2 数据库表数据展示

order订单表
在这里插入图片描述
用户表
在这里插入图片描述

2.4.3 消费者端

  1. controller
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    /**
     * 消费者
     */
    @Autowired
    private ConsumerService consumerService;
    
    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        return consumerService.queryOrderById(orderId);
    }
}
  1. service
public interface ConsumerService {

    /**
     * 根据id查询订单并返回
     */
    Order queryOrderById(Long orderId);
}

  1. impl
@Service
public class ConsumerServiceImpl implements ConsumerService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;
    /**
     * 根据id查询订单并返回
     */
    @Override
    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);

        //2远程查询用户信息
        String url="http://localhost:20086/provider/"+order.getUserId();
        
        //2. 发起调用
        User user = restTemplate.getForObject(url, User.class);
        //3. 存入order
        order.setUser(user);

        // 4.返回
        return order;
    }
}

  1. mapper
@Mapper
public interface OrderMapper {

    @Select("select id, name, num, user_id userId, price from `order` where id = #{id}")
    Order findById(Long orderId);
}

  1. 启动类,并配置RestTemplate
@SpringBootApplication
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    /**
     * 没有实例化RestTemplate时,初始化RestTemplate
     * @return
     */
    @ConditionalOnMissingBean(RestTemplate.class)
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

2.4.4 提供者端

  1. controller
@RestController
@RequestMapping("/provider")
public class ProviderController {

    @Autowired
    private ProviderService providerService;


    /**
     * 根据id查询用户信息
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return providerService.queryById(id);
    }

}
  1. service
public interface ProviderService {

    /**
     * 根据id查询用户信息
     */
    User queryById(Long id);
}


  1. impl
@Service
public class ProviderServiceImpl implements ProviderService {

    @Autowired
    private UserInfoMapper userMapper;

    /**
     * 根据id查询用户信息
     */
    @Override
    public User queryById(Long id) {
        return userMapper.findById(id);
    }
}
  1. mapper
@Mapper
public interface UserInfoMapper {
    
    @Select("select * from user where id = #{id}")
    User findById(@Param("id") Long id);
}
  1. 启动类
@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

2.4.5 注册成功

在这里插入图片描述

三、服务启动测试

3.1 原始http全路径调用 及 存在问题

查看上文代码消费者端是基于全路径http://localhost:20086/provider/1 调用

		//2远程查询用户信息
        String url="http://localhost:20086/provider/"+order.getUserId();

成功调用如下图
在这里插入图片描述

存在问题:

  • 如果有多个服务提供者,消费者如何选择?
  • 消费者如何获取服务提供者地址信息?
  • 如何知晓提供者是否健康 ?

可参考上文------Eureka的作用 图解

3.2 使用Eureka注册中心的服务名调用

这是成功注册的服务

基于服务名称获取服务列表,然后对服务列表做负载均衡

在这里插入图片描述

  1. 服务名代替ip,端口

  2. 使用provider-service(自己配置的服务名)代替localhost:20086

           //2远程查询用户信息
            String url="http://provider-service/provider/"+order.getUserId();
    
    
  3. 在服务消费者的启动类的RestTemplate添加@LoadBalanced负载均衡注解

    负载均衡详解后续文章中更新

        /**
         * 没有实例化RestTemplate时,初始化RestTemplate
         * @return
         */
        @ConditionalOnMissingBean(RestTemplate.class)
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    

测试结果成功
在这里插入图片描述

四、总结

4.1 Eureka的作用

  • 消费者该如何获取服务提供者具体信息?

    • 服务提供者启动时向eureka注册自己的信息
    • eureka保存这些信息
    • 消费猪根据服务名称向eureka拉取提供者信息
  • 如果有多个服务提供者,消费者该如何选择?

    • 服务消费者利用负载均衡算法,从服务列表中选择一个
  • 消费者如何感知服务提供者健康状态?

    • 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
    • eureka会更新记录服务列表信息,心跳不正常会被剔除
    • 消费者就可以拉取到最新的信息

4.2 在Eureka架构中,微服务角色有两类:

  • EurekaServer: 服务端,注册中心
    • 记录服务信息
    • 心跳监控
  • Eurekaclient:客户端
    • Provider: 服务提供者,例如案例中的provider-service
      • 注册自己的信息到EurekaServer
      • 每隔30秒向EurekaServer发送心跳
    • consumer:服务消费者,例如案例中的 consumer-service
      • 根据服务名称从EurekaServer拉取服务列表
      • 基于服务列表做负载均衡,选中一个微服务后发起远程调用

在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/33491.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx配置开机启动(Windows环境)

文章目录 1、下载nginx&#xff0c;并解压2、配置nginx.conf&#xff0c;并启动Nginx3、开机自启动 1、下载nginx&#xff0c;并解压 2、配置nginx.conf&#xff0c;并启动Nginx 两种方法&#xff1a; 方法一&#xff1a;直接双击nginx.exe&#xff0c;双击后一个黑色弹窗一闪…

ELK日志收集系统集群实验

ELK日志收集系统集群实验 目录 一、实验拓扑 二、环境配置 三、 安装node1与node2节点的elasticsearch 1. 安装 2.配置 3.启动elasticsearch服务 4.查看节点信息 四、在node1安装elasticsearch-head插件 1.安装node 2.拷贝命令 3.安装elasticsearch-head 4.修改el…

【机器学习】十大算法之一 “PCA”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

【夜深人静学数据结构与算法 | 第十一篇】枚举算法

目录 前言&#xff1a; 枚举算法&#xff1a; 优点&#xff1a; 枚举算法的种类&#xff1a; 枚举算法案例&#xff1a; 343. 整数拆分 - 力扣&#xff08;LeetCode&#xff09; 12. 整数转罗马数字 - 力扣&#xff08;LeetCode&#xff09; 总结&#xff1a; 前言&…

【手撕算法|动态规划系列No.1】leetcode1137. 第 N 个泰波那契数

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

exe的python文件打包

【步骤01】 【在命令行中用pip工具安装Pyinstaller模块】 pip install Pyinstaller 步骤02】 【切换命令行的路径到你要打包的Python源文件的文件夹路径下】 【下面是我要打包的Python源文件&#xff08;散点坐标图.py&#xff09;及其文件夹路径】 【步骤03】 【执行Pyi…

使用SSH远程直连Docker容器

文章目录 1. 下载docker镜像2. 安装ssh服务3. 本地局域网测试4. 安装cpolar5. 配置公网访问地址6. SSH公网远程连接测试7.固定连接公网地址8. SSH固定地址连接测试 转载自cpolar极点云文章&#xff1a;SSH远程直连Docker容器 在某些特殊需求下,我们想ssh直接远程连接docker 容器…

SpringBoot 实现 elasticsearch 查询操作(RestHighLevelClient 的案例实战)

文章目录 1. 环境准备1. 查询全部2. 根据 name 查询 match 分词查询3. 根据 name 和 品牌查询 multiMatch 分词查询4. 根据 brand 查询 match 分词查询5. 按照价格 范围查询6. 精确查询7. boolQuery8. 分页9. 高亮查询9. 公共解析 上一节讲述了 SpringBoot 实现 elasticsearch …

【图像处理OpenCV(C++版)】——5.3 图像平滑之均值平滑(滤波)

前言&#xff1a; &#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; &#x1f31f;&#x1f31f;&#x1f31f; 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义&#xff0c;适用于平时学习、工作快…

Linux终端与进程的关系 ( 1 ) -【Linux通信架构系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the…

C高级重点

1、请简要描述一下Linux文件系统的层级结构&#xff0c;包括不同目录的作用和功能。 Linux的文件系统结构是一个倒插树结构&#xff0c;所有的文件都从根目录出发。 2、find指令的用途 find 查找的路径 -name 文件名 ----->在指定路径下&#xff0c;以文件名为条件查找文…

总结vue3 的一些知识点:​Vue3 起步

目录 引言 Vue3 混入 实例 选项合并 实例 实例 全局混入 实例 Vue3 起步 Vue 3.0 实例 data 选项 实例 方法 总结 引言 Vue 进阶系列教程将在本号持续发布&#xff0c;一起查漏补缺学个痛快&#xff01;若您有遇到其它相关问题&#xff0c;非常欢迎在评论中留言讨…

Ubuntu 20.04.02 LTS安装virtualbox7.0

ubuntu22.04的软件仓库也有virtualbox&#xff0c;不过版本较老。 使用安装命令&#xff1a;sudo apt install virtualbox 如果想要安装最新版&#xff0c;那么需要去官网下载deb包或者使用官方的仓库。 这里采用安装Oracle官方仓库的方法。 执行如下命令&#xff1a; wge…

HTTP调用:你考虑到超时、重试、并发了吗?

今天&#xff0c;我们一起聊聊进行 HTTP 调用需要注意的超时、重试、并发等问题。 与执行本地方法不同&#xff0c;进行 HTTP 调用本质上是通过 HTTP 协议进行一次网络请求。网络请求必然有超时的可能性&#xff0c;因此我们必须考虑到这三点&#xff1a; 首先&#xff0c;框架…

抖音本地生活团购服务商

抖音本地生活团购服务商市场前景非常广阔。随着移动互联网的普及和人们对本地生活服务需求的增加&#xff0c;本地生活团购行业已成为一个快速增长的市场。而抖音平台拥有庞大的用户基础和强大的社交媒体传播力&#xff0c;为本地生活团购服务商提供了巨大的发展机遇。 抖音…

【博客674】警惕Prometheus 中的重复样本和无序时间戳错误

警惕Prometheus 中的重复样本和无序时间戳错误 1、场景 您的 Prometheus 服务器日志中是否遇到过以下错误&#xff1f; "Error on ingesting out-of-order samples" "Error on ingesting samples with different value but same timestamp" "dupli…

图解CNN中的卷积(卷积运算、池化、Padding、多通道的卷积)

文章目录 卷积操作池化Padding对多通道&#xff08;channels&#xff09;图片的卷积套上激活函数是什么样的参考&#xff1a; 卷积层是深度学习神经网络中经常使用的一种层。它通过卷积运算来提取输入的特征&#xff0c;常用于图像、语音等信号处理任务中。 卷积层有以下几个参…

探索iOS之Metal编程指南

iOS推出Metal渲染库为了取代OpenGL。Metal有自己的Shader语言&#xff0c;渲染效率比OpenGL高。在这里我们一起探索&#xff1a;Metal使用C限制、预处理定义、动态链接配置、GPU编译配置、设备坐标系、视口坐标系、纹理坐标系、矢量类型、矩阵类型、采样器状态、矩阵相乘。 1、…

第 107 场LeetCode双周赛

A 最大字符串配对数目 显然各字符串对 间匹配的先后顺序不影响最大匹配数目, 可以从后往前遍历数组, 判断前面是否有和当前末尾构成匹配的. class Solution { public:int maximumNumberOfStringPairs(vector<string> &words) {int res 0; while (words.size…

使用 Jetpack Compose 构建 RadioButton

欢迎阅读本篇关于使用 Jetpack Compose 构建 RadioButton&#xff08;单选按钮&#xff09;的博客。Jetpack Compose 是 Google 发布的现代化 UI 工具包&#xff0c;用于构建 Android 界面。它的声明式设计使得 UI 开发更加简洁直观。 一、什么是 RadioButton&#xff1f; Rad…