初识Spring Cloud

面对环视的强敌,我一直问自己这样一个问题:现在开始还来得及吗?面对残酷的现实世界,我也不断寻找让自己躺平的理由,可没有一个理由可以让我坦然接受现在的一切。于是,我决定强攻!可这满头乱发,该如何抓呢?好不容易揪住一根银丝,却不知道应该如何开始!只能日日唉声叹气,毫无进展!可一切总要有个说法,徒自烦闷终是于事无补。因此我决定暂时放弃微服务理论部分的知识,直接学习微服务框架Spring Cloud的用法,同时研究其源码。

1 Spring Cloud是什么?

学习一个东西,我们首先要弄清楚三个问题:是什么,干什么,怎么用。下面先来看一下通义千问大模型关于Spring Cloud的描述:

Spring Cloud是一个由Pivotal团队提供的基于Java的微服务工具集它为开发者设计并实现微服务架构提供了全面的解决方案Spring Cloud构建在Spring Boot之上,其核心目标是简化分布式系统和服务的开发流程,通过一系列的开源组件和工具,为开发者提供了服务发现注册、配置管理、熔断器、智能路由、微代理、控制总线、一次性令牌、全局锁、主节点选举、分布式会话、集群状态管理等分布式系统中常见的功能模块

简而言之,Spring Cloud是一个针对微服务架构设计的标准化一站式开发框架,它通过整合和封装各种成熟的第三方库和服务,为开发者提供了一整套开箱即用的微服务开发工具及最佳实践,使得在搭建和管理分布式系统时能更高效、更便捷,从而更好地应对云计算环境下的服务治理挑战

通过这段描述,我们可以得出这样一些信息:Spring Cloud是一套基于Java的微服务工具集,为开发者提供了在分布式系统(微服务架构)中快速构建、部署和管理微服务的一站式解决方案。它是在Spring Boot基础上创建的,用于简化分布式系统和服务的复杂性,促进各服务间的协同工作和统一管理。Spring Cloud整合并封装了一系列经过实战检验的成熟框架和组件,譬如:

  1. 服务注册与发现:通过 Eureka 或 ZooKeeper 提供服务注册与发现机制
  2. 负载均衡与服务调用:利用 Ribbon 和 Feign 进行客户端负载均衡和服务调用
  3. 断路器:采用 Hystrix 实现服务容错和断路器模式,保护服务免受级联故障的影响
  4. 网关服务:借助 Zuul 或 Spring Cloud Gateway 实现 API 路由、过滤、安全控制等功能
  5. 配置中心:使用 Spring Cloud Config 分布式管理不同环境下的应用配置
  6. 服务跟踪:结合 Zipkin 或 Sleuth 可以实现实时监控和全链路追踪
  7. 消息队列支持:通过与 RabbitMQ 或 Kafka 集成,实现异步消息处理
  8. 控制总线和分布式事务支持:如通过 Spring Cloud Bus 实现事件驱动的配置刷新等

2 Spring Cloud怎么用?

通过第一小节,我们了解了Spring Cloud的定义,同时也知道了Spring Cloud可以用来做些什么?可是对于这个工具如何使用,我们却鲜有提及。这一小节我们就来重点聊聊Spring Cloud的用法。然而,因为Spring Cloud是一套微服务工具集,其涉及的框架和组件非常多,譬如:服务注册与发现、负载均衡与服务调用、网关服务、配置中心、断路器、服务跟踪等等,所以想在一小节中就把Spring Cloud的用法完全弄懂是不太现实的。这就好比想一口吃成胖子,实属一厢情愿。但是,我们也不能因此放弃对这个框架用法的讨论!因此本小节我们将从一个小点(Spring Cloud中的注册中心组件)开始,通过对这个小点的分析(学习这个组件的基本用法),然后逐步攻克Spring Cloud这座高大的城池(学会Spring Cloud的用法)。在开始前,我们要先了解一下注册中心这个概念。

注册中心,在分布式系统特别是微服务架构中,是一种服务注册与发现的关键组件它本质上是一个服务注册表(service registry),用于存储和管理各个服务实例的服务元数据和网络位置信息(如IP地址、端口号),确保服务间的相互调用能够准确高效地找到对方。具体来说,注册中心的作用有:

  1. 服务注册:服务提供方启动时,将自己提供的服务信息(服务名、服务地址、健康状态等)注册到注册中心
  2. 服务发现:服务消费方需要调用某个服务时,向注册中心查询所需服务的可用实例列表,获取服务提供方的具体访问地址
  3. 心跳检测与实例管理:注册中心通过心跳机制与服务实例保持连接,实时更新服务实例的状态,比如剔除掉不健康的或者已经下线的服务实例
  4. 服务路由与负载均衡:虽然注册中心本身并不直接提供负载均衡功能,但它可以配合外部的负载均衡器或客户端内部的负载均衡策略,实现对服务消费者的透明化服务路由

在实际应用中,常见的注册中心产品和技术有:

  1. Netflix Eureka:由Netflix开发的服务注册与发现组件,广泛应用于基于Spring Cloud构建的微服务系统中
  2. HashiCorp Consul:除了服务注册与发现外,还提供了KV存储、健康检查等功能
  3. Apache ZooKeeper:虽然不是专门设计为服务注册中心,但在很多场景下可以用来实现服务注册与发现
  4. Alibaba Nacos:阿里巴巴开源的一个更综合的服务发现、配置管理和服务管理平台。

无论如何,通过注册中心,微服务架构得以灵活扩展和动态调整,实现了服务间松耦合和高可用性。下面就来看看如何利用Spring Cloud中的Eureka组件来实现一个注册中心吧!

2.1 创建Eureka注册中心

首先创建一个Maven项目,取名为eureka-server。然后在项目中的pom.xml文件中配置Eureka依赖信息,该文件的详细信息如下所示:

<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>

    <groupId>org.com.chinasoft</groupId>
    <artifactId>springcloud-eureka-server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springcloud-eureka-server</name>
    <!--<url>http://maven.apache.org</url>-->

    <!--引入springboot-parent父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <!--引入 springcloud 的 euekea server 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!--指定下载源和使用springcloud的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

注意:上述代码中的spring-cloud-starter-netflix-eureka-server,就是我们要引入项目中的eureka依赖。

接着编写启动类。该启动的名字为EurekaServerApplication。其源码详细如下所示(注意这个类上的注解@EnableEurekaServer,它表示开启Eureka Server):

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 *
 */
@SpringBootApplication
@EnableEurekaServer // 当前使用eureka的server
public class EurekaServerApplication {

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

}

最后编写项目配置文件,即application.yml。在该配置文件中添加相关配置项,譬如:项目名称(spring.application.name)、端口(server.port)等。配置文件详细信息如下所示:

server:
  port: 8700 # 端口自己决定

# 指定当前eureka客户端的注册地址,也就是eureka服务的提供方,当前配置的服务的注册服务方
eureka:
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
    register-with-eureka: false #自身 不在向eureka注册
    fetch-registry: false  #启动时禁用client的注册
  instance:
    hostname: localhost

#指定应用名称
spring:
  application:
    name: eureka-server

2.2 创建服务提供者

接着创建一个Maven项目,取名为eureka-client。然后在项目中的pom.xml文件中配置相关依赖信息,该文件的详细信息如下所示:

<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>

    <groupId>org.com.chinasoft</groupId>
    <artifactId>springcloud-eureka-client</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springcloud-eureka-client</name>
    <!--<url>http://maven.apache.org</url>-->

    <!--引入springboot-parent父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <!--引入 springcloud 的 euekea server 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!--指定下载源和使用springcloud的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

注意:上述代码中的spring-cloud-starter-netflix-eureka-client,就是我们要引入项目中的eureka依赖。

接着编写启动类。该启动的名字为EurekaServiceApplication。其源码详细如下所示(注意这个类上的注解@EnableDiscoveryClient,它表示当前服务是一个Eureka的客户端):

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 *
 */
@SpringBootApplication
@EnableDiscoveryClient // 代表自己是一个服务提供方
public class EurekaServiceApplication {

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

}

再次编写Controller类,其中控制器用于接收客户端请求。这个Controller类的详细代码如下所示:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/Hello")
public class Controller {

    @RequestMapping("/World")
    public String helloWorld(String s) {
        System.out.println("传入的值为:" + s);
        return "传入的值为:" + s;
    }

}

最后编写项目配置文件,即application.yml。在该配置文件中添加相关配置项,譬如:项目名称(spring.application.name)、端口(server.port)等。配置文件详细信息如下所示:

server:
  port: 8701 # 服务提供方

# 指定当前eureka客户端的注册地址,
eureka:
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:8700/eureka
  instance:
    hostname: localhost

#当前服务名称
spring:
  application:
    name: eureka-service

2.3 创建服务消费者

接着创建一个Maven项目,取名为eureka-consumer。然后在项目中的pom.xml文件中配置相关依赖信息,该文件的详细信息如下所示:

<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>

    <groupId>org.com.chinasoft</groupId>
    <artifactId>eureka-consumer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springcloud-ribbon</name>
    <!--<url>http://maven.apache.org</url>-->

    <!--引入springboot-parent父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <!--引入 springcloud 的 euekea server 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--引入 springcloud 的 ribbon 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!--指定下载源和使用springcloud的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

注意:上述代码中的spring-cloud-starter-netflix-eureka-client和spring-cloud-starter-ribbon,就是我们要引入到项目中的依赖。

接着编写启动类。该启动的名字为EurekaConsumerApplication。其源码详细如下所示(注意这个类上的注解@EnableDiscoveryClient,它表示当前服务是一个Eureka的客户端):

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@SpringBootApplication
@EnableDiscoveryClient // 当前使用eureka的server
public class EurekaConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaConsumerApplication.class, args);
    }
}

再次编写Controller和配置类,其中控制器用于接收客户端请求,配置类用于向容器中注入关键对象,其详细代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/Hello")
public class ConsumerController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/Consumer")
    public String helloWorld(String s) {
        System.out.println("传入的值为:" + s);
        //第一种调用方式
        //String forObject = new RestTemplate().getForObject("http://localhost:8071/Hello/World?s=" + s, String.class);

        //第二种调用方式
        //根据服务名 获取服务列表 根据算法选取某个服务 并访问某个服务的网络位置。
        // ServiceInstance serviceInstance = loadBalancerClient.choose("EUREKA-SERVICE");
        // String forObject = new RestTemplate().getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/Hello/World?s="+s,String.class);

        //第三种调用方式 需要restTemplate注入的方式
        String forObject = restTemplate.getForObject("http://EUREKA-SERVICE/Hello/World?s=" + s, String.class);
        return forObject;
    }

}

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class Beans {

    //管理简单对象
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

最后编写项目配置文件,即application.yml。在该配置文件中添加相关配置项,譬如:项目名称(spring.application.name)、端口(server.port)等。配置文件详细信息如下所示:

server:
  port: 8702 # 服务消费方

# 指定当前eureka客户端的注册地址,
eureka:
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:8700/eureka
  instance:
    hostname: localhost

#当前服务名称
spring:
  application:
    name: eureka-consumer

3 总结

通过这篇文章,我对Spring Cloud有了初步的了解:Spring Cloud是一个基于Java的微服务工具集它为开发者设计并实现微服务架构提供了全面的解决方案。因此个人理解Spring Cloud就是一个方便开发者开发分布式项目的工具集其整合并封装了一系列经过实战检验的成熟框架和组件,譬如:服务注册与发现、负载均衡与服务调用、网关服务、配置中心、断路器、服务跟踪等等,同时Spring Cloud还对消息队列、控制总线和分布式事务提供了支持。总而言之,通过Spring Cloud工程师可以很容易的设计和开发出一套具有可靠性能的分布式应用。

又是通过这篇文章,我对注册中心这个概念有了基本了解:注册中心,在分布式系统尤其是微服务架构中,是一种服务注册与发现的关键组件其本质上是一个服务注册表(service registry),用于存储和管理各个服务实例的网络位置信息(如IP地址、端口号)和服务元数据,确保服务间的相互调用能够准确高效地找到对方。总体来看,注册中心就是一个类似于操作系统的注册表,通过这个注册表我们能够很容易的找到自己想用的服务

最后还是通过这篇文章,我对Spring Cloud这个工具集中的Eureka组件的用法有了一定的了解:知道了如何编写Eureka服务方(即注册中心)、如何编写Eureka服务(即服务提供者)、如何编写Eureka消费者。但是这些信息是如何被Eureka管理的呢?服务提供者是如何注册到Eureka服务端(注册中心的)?服务提供者和Eureka服务端之间是通过什么形式的连接通讯的?Eureka服务端是如何知道服务提供者的状态的(上线、下线)?Eureka消费者是如何从Eureka服务端拉取存活的服务的?Eureka消费者是如何调用Eureka服务提供者的?等等,这些问题都需要我们通过后续的文章一步步深入梳理。

相关推荐

  1. Dockerfile

    2024-04-03 22:22:01       57 阅读
  2. MyBatis

    2024-04-03 22:22:01       67 阅读
  3. docker

    2024-04-03 22:22:01       49 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-03 22:22:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-03 22:22:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-03 22:22:01       87 阅读
  4. Python语言-面向对象

    2024-04-03 22:22:01       96 阅读

热门阅读

  1. C++引用python代码

    2024-04-03 22:22:01       46 阅读
  2. 信奥赛一本通 【例4.2】天安门广场的面积

    2024-04-03 22:22:01       40 阅读
  3. pygame--坦克大战(二)

    2024-04-03 22:22:01       39 阅读
  4. 供应商管理软件:供应商绩效评估实用清单

    2024-04-03 22:22:01       40 阅读
  5. ChatGPT学术写作攻略:让论文更具深度

    2024-04-03 22:22:01       38 阅读
  6. 宝塔面板无法访问 404 not found

    2024-04-03 22:22:01       33 阅读
  7. Memcached 教程之 Memcached add 命令(六)

    2024-04-03 22:22:01       35 阅读