服务注册/发现-Eureka-微服务核心组件【分布式微服务笔记02】

服务注册/发现-Eureka-微服务核心组件【分布式微服务笔记02】

服务注册/发现-Eureka

目前主流的服务注册&发现的组件是Nacos, 但是Eureka 作为一个老牌经典的服务注册&发现技术还是有必要学习一下, 原因:

  1. 一些早期的分布式微服务项目使用的是Eureka,在工作中, 完全有可能遇到.
  2. 后期的服务注册&发现组件/技术, 都参考了Eureka 设计和理念, 学习了Eureka 后, 我们上手Nacos 容易很多,而且理解的更深刻.

引出Eureka

在不使用 服务注册/发现-Eureka 时,通常我们的项目架构是:

服务消费方 ------利用restTemplate (直接调用) ---->服务提供方

如下:

@RestController
@RequestMapping("/member/consumer")
@Slf4j
public class MemberConsumerController {//定义MEMBER_SERVICE_PROVIDER_URL 基础url地址public static final String MEMBER_SERVICE_PROVIDER_URL = "http://localhost:10001";@Autowiredprivate RestTemplate restTemplate;//接口/****  添加member;*  member :通过restTemplate 发出的请求携带的数据;*  Result.class :返回对象的类型;*/@PostMapping("/save")public Result<Member> save(Member member) {return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);}//根据id 调用服务接口 返回member@GetMapping("/get/{id}")public Result<Member> getMemberById(@PathVariable("id") Long id) {return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/get/" + id, Result.class);}}

但这样简单的项目结构有一定的缺陷:

  1. 在企业级项目中,服务消费访问请求会存在高并发
  2. 如果只有一个会员中心-提供服务,可用性差
  3. 所以,提供服务方往往是一个集群,也就是说会有多个提供服务微服务模块
  4. 那么这个时候,就存在一个问题就是服务消费方,不能写死这些url,那怎么去发现可以使用的服务(引出服务发现)
  5. 当服务消费方,发现了可以使用的服务后(可能是多个,又存在一个问题就是到底调用A服务,还是B 服务的问题,这就引出了服务注册和负载均衡)
  6. Eureka 就可以解决上述问题

引入Eureka后项目

使用 服务注册/发现-Eureka 后,通常我们的项目架构是:

  1. 服务提供方【可能是一个集群】------将自己注册到/renew/cancel---->Eureka Server【可能是一个集群】
  2. 服务消费方 ------将自己注册到/发现服务---->Eureka Server【可能是一个集群】 ---->
  3. 服务消费方 ------远程调用 remote call---->服务提供方

分析:

  1. 会员中心-提供服务的,在项目中,会做成集群,提供高可用
  2. Eureka Server 有必要的话,也可以做成集群,保证单个Eureka Server 宕机,保证高可用
  3. Eureka 包含两个组件∶Eureka Server 和 Eureka Client
  4. Eureka Server 提供注册服务, 各个微服务节点【服务消费方、服务提供方】通过配置启动后,会在Eureka Server 中进
    行注册,这样EurekaServer 中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面【Eureka 提供的界面】中直观看到。
  5. EurekaClient 通过注册中心进行访问, 是一个Java 客户端,用于简化Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin) 负载算法的负载均衡器。在应用启动后,将会向Eureka Server 发送心跳(默认周期为30 秒)【确定微服务模块还在运行】。如果Eureka Server 在多个心跳周期内没有接收到某个节点的心跳【宕机了】,EurekaServer 将会从服务注册表中把这个服务节点移除(默认90 秒)

服务治理

  1. Eureka实现了服务治理
  2. 在传统的rpc(Remote Procedure Call) 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理困难,所以需要治理服务之间依赖关系
  3. 服务治理实现服务调用、负载均衡、容错等,实现服务发现与注册

服务注册和服务发现

  1. Eureka采用了CS【client-server】的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。
  2. 系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接,通过Eureka Server 来监控系统中各个微服务是否正常运行。
  3. 在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。
  4. 服务消费者或者服务提供者,以服务别名的方式去注册中心上获取到实际的服务提供者通讯地址,然后通过RPC调用服务

Eureka-Server 【非集群】代码实现

  1. pom.xml引入 eureka-server starter场景启动器

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  2. 配置application.yml

    #配置端口号
    server:port: 9001#配置eureka-server
    eureka:instance:#服务实例名hostname: localhost#当 eureka-server是一个集群时,需要互相注册,变成了 clientclient:#配置不向注册中心注册自己register-with-eureka: false#表示自己就是注册中心,作用: 维护注册服务实例,不需要去检索服务fetch-registry: falseservice-url:#设置与 eureka-server 交互的模块,查询服务和注册服务都需要依赖这个地址defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    
  3. 编写主启动类

    @EnableEurekaServer //表示该程序作为Eureka-server,并且监听端口
    @SpringBootApplication
    public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}
    }
    

    Eureka-Client 【非集群 】代码实现

  4. 引入 eureka-client 场景启动器 starter

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  5. 配置application.yml

    #配置端口号
    server:port: 10001spring:application:name: member-service-provider-10001 #配置应用的名称datasource:type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8username: rootpassword: zy#配置mybatis
    mybatis:mapper-locations: classpath:mapper/*.xml #指定mapper。xml文件type-aliases-package: com.zy88.springcloud.entity #实体类 别名引用#配置eureka-client
    eureka:client:# 将自己注册到eureka-serverregister-with-eureka: true# 表示从 Euraka-Server 抓取注册信息,如果不是集群,可以不配置。# 如果是集群,设置成true才能配合Ribbon使用负载均衡fetch-registry: true#表示将自己注册到哪个eureka-serverservice-url:defaultZone: http://localhost:9001/eureka
    
  6. 编写主启动类

    @EnableEurekaClient//表示该程序作为Eureka-Client,并且监听端口
    @SpringBootApplication
    public class MemberApplication {public static void main(String[] args) {SpringApplication.run(MemberApplication.class, args);}
    }
    

Eureka自我保护模式

  1. 默认情况下EurekaClient定时向EurekaServer端发送心跳包

  2. 如果Eureka在server端在一定时间内(默认90秒)没有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务

  3. 如果Eureka 开启了自我保护模式/机制, 那么在短时间(90秒中)内丢失了大量的服务实例心跳,这时候EurekaServer会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通或者阻塞) 因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的

  4. 自我保护是属于CAP 里面的AP 分支, 保证高可用和分区容错性

  5. 自我保护模式是—种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式, 可以让Eureka 集群更加的健壮、稳定。

  6. 参考:https://blog.csdn.net/wangliangluang/article/details/120626014

  7. 禁用Eureka自我保护模式【实际生产不推荐!】

    eureka:server:#禁用自我保护模式enable-self-preservation: false
    

Eureka-Server 【集群】代码实现

为什么需要集群?

  1. 微服务RPC 远程服务调用最核心的是实现高可用
  2. 如果注册中心只有1 个,它出故障,会导致整个服务环境不可用
  3. 解决办法∶搭建Eureka 注册中心集群,实现负载均衡+故障容错

代码实现:

  1. 修改application.yml

    server:port: 9001#配置eureka-server
    eureka:instance:#服务实例名hostname: eureka9001.com#当 eureka-server是一个集群时,需要互相注册,变成了 clientclient:#配置不向注册中心注册自己register-with-eureka: false#表示自己就是注册中心,作用: 维护注册服务实例,不需要去检索服务fetch-registry: falseservice-url:#集群需要相互注册 , 注册到eureka9001defaultZone: http://eureka9002.com:9002/eureka/
    
  2. 修改hosts文件

    文件地址:C:\Windows\System32\drivers\etc\hosts

Eureka-Client-提供方 【集群 】代码实现

修改 eureka-client 的 application.yml即可

server:port: 10001spring:application:name: member-service-provider #配置应用的名称datasource:type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8username: rootpassword: zy#配置mybatis
mybatis:mapper-locations: classpath:mapper/*.xml #指定mapper。xml文件type-aliases-package: com.zy88.springcloud.entity #实体类 别名引用#配置eureka-client
eureka:client:# 将自己注册到eureka-serverregister-with-eureka: true# 表示从 Euraka-Server 抓取注册信息,如果不是集群,可以不配置。# 如果是集群,设置成true才能配合Ribbon使用负载均衡fetch-registry: true#表示将自己注册到哪个eureka-serverservice-url:# 注册到集群,多个eureka,使用逗号间隔defaultZone: http://eureka9001.com:9001/eureka,http://eureka9002.com:9002/eureka
  • 以集群提供服务,需要将spring.application.name 统一,这样消费方通过统一的别名进行负载均衡调用

    spring:application:name: member-service-provider #配置应用的名称,如果是集群保持一致
    

Eureka-Client-消费方【集群 】代码实现

  1. 需要修改MemberConsumerController

    @RestController
    @RequestMapping("/member/consumer")
    @Slf4j
    public class MemberConsumerController {//定义MEMBER_SERVICE_PROVIDER_URL 基础url地址//MEMBER-SERVICE-PROVIDER 表示服务提供方【集群】,注册到Eureka-server的别名//就是服务提供方【集群】,对外暴露的名称MEMBER-SERVICE-PROVIDERpublic static final String MEMBER_SERVICE_PROVIDER_URL = "http://MEMBER-SERVICE-PROVIDER";@Autowired
    private RestTemplate restTemplate;//接口
    /****  添加member;*  member :通过restTemplate 发出的请求携带的数据;*  Result.class :返回对象的类型;*/@PostMapping("/save")public Result<Member> save(Member member) {return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);}//根据id 调用服务接口 返回member
    @GetMapping("/get/{id}")
    public Result<Member> getMemberById(@PathVariable("id") Long id) {return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/get/" + id, Result.class);}
    }
    
  2. 在配置类,CustomizationBean 中增加一个注解@LoadBalanced 赋予 restTemplate 负载均衡的能力,也就是说根据负载均衡算法【默认轮询算法,也可以配置负载均衡的算法】来选择某个服务去访问

    //配置注入 RestTemplate
    @Configuration
    public class CustomizationBean {@LoadBalanced //赋予 restTemplate 负载均衡 的能力@Beanpublic RestTemplate getRestTemplate() {return new RestTemplate();}
    }
    
  • 轮询交替访问member 服务说明:
    1. 注解@LoadBalanced 底层是Ribbon 支持算法
    2. Ribbon 和Eureka整合后consumer 直接调用服务而不用再关心地址和端口号,且该服务还有负载功能

DiscoveryClient-获取Eureka Server 服务注册信息

获取到Eureka Server 服务注册信息,可以使用 DiscoveryClient

  1. 需要加上 @EnableDiscoveryClient , 启用服务发现
  2. 装配 DiscoveryClient
  3. 编写接口discovery( )
@EnableDiscoveryClient //启用服务发现
@RestController
@RequestMapping("/member/consumer")
@Slf4j
public class MemberConsumerController {public static final String MEMBER_SERVICE_PROVIDER_URL = "http://MEMBER-SERVICE-PROVIDER";@Autowiredprivate RestTemplate restTemplate;//装配 DiscoveryClient@Autowiredprivate DiscoveryClient discoveryClient;@GetMapping("/discovery")public Object discovery(){List<String> services = discoveryClient.getServices();//遍历服务for (String service : services) {log.info("服务名= {}",service);//获取服务名对应的实例List<ServiceInstance> instances = discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {log.info("id= {},host= {},port= {},uri= {}",instance.getServiceId(),instance.getHost(),instance.getPort(),instance.getUri());}}return discoveryClient;}@PostMapping("/save")public Result<Member> save(Member member) {return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);}@GetMapping("/get/{id}")public Result<Member> getMemberById(@PathVariable("id") Long id) {return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/get/" + id, Result.class);}}

访问 http://localhost/member/consumer/discovery 获取Eureka Server 服务注册信息:


本文学习内容来自韩顺平老师的课程

仅供个人参考学习

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

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

相关文章

Toshiba东芝硬盘开盘数据恢复

一、开盘数据恢复的前提 当硬盘出现物理性损坏,如磁头损坏、盘片划伤等,导致数据无法通过常规手段读取时,开盘数据恢复成为唯一可行的选择。 需要明确的是,开盘数据恢复应在数据无法通过恢复或其他非开盘手段解决的情况下进行。 二、开盘数据恢复的步骤 准备阶段 在无尘环境…

磁头损坏的修复方法有哪些

一、更换磁头 购配件盘:首先,需购一块与故障硬盘同型号、同批次或同时期的配件盘。这是因为磁头的规格和兼容性对于修复成功至关重要。 无尘室操作:在无尘室环境下进行操作,以防止灰尘等杂质对硬盘内部造成进一步污染。 更换磁头:将故障硬盘的磁头取下,并替换为配件盘上的…

关于三星SSD移动硬盘的维修与数据恢复

通常涉及多个方面,包括故障诊断、硬件维修以及数据恢复等。 一、故障诊断 检查连接: 确保SSD移动硬盘与计算机的连接是稳定的,检查数据线是否损坏或接触不良。 尝试更换不同的USB端口或电脑进行测试,以排除USB接口问题。 电源检查: 确认移动硬盘的电源供应是否正常,特别是…

硬盘如何维修数据恢复

一、硬盘维修方法 检查硬件连接: 确保硬盘与计算机的连接线(如SATA线、电源线)插紧且没有损坏。 尝试更换连接线或使用主板上的其他接口,以排除连接线或接口故障的可能性。 使用系统自带工具: 在Windows系统中,可以使用“磁盘检查”工具(chkdsk)来检测和修复硬盘上的文…

产品探秘:智影AI——你的创意视频制作神器!

从文字到图片再到视频的智能创作工具。只需3步,把小说变成视频。免费试用,首次注册赠送600积分。只需3步,把小说变成视频。免费试用,首次注册赠送600积分。 https://icomicai.com/在这个快节奏的时代,创意与效率并重成为了我们追求的新风尚。今天,就让我带你一起揭秘一款颠…

如何在Mac上隐藏APP? 在Mac上隐藏不用的APP小技巧

在Mac电脑中我们每天要使用很多APP,虽然Mac切换APP窗口的快捷键非常方便,但同时使用几个APP窗口是不是特别容易搞混?看起来乱糟糟的。下面我们分享在Mac上隐藏不用的APP小技巧,让用户摆脱混乱的APP窗口。 1、在Mac电脑中,打开你想要保留的APP;2、点击屏幕顶部菜单栏中APP…

帝国cms、以下状况或错误提示,是没有按照安装说明中讲的“初始化内置数据”这个步骤操作的原因:

1、增加信息提示“建立目录不成功!请检查目录权限”; 2、除了首页外,其他页面都打不开; 3、页面的CSS地址错误。本文来自博客园,作者:黄文Rex,转载请注明原文链接:https://www.cnblogs.com/hwrex/p/18306966

DC8渗透报告

概述测试目的测试范围序号系统IP1本机192.168.152.1282DC8192.168.152.139详细测试流程1、发现测试目标2、信息收集3、漏洞利用sqlmap -u http://192.168.152.139?nid=1 --random-agent --level 3 --risk 3 --current-db --is-dba --batch –dbs发现不是dba有2个数据库然后逐步…

使用forEach循环异步方法,导致使用深拷贝时,得不到最新数据,控制台会打印出最新的数据

解决forEach不能处理异步方法问题在使用forEach循环遍历一个数组,如果循环时有异步方法,会导致最终深拷贝得不到最新数据,但是控制台会打印最新的数据 `const arr = [ { name: "Jone", age: 18 }, { name: "Tom", age: 15 }, { name: "Liu", …

Mac ssh自动输入密码

1. 需要在Mac上安装expect,如果已经安装过可以省略这一步 Mac 上安装一般是使用homebrew安装,在终端上输入brew install expect可以安装,如果还未安装过homebrew的朋友参考https://www.cnblogs.com/orzs/p/18306760或自行百度。2. 编写脚本 第一个脚本autossh.exp#!/usr/bin…

windows动态磁盘扩容

1. 基本磁盘 基本磁盘的卷旁边没有未分配空间的话,是无法进行扩容的 2. 动态磁盘 动态磁盘旁边没未分配空间的话可以扩容,会在原本最后面一共卷后在追加一个卷空间(与被扩容卷同名)其他 动态磁盘与基本磁盘对比: 一块基本磁盘只能包含4个分区,它们是最多三个主分区和一个…

C#8 中有趣的的索引和范围特性

C#8 中有趣的的索引和范围特性var array = new int[]{3,4,6,4,52,63,5,545,4,345,5,52,6};Debug.Log(array[^5]);Debug.Log(array[5..8].Length);使用这些索引和范围特性可以让您更方便地访问和操作数组、列表或字符串中的元素。它们不仅可以提高代码的可读性,还可以减少一些常…