Spring Cloud——服务注册与服务发现原理与实现

目录

理解服务注册与服务发现

理解CAP理论

服务发现与注册的实现方式

常见的注册中心

Eureka的使用

前置环境

[搭建Eureka Server](#搭建Eureka Server)

服务注册

服务发现

理解服务注册与服务发现

在微服务架构中,服务之间需要频繁通信(例如订单服务调用支付服务、用户服务调用商品服务等)。但微服务的特点是服务实例动态变化 (如扩缩容、故障重启、部署升级等),导致服务的网络地址(IP + 端口 )经常变动。为解决 "服务消费者如何找到动态变化的服务提供者" 这一问题,就需要服务注册与服务发现机制。

注册中心主要有三种角色:

服务提供者Server):⼀次业务中, 被其它微服务调用的服务,也就是提供接口给其它微服务。

服务消费者(Client):⼀次业务中, 调用其它微服务的服务,也就是调用其它微服务提供的接口。

服务注册中心(Registry):用于保存Server 的注册信息,当Server 节点发生变更时,Registry 会同步变更,服务与注册中心使用⼀定机制通信,如果注册中心与某服务长时间无法通信, 就会注销该实例。

他们之间的关系以及⼯作内容, 可以通过两个概念来描述:

**服务注册:**服务提供者在启动时, 向 Registry 注册自身服务,并向 Registry 定期发送心跳汇报存活状态。

服务发现: 服务消费者从注册中心查询服务提供者的地址,并通过该地址调⽤服务提供者的接口,服务发现的⼀个重要作用就是提供给服务消费者⼀个可用的服务列表。

理解CAP理论

CAP 理论是分布式系统设计中最基础, 也是最为关键的理论。

⼀致性(Consistency) :CAP理论中的⼀致性,指的是强⼀致性,所有节点在同⼀时间具有相同的数据。

可用性(Availability) :保证每个请求都有响应(响应结果可能不对)。

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

分布式系统中,系统间的网络不能100%保证健康,服务又必须对外保证服务,因此分区容错性不可避免,那就只能在C和A中选择⼀个,也就是CP或者AP架构。

CP架构:如果网络出现异常数据不同步,为了保证分布式系统对外的数据⼀致性, 于是选择不返回任何数据。

AP架构:如果网络出现异常数据不同步,为了保证分布式系统的可用性,节点2返回V0版本的数据(即使这个数据不正确)

服务发现与注册的实现方式

常见的注册中心

Eureka:Netflix 出品,Java 生态深;AP,高可用,健康依赖心跳;与 Spring Cloud 集成顺滑。

Nacos:阿里开源,Service+Config 一体,支持权重、命名空间、Group、Cluster,国内容量大;AP/CP 兼顾。

Consul:HashiCorp,CP,支持 KV、健康检查、跨数据中心,带 DNS 接口,生态友好。

Zookeeper:老牌 CP 组件,更适合协调/选举;做注册中心也行,但使用体验不如上面几位现代化。

Eureka的使用

Eureka主要分为两个部分:

Eureka Server:作为注册中⼼Server端,向微服务应用程序提供服务注册,发现, 健康检查等能力。

Eureka Client:服务提供者,服务启动时,会向Eureka Server 注册自己的信息(IP,端口,服务信息等),Eureka Server 会存储这些信息。

前置环境

在idea下搭建了一个通过pom.xml构建的父子工程项目,子模包含订单模块,产品信息模块,每个模块都存在根据id查找对应的信息(例如根据订单id查询订单信息,根据产品id查找对应的产品信息)。现在的需求是根据服务注册中心,能够实现通过网络远程调用其他模块的信息,在订单数据表中包含对应的产品id,因此下面是实现在访问订单模块的时候能同时获取到对应产品的信息。

订单模块配置信息

产品模块配置信息

搭建Eureka Server

创建eureka_server子模块,引入spring

引入关键依赖

XML 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

配置yml

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

添加注解

java 复制代码
@EnableEurekaServer
@SpringBootApplication
public class EurekaServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServiceApplication.class,args);
    }
}

在Eureka项目的启动类中添加@EnableEurekaServer注解。

启动服务

启动服务访问注册中心:http://127.0.0.1:10010/,出现下面界面则访问成功

服务注册

下面的服务注册是对于需要进行服务注册的项目服务进行单独操作

引入依赖,注意这里是client,而eureka那里是server

XML 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

添加配置文件

java 复制代码
spring:
 application:
   name: product-service
eureka:
 client:
   service-url:
     defaultZone: http://127.0.0.1:10010/eureka

启动服务

服务发现

引入依赖

XML 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

添加配置文件

java 复制代码
spring:
 application:
   name: order-service
eureka:
 client:
   service-url:
     defaultZone: http://127.0.0.1:10010/eureka
复制代码

添加远程调用

java 复制代码
@Configuration
public class BeanConfig {
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
java 复制代码
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Resource
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;
​
    public OrderInfo selectOrderById(Integer orderId) {
​
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
​
        //根据应⽤名称获取服务列表
        List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
​
        //服务可能有多个,获取第⼀个
        EurekaServiceInstance instance = (EurekaServiceInstance) 
        instances.get(0);
​
        //拼接url
        String url = instance.getUri()+"/product/"+ orderInfo.getProductId();
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
     }
}

启动服务

访问接口: http://127.0.0.1:8080/order/1

远程调用成功。

相关推荐
cxr8286 小时前
自动化知识工作AI代理的工程与产品实现
运维·人工智能·自动化
·云扬·6 小时前
从零开始搭 Linux 环境:VMware 下 CentOS 7 的安装与配置全流程(附图解)
linux·运维·centos
btyzadt9 小时前
虚拟机蓝屏问题排查与解决
linux·运维·网络
G_H_S_3_10 小时前
【网络运维】Shell 脚本编程:while 循环与 until 循环
linux·运维·网络·shell
张鱼小丸子11 小时前
MySQL企业级部署与高可用实战
运维·数据库·mysql·云原生·高可用·mha·组从复制
弈芯11 小时前
SpringCloud微服务拆分最佳实践
spring cloud
时空自由民.11 小时前
linux下camera 详细驱动流程 OV02K10为例(chatgpt版本)
linux·运维·服务器
云川之下12 小时前
【网络】使用 DNAT 进行负载均衡时,若未配置配套的 SNAT,回包失败
运维·网络·负载均衡
ManageEngineITSM13 小时前
云原生环境下的ITSM新趋势:从传统运维到智能化服务管理
大数据·运维·人工智能·云原生·itsm·工单系统
檀越剑指大厂13 小时前
【Nginx系列】查看 Nginx 的日志
运维·nginx