为了账号安全,请及时绑定邮箱和手机立即绑定

SpringCloud教程:从入门到初级应用

标签:
Spring Cloud
概述

SpringCloud教程介绍了基于Spring Boot的微服务开发框架,涵盖了服务注册与发现、配置中心、断路器和路由等功能。文章详细解释了如何搭建开发环境、创建项目以及实现服务发现和配置中心。此外,还提供了使用Hystrix实现断路器功能和Ribbon进行负载均衡的示例。

SpringCloud简介

SpringCloud 是一套基于 Spring Boot 框架的微服务开发工具,为开发者提供了在分布式系统(如配置管理、服务调度、服务发现、断路器、路由、微代理、集群状态管理等)中构建微服务应用的一整套框架。它通过集成一系列现有开源项目来实现这些功能,简化了分布式系统的设计,使开发者能够更加专注于业务逻辑的实现。

SpringCloud的优势和应用场景

  1. 简化微服务架构的开发:SpringCloud 提供了一套开箱即用的微服务组件,使开发者能快速搭建微服务架构。
  2. 增强服务治理能力:提供了服务注册与发现、配置中心、负载均衡、断路器、路由等功能,增强了系统的稳定性和可伸缩性。
  3. 支持多种编程语言:虽然 SpringCloud 主要支持 Java 语言,但其生态体系中也包含了一些支持其他语言的工具,如 SpringCloud Gateway 支持多种语言的 API 代理。

常见的SpringCloud组件介绍

  1. 服务注册与发现:Eureka、Consul 和 Zookeeper 是常用的注册中心,用于管理服务的注册与发现。
  2. 配置中心:SpringCloud Config 用于集中管理和分发应用的配置信息。
  3. 服务网关:SpringCloud Gateway、Zuul 用于构建 API 网关,实现请求路由和过滤。
  4. 断路器:Hystrix、Resilience4j 用于实现服务熔断机制,保障系统的稳定性。
  5. 负载均衡:Ribbon 用于实现客户端负载均衡。
  6. 服务追踪:SpringCloud Sleuth 用于服务调用链路追踪。
  7. 消息总线:SpringCloud Bus 通过消息总线实现配置更新的广播。
快速搭建SpringCloud开发环境

开发工具的安装与配置

为了开始 SpringCloud 开发,需要先安装一些必要的开发工具,比如 Java 开发工具包(JDK)、Maven 构建工具、IDE(如 IntelliJ IDEA 或 Eclipse)。

  1. 安装 JDK

    • 下载并安装最新版本的 JDK。
    • 配置环境变量 JAVA_HOMEPATH
  2. 安装 Maven

    • 下载 Maven 并解压。
    • 设置环境变量 MAVEN_HOMEPATH
  3. 安装开发工具
    • 选择合适的 IDE,如 IntelliJ IDEA 或 Eclipse。
    • 安装 Spring Boot 插件,这将提供 Spring Boot 项目模板和更多的 Spring Boot 支持。

创建第一个SpringCloud项目

  1. 创建 Spring Boot 项目

    • 使用 IDE 创建一个新的 Spring Boot 项目。可以在 IntelliJ IDEA 中通过 Spring Initializr 创建,选择 Spring Cloud Starter 作为依赖。
    • 确保项目中包含 Spring Boot Starter Web 和 Spring Cloud Starter Config 依赖。
  2. 配置 Maven 依赖

    • 打开项目的 pom.xml 文件,确保包含以下依赖:

      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
      </parent>
      
      <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <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>
            <version>2.2.6.RELEASE</version>
        </dependency>
      </dependencies>
      
      <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
      </dependencyManagement>
  3. 启动项目
    • 启动项目可以使用 IDE 内置的 Spring Boot 启动功能或者直接运行 main 方法。
    • 确保项目能够正常启动并访问。
    • 示例启动类代码如下:
      @SpringBootApplication
      @EnableEurekaClient
      public class DemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
      }

项目的基本结构和依赖管理

  1. 项目的基本结构

    • main/resources/application.yml:项目的配置文件。
    • main/java/com/example/demo/:存放应用程序的主要代码。
    • main/java/com/example/demo/DemoApplication.java:项目的主启动类。
  2. 依赖管理
    • pom.xml 文件是项目依赖的管理文件。通过引入 Spring Cloud Starter 依赖,可以方便地使用 Spring Cloud 提供的功能。
    • 可以在 pom.xml 中添加其他相关依赖,如 spring-cloud-starter-netflix-zuulspring-cloud-starter-netflix-hystrix
SpringCloud服务发现与配置中心

使用Eureka实现服务发现

Spring Cloud Eureka 是一个基于 Netflix Eureka 实现的服务注册与发现组件。服务提供者将自己注册到 Eureka Server,并周期性发送心跳来维持自己的存活状态;服务消费者从 Eureka Server 获取服务提供者的地址列表,实现服务调用。

  1. 服务提供者的配置

    • application.yml 中配置服务提供者向 Eureka 注册:
      spring:
      application:
        name: service-provider
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
  2. 服务消费者的配置

    • application.yml 中配置服务消费者从 Eureka 获取服务提供者的地址:
      spring:
      application:
        name: service-consumer
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
  3. 服务提供者的实现

    • 示例代码如下:

      @SpringBootApplication
      @EnableEurekaClient
      public class ServiceProviderApplication {
        public static void main(String[] args) {
            SpringApplication.run(ServiceProviderApplication.class, args);
        }
      }
      
      @RestController
      @RequestMapping("/service-provider")
      public class ServiceProviderController {
        @GetMapping("/hello")
        public String sayHello() {
            return "Hello, this is service provider!";
        }
      }
  4. 服务消费者的实现

    • 示例代码如下:

      @SpringBootApplication
      @EnableDiscoveryClient
      public class ServiceConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ServiceConsumerApplication.class, args);
        }
      }
      
      @RestController
      @RequestMapping("/service-consumer")
      public class ServiceConsumerController {
        @Autowired
        private DiscoveryClient discoveryClient;
      
        @GetMapping("/hello")
        public String sayHello() {
            List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
            if (instances != null && !instances.isEmpty()) {
                ServiceInstance instance = instances.get(0);
                String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/service-provider/hello";
                return restTemplate.getForObject(url, String.class);
            }
            return "Service provider not found!";
        }
      }

使用Config Server实现配置中心

Spring Cloud Config Server 提供了集中化的配置管理功能,可以将配置文件集中存储在 Git、SVN 等版本控制系统中。服务应用从 Config Server 获取配置信息,使配置变得集中化、可管理。

  1. 启动 Config Server

    • application.yml 中配置 Config Server:
      spring:
      application:
        name: config-server
      server:
      port: 8888
      spring:
      cloud:
        config:
          server:
            git:
              uri: https://github.com/your-username/config-repo
              username: your-username
              password: your-password
  2. 配置文件的结构

    • 配置文件的结构如下:spring/application.ymlspring/default.yml
    • 每个文件对应不同环境的配置,例如 application.yml 对应开发环境,default.yml 对应默认环境。
    • 文件命名规则为 spring/${spring.application.name}-${profile}.yml,其中 ${spring.application.name} 是应用的名字,${profile} 是配置文件的环境标识(如 devprod)。
  3. 服务应用的配置

    • 在服务应用中配置从 Config Server 获取配置:
      spring:
      cloud:
        config:
          name: config-client
          profile: dev
          label: master
          uri: http://localhost:8888
  4. 服务应用中的配置获取

    • 在服务应用中可以通过 @Value 注解获取配置值:

      @SpringBootApplication
      public class ConfigClientApplication {
        @Value("${application.name}")
        private String appName;
      
        public static void main(String[] args) {
            SpringApplication.run(ConfigClientApplication.class, args);
        }
      
        @RestController
        @RequestMapping("/config")
        public class ConfigController {
            @GetMapping("/name")
            public String getAppName() {
                return appName;
            }
        }
      }
SpringCloud断路器与负载均衡

使用Hystrix实现断路器功能

断路器是一种容错机制,用于保护服务在调用失败时不会导致服务雪崩。Spring Cloud Hystrix 通过封装系统间的异步交互来实现断路器功能,包括请求的隔离、缓存、降级等。

  1. 在服务提供者中使用 Hystrix

    • pom.xml 中添加 Hystrix 依赖:
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 使用 @HystrixCommand 注解实现服务调用的降级:

      @RestController
      @RequestMapping("/service-provider")
      public class ServiceProviderController {
        @GetMapping("/hello")
        @HystrixCommand(fallbackMethod = "fallbackHello")
        public String sayHello() {
            // 业务逻辑
            return "Hello, this is service provider!";
        }
      
        public String fallbackHello() {
            return "Fallback: Service provider is not available!";
        }
      }
  2. 在服务消费者中使用 Hystrix

    • pom.xml 中添加 Hystrix 依赖:
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 使用 @HystrixCommand 注解实现服务调用的降级:

      @RestController
      @RequestMapping("/service-consumer")
      public class ServiceConsumerController {
        @Autowired
        private RestTemplate restTemplate;
      
        @GetMapping("/hello")
        @HystrixCommand(fallbackMethod = "fallbackHello")
        public String sayHello() {
            String url = "http://localhost:8080/service-provider/hello";
            return restTemplate.getForObject(url, String.class);
        }
      
        public String fallbackHello() {
            return "Fallback: Service provider is not available!";
        }
      }

使用Ribbon实现负载均衡

Ribbon 是一个客户端负载均衡器,内置了多种负载均衡算法,如轮询、随机、最少请求数量等。Spring Cloud Ribbon 与 Eureka 结合使用可以实现服务间的负载均衡。

  1. 在服务提供者中使用 Ribbon

    • pom.xml 中添加 Ribbon 依赖:
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 配置 Ribbon 的负载均衡算法:
      spring:
      application:
        name: service-provider
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      ribbon:
      NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
  2. 在服务消费者中使用 Ribbon

    • pom.xml 中添加 Ribbon 依赖:
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 使用 Ribbon 调用服务提供者:

      @RestController
      @RequestMapping("/service-consumer")
      public class ServiceConsumerController {
        @Autowired
        private LoadBalancerClient loadBalancerClient;
      
        @GetMapping("/hello")
        public String sayHello() {
            ServiceInstance serviceInstance = loadBalancerClient.choose("service-provider");
            String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/service-provider/hello";
            return restTemplate.getForObject(url, String.class);
        }
      }
SpringCloud路由与API网关

使用Zuul实现API网关

Spring Cloud Zuul 是一个 API 网关,用于服务路由和过滤器,可以将外部调用路由到内部微服务中,并对请求进行一系列过滤处理。

  1. 启动 Zuul API 网关

    • pom.xml 中添加 Zuul 依赖:
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 配置 Zuul 的路由规则:
      spring:
      application:
        name: api-gateway
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      zuul:
      routes:
        service-provider:
          path: /api/service-provider/**
          serviceId: service-provider
  2. 使用 Zuul 实现路由

    • 在 Zuul API 网关中定义过滤器和路由规则:

      @SpringBootApplication
      @EnableZuulProxy
      public class ApiGatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(ApiGatewayApplication.class, args);
        }
      }
      
      @Configuration
      public class ZuulConfig {
        @Bean
        public ZuulFilter customRouteFilter() {
            return new CustomRouteFilter();
        }
      }
      
      public class CustomRouteFilter extends ZuulFilter {
        @Override
        public String filterType() {
            return "pre";
        }
      
        @Override
        public int order() {
            return 0;
        }
      
        @Override
        public boolean shouldFilter() {
            return true;
        }
      
        @Override
        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            ctx.addZuulOrigin();
            return null;
        }
      }
    • 请求路由的示例代码:

      @RestController
      @RequestMapping("/api")
      public class GatewayController {
        @Autowired
        private DiscoveryClient discoveryClient;
      
        @GetMapping("/service-provider/hello")
        public String sayHello() {
            List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
            if (instances != null && !instances.isEmpty()) {
                ServiceInstance instance = instances.get(0);
                String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/service-provider/hello";
                return restTemplate.getForObject(url, String.class);
            }
            return "Service provider not found!";
        }
      }

路由规则的配置与使用

  1. 配置路由规则

    • application.yml 中定义路由规则:
      zuul:
      routes:
        service-provider:
          path: /api/service-provider/**
          serviceId: service-provider
  2. 使用路由规则
    • 通过定义的路由规则,外部请求可以路由到指定的服务提供者:
      @RestController
      @RequestMapping("/api")
      public class GatewayController {
        @GetMapping("/service-provider/hello")
        public String sayHello() {
            return "Hello, this is service provider!";
        }
      }
实战演练:构建一个简单的微服务系统

设计一个简单的微服务架构

假设我们设计一个简单的图书管理系统,包括三个微服务:图书服务、用户服务和订单服务。图书服务负责管理图书信息,用户服务负责管理用户信息,订单服务负责管理订单信息。

  1. 图书服务

    • 主要负责图书的增删改查操作。
    • 使用 Spring Boot 和 Spring Data JPA 进行数据库操作。
  2. 用户服务

    • 主要负责用户的注册、登录、个人信息的增删改查操作。
    • 使用 Spring Boot 和 Spring Data JPA 进行数据库操作。
  3. 订单服务
    • 负责订单的创建、查询和取消操作。
    • 使用 Spring Boot 和 Spring Data JPA 进行数据库操作。
    • 依赖于图书服务和用户服务。

整合上述功能实现一个测试项目

  1. 启动 Eureka Server

    • 创建 Eureka Server 项目,配置 Eureka Server:

      server:
      port: 8761
      
      eureka:
      instance:
        hostname: localhost
      client:
        register-with-eureka: false
        fetch-registry: false
        server: true
  2. 启动图书服务

    • pom.xml 中添加相关依赖:
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 配置 Eureka Client:

      spring:
      application:
        name: book-service
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      server:
      port: 8081
    • 启动类代码:
      @SpringBootApplication
      @EnableEurekaClient
      public class BookServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(BookServiceApplication.class, args);
        }
      }
  3. 启动用户服务

    • pom.xml 中添加相关依赖:
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 配置 Eureka Client:

      spring:
      application:
        name: user-service
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      server:
      port: 8082
    • 启动类代码:
      @SpringBootApplication
      @EnableEurekaClient
      public class UserServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(UserServiceApplication.class, args);
        }
      }
  4. 启动订单服务

    • pom.xml 中添加相关依赖:
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 配置 Eureka Client:

      spring:
      application:
        name: order-service
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      server:
      port: 8083
    • 启动类代码:
      @SpringBootApplication
      @EnableEurekaClient
      public class OrderServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderServiceApplication.class, args);
        }
      }
  5. 启动 API Gateway

    • pom.xml 中添加相关依赖:
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.6.RELEASE</version>
      </dependency>
    • 配置 Eureka Client 和 Zuul 路由:

      spring:
      application:
        name: api-gateway
      eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      server:
      port: 8080
      zuul:
      routes:
        book-service:
          path: /api/book/**
          serviceId: book-service
        user-service:
          path: /api/user/**
          serviceId: user-service
        order-service:
          path: /api/order/**
          serviceId: order-service
    • 启动类代码:
      @SpringBootApplication
      @EnableZuulProxy
      public class ApiGatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(ApiGatewayApplication.class, args);
        }
      }
  6. 整合服务

    • 在订单服务中调用图书服务和用户服务:

      @RestController
      @RequestMapping("/api")
      public class OrderController {
        @Autowired
        private RestTemplate restTemplate;
      
        @GetMapping("/order/create/{bookId}/{userId}")
        public String createOrder(@PathVariable Long bookId, @PathVariable Long userId) {
            // 假设图书服务和用户服务已经注册到 Eureka 服务器
            String bookUrl = "http://book-service/api/book/" + bookId;
            String userUrl = "http://user-service/api/user/" + userId;
      
            // 调用图书服务和用户服务获取信息
            Book book = restTemplate.getForObject(bookUrl, Book.class);
            User user = restTemplate.getForObject(userUrl, User.class);
      
            // 创建订单逻辑
            // ...
      
            return "Order created successfully!";
        }
      }
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消