SpringCloud 源码剖析(一)实战 Eureka 服务注册、调用、集群搭建

简介: SpringCloud 源码剖析(一)实战 Eureka 服务注册、调用、集群搭建

实战 Eureka 服务注册、调用、集群搭建

大家好,我是悟空呀~

之前已经写过 7 篇 Eureka 注册中心的源码剖析和理论相关的文章了,缺少一点实战。

本篇会带大家做一个实战案例,涉及内容:

  • 配置服务注册到 Eureka 注册中心。
  • 服务之间通过注册的服务名来访问。
  • 本地如何搭建 Eureka 集群。
  • 本地如何搭建微服务集群。
  • -如何用 Ribbon 实现负载均衡。

目录

之前的几篇 Eureka 文章也汇总下:

领导让我研究 Eureka 源码 | 启动过程

领导“叕”让我研究 Eureka 源码:注册过程

值得收藏的 Eureka 控制台详解

原来一个 Map 就能搞定注册表了

6 张图 | 剖析客户端首次同步注册表

11 张图 | 讲透原理,最细的增量拉取

12 张图 | 硬刚了一波,三层缓存架构

本文已同步至我的个人网站:www.passjava.cn

一、基本原理

注册 + 服务调用

先上原理图:

下面说下原理图中对应的场景:

场景

  • 有一个订单服务部署在一台机器上,另外有两个商品服务部署在一台机器上,三个服务的端口都不一样。
  • 商品服务和订单服务都将自己的地址信息注册到 Eureka,Eureka 把这些信息都缓存到注册表中。
  • 当订单服务想要调用商品服务时,其实是先从 eureka 上获取商品服务的地址信息。
  • 订单服务向两个商品服务发送 HTTP 请求。

服务宕机

当有一个商品服务宕机后,eureka 会把这个服务的注册信息移除掉,订单服务也不会调用这个商品服务。

下面我们按照上面服务调用的场景来简单使用下 Eureka。

需求:首先有一个订单服务 OrderService,一个商品服务 ProductService, 订单服务不知道商品服务的 IP 地址,只知道商品服务的 的名字,订单服务通过向 Eureka 注册中心获取到了商品服务的具体 IP 地址,然后成功调用商品服务的的 getProduct API。

二、创建 Eureka Server

总共会启动 4 个微服务,如下图所示:

创建一个 Eureka 服务。

前提条件:Spring Cloud 基于 Hoxton.SR10 版本,Spring Boot 基于 2.3.2.RELEASE。

启动类

创建启动类,Eureka Server 就是这个类启动的。

/**
 * @Author: 公众号 | 悟空聊架构
 * @Date: 2021/9/13 7:28
 * @Site: www.passjava.cn
 * @Github: https://github.com/Jackson0714/eureka-learning
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

配置项

然后配置下 Eureka Server 的基本信息。配置信息可以放到 application.yml 文件中。

server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

port:Eureka Server 监听的端口。

register-with-eureka: 是否把自己注册到 Eureka,单机情况下,不需要注册自己。

fetch-registry: 是否到 Euraka 服务抓取注册信息。

pom.xml 文件

首先需要配置 pom.xml 文件,引入 Eureka 依赖。

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.2.RELEASE</version>
  </parent>
  
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR10</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>

  </dependencies>

启动

接下来启动 Eureka Server 的控制台。浏览器访问 http://localhost:8761/ 就可以看到控制台了。

因为还没有服务注册到 Eureka,所以控制台中的服务列表是空的。

三、创建商品服务

application.yml 配置

商品服务对应的端口为 8006 和 8007,可以先启动一个商品服务,然后修改端口后,再启动另外一个商品服务。

server:
  port: 8006
spring:
  application:
    name: ProductService
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka

Controller 类

定义了获取商品的 API,提供给订单服务调用。

/**
 * 订单服务的接口
 *
 */
@RestController
public class ProductServiceController {

    /**
     * 订单服务
     * @param name 商品名称
     * @return 测试返回商品名
     */
    @RequestMapping(value = "/product/{name}",
            method = RequestMethod.GET)
    public String getProduct(@PathVariable("name") String name) {

        System.out.println("商品服务被调用了");
        return "order" + name;
    }
}

启动类

用来启动商品服务。

/**
 * 商品服务
 * @Author: 公众号 | 悟空聊架构
 * @Date: 2021/9/13 7:28
 * @Site: www.passjava.cn
 * @Github: https://github.com/Jackson0714/eureka-learning
 */
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {

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

}

pom.xml 文件

引入 Eureka Client 依赖。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
                  <version>Hoxton.SR10</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
 </dependencies>
</dependencyManagement>

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

测试商品服务是否正常启动

先按照 8006 端口启动一个商品服务,然后按照 8007 端口启动另外一个商品服务。

Eureka 控制台可以看到两个商品服务已启动。

测试访问商品服务

用 Postman 工具进行测试:

http://localhost:8006/getProduct/悟空聊架构专属商品

返回结果:

四、创建订单服务

订单服务和商品服务的区别

  • 多了一个 Ribbon 依赖。
  • 订单服务会调用商品服务。
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

订单服务调用商品服务的 API

@RestController
@Configuration
public class OrderServiceController {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {

        return new RestTemplate();
    }

    /**
     * 根据订单 id 查找商品信息
     * @param id 订单 id
     * @return 商品服务返回的数据
     */
    @RequestMapping(value = "/order/{id}", method = RequestMethod.GET)
    public String getOrder(@PathVariable("id") String id) {
        RestTemplate restTemplate = getRestTemplate();
        return restTemplate.getForObject("http://ProductService/product/" + id, String.class);
    }
}
我们看到有一个 @LoadBalanced 注解,这里做下说明:

RestTemplate 用来实现单个 http 请求的,加了 @LoadBalanced 注解后,就可以实现负载均衡。

测试

启动订单服务,IDEA 中可以看到

可以在 eureka 控制台看到订单服务在注册列表上。

测试访问订单 API

http://localhost:9091/order/悟空聊架构专属商品

测试结果:

说明订单服务 OrderService 通过 Eureka 拿到了的商品服务 ProductService 的 URL 信息,然后成功调用商品服务。如下 URl 所示,只知道商品服务的名字 ProductService,但是不知道具体的 IP 地址。

http://ProductService/product/

通过 Eureka 的注册表信息获取到了具体的 IP 地址。z

192.168.10.197:ProductService:8007
192.168.10.197:ProductService:8006

Eureka + 商品服务 + 订单服务 的演示案例已经完成。

接下来我们看下怎么把两个 Eureka Server 组成 Eureka 集群。

五、组成 Eureka 集群

修改本地 hosts 配置

host 文件添加两台 Eureka server 的地址映射,都为本地 localhost 地址

127.0.0.1 eureka-server1
127.0.0.1 eureka-server2

修改 Eureka Server 配置

两个服务互相向对方注册,第一个 Eureka 开放 8761 端口,注册到第二个 Eureka 的 8762 端口。

第一个 Eureka Server 的配置并启动

server:
  port: 8761
eureka:
  instance:
    hostname: eureka-server1
  client:
    serviceUrl:
      defaultZone: http://eureka-server1:8762/eureka/

修改第二个 Eureka Server 的配置,并启动

server:
  port: 8762
eureka:
  instance:
    hostname: eureka-server2
  client:
    serviceUrl:
      defaultZone: http://eureka-server2:8761/eureka/

访问 http://localhost:8761/

访问 http://localhost:8762/

mark

说明两台 Eureka Server 组成了一个集群环境。

六组成服务集群

接下来将服务注册到 Eureka 集群上。另外因为我最开始用的商品服务的名字是 ServiceA,而不是 ProductService,所以案例中的截图都是 ServiceA,订单服务对应的是 ServiceB,不影响案例演示

将服务 A 配置成注册到 Eureka 集群。在 defaultZone 配置中添加第二个 eureka 的服务地址。

server:
  port: 8006
spring:
  application:
    name: ServiceA
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka

然后启动服务 。

然后将服务 A 的 port 改为 8006 后,再次启动一个服务 A,相当于部署了两个服务 A,后续可以作为测试负载均衡的功能。

发现一个 Eureka 的问题,注册列表总是刷新不出最新的注册信息,重启 Eureka 服务后就刷出来了。

接着我们把服务 A 的passjava 方法,打下日志,后面观察两个服务 A 分别被服务 B 调用了几次。

七、修改调用者的配置

将服务 B 配置成注册到 Eureka 集群。在 defaultZone 配置中添加第二个 eureka 的服务地址。

两个 Eureka 服务中都有服务 B 的注册信息。

八、测试集群微服调用

多次刷新浏览器,访问订单服务的 API

http://localhost:9091/test/悟空

第一个服务 A 被服务 B 调用了 6 次:

第二个服务A 被服务 B 调用了 7 次:

根据上面的结果说明 Eurkea 集群 + Ribbon + 微服务集群的案例演示完成。

九、总结

本篇通过案例演示的方式,带着大家练习了如下内容:

  • 如何使用 Eureka 作为注册中心。
  • 如何将多个服务注册到 Eureka 上。
  • 通过使用 Eureka,服务间的调用不再需要知道对方的 IP 地址。
  • 如何将两个 Eureka Server 在本地组成 Eureka 集群。
  • 如何将多个服务注册到 Eureka 集群上。
  • 如何将多个相同的服务组成微服务集群。
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
4月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
5月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
928 3
|
3月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
Spring Boot 3.x 微服务架构实战指南
|
3月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
8月前
|
人工智能 Java API
Spring AI 实战|Spring AI入门之DeepSeek调用
本文介绍了Spring AI框架如何帮助Java开发者轻松集成和使用大模型API。文章从Spring AI的初探开始,探讨了其核心能力及应用场景,包括手动与自动发起请求、流式响应实现打字机效果,以及兼容不同AI服务(如DeepSeek、通义千问)的方法。同时,还详细讲解了如何在生产环境中添加监控以优化性能和成本管理。通过Spring AI,开发者可以简化大模型调用流程,降低复杂度,为企业智能应用开发提供强大支持。最后,文章展望了Spring AI在未来AI时代的重要作用,鼓励开发者积极拥抱这一技术变革。
2862 71
Spring AI 实战|Spring AI入门之DeepSeek调用
|
5月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
9月前
|
存储 人工智能 Java
Spring AI与DeepSeek实战四:系统API调用
在AI应用开发中,工具调用是增强大模型能力的核心技术,通过让模型与外部API或工具交互,可实现实时信息检索(如天气查询、新闻获取)、系统操作(如创建任务、发送邮件)等功能;本文结合Spring AI与大模型,演示如何通过Tool Calling实现系统API调用,同时处理多轮对话中的会话记忆。
1808 57
|
7月前
|
Cloud Native Java 微服务
Spring Boot 3.x 现代化应用开发实战技巧与最佳实践
本指南基于Spring Boot 3.x,融合微服务、云原生与响应式编程等前沿技术,打造现代化应用开发实践。通过构建智能电商平台案例,涵盖商品、订单、用户等核心服务,展示Spring WebFlux、OAuth 2.0认证、Spring Cloud Gateway路由、GraalVM原生编译等技术实现。同时提供Docker/Kubernetes部署方案及性能优化策略,助您掌握从开发到生产的全流程。代码示例详实,适合进阶开发者参考。
705 2

热门文章

最新文章