Eureka 服务注册和服务发现的使用

1. 父子工程的搭建

首先创建一个 Maven 项目,删除 src ,只保留 pom.xml

然后来进行 pom.xml 的相关配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules><module>order-service</module><module>product-service</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><java.version>17</java.version><mybatis.version>3.0.3</mybatis.version><mysql.version>8.0.33</mysql.version><spring-cloud.version>2022.0.3</spring-cloud.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>${mybatis.version}</version><scope>test</scope></dependency></dependencies></dependencyManagement>
</project>

在上面的配置中,使用 properties 来进行版本号的统一管理,使用 dependencyManagement 来管理依赖,并通过<packaging>pom</packaging>来生命父工程的打包方式为 pom

dependencyManagement 和 dependencies

  1. dependencies:将依赖的 jar 包添加到父项目的 dependencies 部分时,这些依赖会被父项目及其子项目继承,子项目无需额外操作即可自动包含这些依赖。
  2. dependencyManagement: 仅用于声明依赖,不会将 jar 包引入到父项目或子项目中。当子项目需要使用在父项目 dependencyManagement 中声明的依赖时,需在子项目中显式声明该依赖。子项目不指定版本号时,会从父项目的 dependencyManagement 部分读取相应依赖的版本号;如果子项目指定了版本号,就使用子项目中指定的版本号,不使用父项目声明的版本。

关于打包方式:父项目的打包方式通常应为 pom,而不是 jarwar,因为父项目主要起依赖管理和项目聚合的作用,不包含需要部署或运行的代码。

2. 子工程的搭建

在父工程右键选择新建一个 Module,

创建时 Parent 默认为父工程

接着配置子工程的项目依赖,由于父工程已经对版本号进行了统一管理,直接进行以下配置即可

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/**</include></includes></resource></resources>
</build>

在一个父项目中搭建两个子工程

然后在这两个子工程中分别写一个查询接口

@RequestMapping("/{orderId}")
public OrderInfo getOrderById(@PathVariable("orderId") Integer orderId){return orderService.selectOrderById(orderId);
}
@RequestMapping("/{productId}")
public ProductInfo selectProductById(@PathVariable("productId") Integer productId) {return productService.selectProductById(productId);
}

3. 远程调用

如果此时需要实现一个查询订单的功能,查询结果中需要包含商品信息,由于上面的两个子工程现在是分开的,并不是像之前一样写在一个工程中,那么现在就不能直接调用查询的结果了

可以联想一下前端调用后端获取资源的方式,就是通过发送一个 http 请求来获取的,那么后端之间调用也可以使用这种方式,order-service 服务向 product-service 服务发送一个 http 请求,把得到的返回结果和订单结果合并在一起返回给调用方,有许多方式可以构造一个 http 请求,这里采用 Spring 提供的 RestTemplate 来实现一下:

RestTemplate 是 Spring 提供的,封装 http 调用,并强制使用 RESTful 风格,它会处理 http 连接和关闭,只需要提供资源的地址和参数即可

首先定义一下 RestTemplate

@Configuration
public class BeanConfig {@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}

之后就可以在 service 中注入 RestTemplate 对象,然后就可以构造 http 请求了,把获取到的资源再通过指定的 ProductInfo 类型进行返回

@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);//构建URLString url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId();//通过get方式发起请求获取资源ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}
}

通过这种方式就实现了远程调用

String url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId();

不过上面的方式存在一些弊端,根据 get,post,put 等来区分对资源的操作类型并不能直观地看出来,通过抓包才能看出具体是哪种类型,不如直接把动作放在 URL 上直观

此外,还存在下面的一些问题:

  1. 由于 IP 地址是固定写的,如果 IP 地址发生了变化就需要修改代码
  2. 如果是多机部署如何处理?
  3. 返回结果怎么共用?
  4. URL 也的书写也容易出现错误
  5. 接口是对外开放的,存在一定风险

4. 注册中心的引入

针对 IP 地址改变的问题,可以通过下面的流程来解决

  1. 服务提供者(Server):一次业务中被其它微服务调用的服务,也就是提供接口给其它微服务
  2. 服务消费者(Client):一次业务中,调用其它微服务的服务,也就是调用其它微服务提供的接口
  3. 服务注册中心(Registry):用于保存 Server 的注册信息,当 Server 节点发生变更时,Registry 会同步变更,服务与注册中心使用一定机制通信,如果注册中心与某服务长时间无法通信,就会注销该实例
  4. 服务注册:服务提供者在启动时,向 Registry 注册自身服务,并向 Registry 定期发送心跳汇报存活状态。
  5. 服务发现:服务消费者从注册中心查询服务提供者的地址,并通过该地址调用服务提供者的接口。服务发现的一个重要作用就是提供给服务消费者一个可用的服务列表。

在上面的流程中,通过一个注册中心来存储应用和 IP 之间的关系,服务消费者以此来获取应用的 IP 地址,然后再去远程调用

5. CAP 理论

C:一致性(强一致性),所有节点在同一时间具有相同的数据

当客户端向数据库集群发送了一个数据修改的请求之后,数据库集群需要向客户端进行响应,此时就会有两种情况:

  1. 主数据库接收到请求并处理成功,不过数据还没有同步到从数据库,随着时间的推移会同步到从数据库
  2. 主数据库接收到请求,所有的从数据库数据同步成功时

弱一致性就是第一种情况,强一致性就是第二种情况,不论何时,主库和从库对外提供的服务都是一致的

A:可用性,保证每个请求都有响应,不过响应结果可能不对

P:分区容错性,当出现网络分区后,系统仍然能够对外提供服务

这三种特性是不能同时兼顾的,比如,在主数据库和从数据库同步数据的过程中网络出现了问题,那么这个过程就会被拉长,如果保证可用性,那么用户此时获取到的信息就不是强一致性的数据,在微服务架构中, P 是必须要保证的,所以 C 和 A 只能兼顾一个,也就是 CP 架构和 AP 架构

6. Eureka

官方文档:https://github.com/Netflix/eureka/wiki

6.1. 搭建 Eureka Server

首先再创建一个 eureka-server 的子模块

然后引入 eureka-server 的依赖和项目构建的插件

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>
</dependencies>
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

接着还需要编写配置文件

server:port: 10010  
spring:application:name: eureka-server
eureka:instance:hostname: localhostclient:fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为falseregister-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.service-url:# 设置与Eureka Server的地址,查询服务和注册服务都需要依赖这个地址defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

然后编写启动类进行启动,和之前的启动类不同的是,这里还需要加上@EnableEurekaServer注解

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

启动之后访问服务就可以看到注册中心的界面了:

6.2. 服务注册

把 product-service 注册到 eureka-server 中需要在 product-service 中添加客户端的依赖

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

然后配置文件也需要完善一下,把要注册的服务的名称和 eureka 的地址配置一下:

在 product-service 的 yml 文件中添加一下配置,端口号也是之前配置的 eureka 的端口号,

#Eureka Client
eureka:client:service-url:defaultZone: http://127.0.0.1:10010/eureka/

然后配置服务名称

spring:application:name: product-service

接下来先启动 eureka 服务,再启动 product 服务就能够看到已经注册成功了

然后以相同的方式把 order-service 也添加到注册列表中

6.3. 服务发现

之后再进行远程调用的时候就可以从注册中心来获取要调用服务的 IP 和端口号了,需要在原来获取的方式上进行一些修改

接下来就能成功的获取到 product-service 的信息了

Eureka 和 Zookeeper 的区别:

Eureka 和 Zookeeper 都是用于服务注册和发现的工具,区别有以下几点:

  1. Eureka 是 Netflix 开源的项目,而 Zookeeper 是 Apache 开源的项目
  2. Eureka 基于 AP 原则,保证高可用,Zookeeper 基于 CP 原则,保证数据一致性
  3. Eureka 每个节点都是均等的,Zookeeper 的节点区分 Leader 和 Follower 或 Observer,由于这个原因,如果 Zookeeper 的 Leader 发生故障,需要重新选举,选举过程集群会有短暂时间的不可用

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV:二值化与自适应阈值

目录 简述 1. 什么是二值化 2. 二值化接口 2.1 参数说明​​​​​ 2.2 示例代码 2.3 运行结果 3. 自适应阈值 3.1 参数说明 3.2 示例代码 3.3 运行结果 4. 总结 4.1 二值化 4.2 自适应阈值 相关阅读 OpenCV&#xff1a;图像的腐蚀与膨胀-CSDN博客 简述 图像二值…

Java面试题2025-设计模式

1.说一下开发中需要遵守的设计原则&#xff1f; 设计模式中主要有六大设计原则&#xff0c;简称为SOLID &#xff0c;是由于各个原则的首字母简称合并的来(两个L算一个,solid 稳定的)&#xff0c;六大设计原则分别如下&#xff1a; 1、单一职责原则 单一职责原则的定义描述非…

Win11下帝国时代2无法启动解决方法

鼠标右键点图标&#xff0c;选择属性 点开始&#xff0c;输入启用和关闭

JAVA实战开源项目:在线文档管理系统(Vue+SpringBoot) 附源码

本文项目编号 T 038 &#xff0c;文末自助获取源码 \color{red}{T038&#xff0c;文末自助获取源码} T038&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

Python设计模式 - 组合模式

定义 组合模式&#xff08;Composite Pattern&#xff09; 是一种结构型设计模式&#xff0c;主要意图是将对象组织成树形结构以表示"部分-整体"的层次结构。这种模式能够使客户端统一对待单个对象和组合对象&#xff0c;从而简化了客户端代码。 组合模式有透明组合…

算法每日双题精讲 —— 前缀和(【模板】一维前缀和,【模板】二维前缀和)

在算法竞赛与日常编程中&#xff0c;前缀和是一种极为实用的预处理技巧&#xff0c;能显著提升处理区间和问题的效率。今天&#xff0c;我们就来深入剖析一维前缀和与二维前缀和这两个经典模板。 一、【模板】一维前缀和 题目描述 给定一个长度为 n n n 的整数数组 a a a&…

VLLM性能调优

1. 抢占 显存不够的时候&#xff0c;某些request会被抢占。其KV cache被清除&#xff0c;腾退给其他request&#xff0c;下次调度到它&#xff0c;重新计算KV cache。 报这条消息&#xff0c;说明已被抢占&#xff1a; WARNING 05-09 00:49:33 scheduler.py:1057 Sequence gr…

知识管理系统塑造企业文化与学习型组织的变革之路

内容概要 知识管理系统&#xff08;Knowledge Management System, KMS&#xff09;是指组织内部为有效获取、存储、共享和应用知识而建立的结构和技术体系。这一系统不仅是信息技术的运用&#xff0c;更是推动企业文化和学习型组织发展的重要工具。在当今快速变化的商业环境中…

智能汽车网络安全威胁报告

近年来随着智能汽车技术的快速发展&#xff0c;针对智能汽车的攻击也逐渐从传统的针对单一车辆控制器的攻击转变为针对整车智能化服务的攻击&#xff0c;包括但不限于对远程控制应用程序的操控、云服务的渗透、智能座舱系统的破解以及对第三方应用和智能服务的攻击。随着WP.29 …

Python练习(2)

今日题单 吃鱼还是吃肉 PTA | 程序设计类实验辅助教学平台 降价提醒机器人PTA | 程序设计类实验辅助教学平台 幸运彩票 PTA | 程序设计类实验辅助教学平台 猜帽子游戏 PTA | 程序设计类实验辅助教学平台 谁管谁叫爹 PTA | 程序设计类实验辅助教学平台 就不告诉你 PTA | 程…

Ubuntu-手动安装 SBT

文章目录 前言Ubuntu-手动安装 SBT1. SBT是什么?1.1. SBT 的特点1.2. SBT 的基本功能1.3. SBT 的常用命令 2. 安装2.1. 下载2.2. 解压 sbt 二进制包2.3. 确认 sbt 可执行文件的位置2.4. 设置执行权限2.5. 创建符号链接2.6. 更新 PATH 环境变量2.7. 验证 sbt 安装 前言 如果您觉…

240. 搜索二维矩阵||

参考题解&#xff1a;https://leetcode.cn/problems/search-a-2d-matrix-ii/solutions/2361487/240-sou-suo-er-wei-ju-zhen-iitan-xin-qin-7mtf 将矩阵旋转45度&#xff0c;可以看作一个二叉搜索树。 假设以左下角元素为根结点&#xff0c; 当target比root大的时候&#xff…

Golang笔记——常用库context和runtime

大家好&#xff0c;这里是Good Note&#xff0c;关注 公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Golang的常用库context和runtime&#xff0c;包括库的基本概念和基本函数的使用等。 文章目录 contextcontext 包的基本概念主要类型和函数1. **…

Leetcode:350

1&#xff0c;题目 2&#xff0c;思路 首先判断那个短为什么呢因为我们用短的数组去挨个点名长的数组主要用map装长的数组max判断map里面有几个min数组的元素&#xff0c;list保存交集最后用数组返回list的内容 3&#xff0c;代码 import java.util.*;public class Leetcode…

《多线程基础之互斥锁》

【互斥锁导读】互斥锁是大家使用最多的线程同步手段&#xff0c;但仅仅知道怎么用还是不够的&#xff1f;比如&#xff1a;面试官问你"互斥锁是属于内核层还是应用层的同步保护机制&#xff1f;性能怎样&#xff1f;"&#xff0c;"频繁加解锁&#xff0c;会有什…

【Rust自学】15.0. 智能指针(序):什么是智能指针及Rust智能指针的特性

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.0.1 指针的基本概念 指针是一个变量在内存中包含的是一个地址&#xff0c;指向另一个数据。 Rust 中最常见的指针是引用&#xff0c…

Android Studio 正式版 10 周年回顾,承载 Androider 的峥嵘十年

Android Studio 1.0 宣发于 2014 年 12 月&#xff0c;而现在时间来到 2025 &#xff0c;不知不觉间 Android Studio 已经陪伴 Androider 走过十年历程。 Android Studio 10 周年&#xff0c;也代表着了我的职业生涯也超十年&#xff0c;现在回想起来依然觉得「唏嘘」&#xff…

Swing使用MVC模型架构

什么是MVC模式? MVC是一组英文的缩写,其全名是Model-View-Controller,也就是“模型-视图-控制器”这三个部分组成。这三个部分任意一个部分发生变化都会引起另外两个发生变化。三者之间的关系示意图如下所示: MVC分为三个部分,所以在MVC模型中将按照此三部分分成三…

1.Template Method 模式

模式定义 定义一个操作中的算法的骨架&#xff08;稳定&#xff09;&#xff0c;而将一些步骤延迟&#xff08;变化)到子类中。Template Method 使得子类可以不改变&#xff08;复用&#xff09;一个算法的结构即可重定义&#xff08;override 重写&#xff09;该算法的某些特…

arm-linux-gnueabihf安装

Linaro Releases windows下打开wsl2中的ubuntu&#xff0c;资源管理器中输入&#xff1a; \\wsl$gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz 复制到/home/ark01/tool 在 Ubuntu 中创建目录&#xff1a; /usr/local/arm&#xff0c;命令如下&#xff1a; …