当前位置: 首页 > news >正文

【微服务】注册中心 - Eureka(day3)

CAP理论

P是分区容错性。简单来说,分区容错性表示分布式服务中一个节点挂掉了,并不影响其他节点对外提供服务。也就是一台服务器出错了,仍然可以对外进行响应,不会因为某一台服务器出错而导致所有的请求都无法响应。综上所述,在分布式系统中,分区容错性是必须要保证的一个特性。

C表示一致性。通俗的讲,一致性就是所有节点在某个响应时的数据都是相同的。

A表示可用性。可用性指代对所有的请求都有相应结果。

在分布式系统中,P是必须要保证的一个特性,因此可用性和一致性就不能同时保证。原因就是当一个节点收到数据之后,要传给别的节点进行复制,在这个过程中,如果有请求的话,那么就可能导致一致性出现问题。假设要保证一致性,那就得上锁,不对外响应,那么此时可用性就出现了问题。因此,分布式系统中,只存在AP理论和CP理论。

举个例子来说明一下CAP的概念。在一家生意火爆的饭店中,一道菜的原料没有了,就要告诉所有的服务员不能再下单该菜了,但是通知的过程是要浪费时间的。

一致性表示所有的服务都接到通知了,因此对客户的响应都是相同的。可用性就是不管有没有接收到通知,服务员都会给出一个响应。分区容错性是指一个服务员请假了,那也不会影响今天的饭店开门。分区容错性饭店肯定是能保证的。但是如果要保证一致性,那么在所有服务员接收到通知之前,都是不能讲话的,这就影响到了可用性。如果要保证可用性,那么所有的服务员都能讲话,但是不确定谁没有接收到信息。如果想要同时保证可用性和一致性,只有一种可能,就是饭店只有一个人,但是这种情况下,他请假,饭店就关门了,分区容错性就没有了。

服务注册和发现引入

概述

在基础工程搭建中,我们发现调用服务时是以硬编码的方式来创建URL的,但是对于微服务来说,一个服务可能有成百上千个实例,并且还会随时扩缩容。因此,我们采用这种方式是不合理的。并且,在日常管理中,对这么多的实例,我们并不能立马确定哪个实例出现了宕机等问题。因此就出现了微服务家族的第一套组件——服务注册和发现。

服务注册和发现,最重要干的事就是把所有注册到注册中心的实例给展示出来。这样,我们可以轻松的看到所有的实例运行情况。如果此时某台实例出错下线了,注册中心也能监控到,并将该实例进行剔除,不再对外进行服务。而且,有的注册中心也能支持实例的动态上下线,这样能很快的实现扩缩容,大大减少了运维开发的工作。

综上所述,服务注册和发现组件的功能大概有:服务管理、容错处理、动态扩展等。当然,不同产品也会存在一定的差异化,例如咋们中国阿里巴巴的Nacos就不止实现了服务注册和发现这个功能,还有分布式配置管理等,当然,这都是下文了。

功能图

 角色

Server,服务提供者:一次业务中,被其他服务调用的服务,也就是提供接口给其他服务。

Client,服务消费者:一次业务中,调用其他服务的服务,也就是使用接口的服务。

Registry,服务注册中心:用来保存Server的注册信息,当Server节点发生变更时,注册中心就会感知到并进行同步更新。注册中心和注册的服务存在一定机制进行通信,如果注册中心与某服务长期没有通信,也就是超过限定的阈值,那么注册中心就会下线该实例。

服务注册和服务发现

服务注册:服务提供者在启动服务时,将自身注册到注册中心中,并定期向注册中心发送心跳包表示自己还存活。

服务发现:服务消费者需要调用某服务时,就先去注册中心找到服务提供者的地址,通过该地址对服务提供者进行调用。服务发现的重要作用就是提供一个可用的服务列表给消费者。

搭建注册中心

内容

1. Eureka Server:作为注册中心,向服务提供服务注册、服务发现、健康检查等功能。

2. Eureka Client:服务提供者,服务启动时,会向注册中心提供自己的信息,例如端口号,IP地址等内容,而注册中心会保存这些信息。

步骤

1. 搭建Eureka Server。

2. 将服务都注册到注册中心中。

3. 服务与服务之间进行调用时,先去注册中心查找被调用服务的服务列表,然后进行调用。

搭建案例

搭建注册中心

建模块

写pom文件

<?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><parent><groupId>com.wbz</groupId><artifactId>spring-cloud-test</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>cloud-server-eureka10010</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--web通用模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--注册中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies></project>

写yml文件

server:port: 10010spring:application:name: cloud-server-eureka10010eureka:instance:hostname: localhostclient:# 表示是否从注册中心中获取注册的服务信息,默认是true# 咋们搭建的只是一个单体的,没有其他注册中心,因此不需要同步fetch-registry: false# 表示是否将自己注册到注册中心register-with-eureka: falseservice-url:# 设置注册中心的地址,查询服务和注册服务都需要依赖这个地址defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

改启动类

/*** Eureka服务注册中心*/@EnableEurekaServer // 开启注册中心服务
@SpringBootApplication
public class EurekaServerApplication10010 {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication10010.class, args);}}

启动该服务,访问URL:127.0.0.1:10010,出现如下界面就算搭建成功:

注册商品服务到注册中心

修改pom文件

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

修改yml文件

eureka:client:service-url:defaultZone: http://127.0.0.1:10010/eureka/

注册订单服务到注册中心

 修改pom文件

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

修改yml文件

eureka:client:service-url:defaultZone: http://127.0.0.1:10010/eureka/

把两个项目进行重新启动,再次观察Eureka的页面,发现:

硬编码解耦

订单服务中进行修改

@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {/*@Resourceprivate RestTemplate restTemplate;@Overridepublic Order getOrderById(Integer id) {Order order = this.getById(id);String url = "http://127.0.0.1:8001/product/query/" + order.getProductId();Product product = this.restTemplate.getForObject(url, Product.class);order.setProduct(product);return order;}*/private final String PRODUCT_SERVICE_NAME = "cloud-provider-payment8001";@Resourceprivate RestTemplate restTemplate;@Resourceprivate DiscoveryClient discoveryClient;@Overridepublic Order getOrderById(Integer id) {// 获取订单Order order = this.getById(id);// 获取商品服务的实例List<ServiceInstance> instances = discoveryClient.getInstances(this.PRODUCT_SERVICE_NAME);// 输出日志查看获取到的实例有哪些内容log.info(instances.toString());// 获取第一个商品实例的uriString uri = instances.get(0).getUri().toString();log.info(uri);// 拼接urlString url = uri + "/product/query/" + order.getProductId();// 远程调用Product product = this.restTemplate.getForObject(url, Product.class);order.setProduct(product);// 返回结果return order;}}

在硬编码解耦中,其实就是将原来的IP和PORT进行改换。通过服务名字去注册中心查找实例然后进行调用,这样无论启动多少个实例,也不用对代码进行变动。

Eureka对于CAP理论来说,其实现的是AP理论,保证高可用。

总结与疑惑 

在我第一次学习了Eureka之后,感觉这个组件好好用,能减少代码的耦合,不过,随之而来又出现了一个问题就是当我启动多个实例之后,发现我依旧只能调用第一个服务,那原因是出在哪里呢。经过查看我的代码如下图发现,是在服务调用的时候写了只调用第一个。问题找打了,但是如何解决呢?写一个取余来判断?但是我又不确定又几个实例。在这里就不多说了,好奇的同学就赶快去看第二个组件负载均衡吧,他完美解决了这个问题。

再提一句,学习了Nacos和Consul之后,发现Eureka不香了,看到这里的同学是不是得来一句——经典白雪,赶快打在评论区吧。


http://www.mrgr.cn/news/42393.html

相关文章:

  • Timer 计时器
  • 《蓝桥杯算法入门》(C/C++、Java、Python三个版本)24年10月出版
  • 华为OD机试 - 无向图染色(Python/JS/C/C++ 2024 E卷 100分)
  • 两个wordpress网站共用一个数据库的数据表
  • 如何对物理系统进行数学建模?
  • CSS属性 - animation
  • 14 Shell Script正则表达式
  • Navicat Premium 12 for Mac中文永久版
  • 鸿蒙HarmonyOS开发生态:构建万物互联的未来
  • java高并发场景RabbitMQ的使用
  • 360浏览器时不时打不开csdn
  • 大厂笔试现已经禁用本地IDE怎么看
  • 系统架构设计师教程 第13章 13.2 表现层架构设计 笔记
  • 【ubuntu】Ubuntu20.04安装中文百度输入法
  • 我是如何写作的?
  • 使用 Python 实现图形学的着色器编程算法
  • C初阶(十二)do - while循环 --- 致敬革命烈士
  • 告别繁琐!用Flyon UI轻松实现高颜值网站!
  • 【LeetCode: 344. 反转字符串 | 双指针模拟】
  • 外包干了3个多月,技术退步明显。。。。。