Skip to content
xiaoyang 的头像xiaoyang发布于 2024-05-166,065 字阅读约 20 分钟浏览加载中

3.Spring Cloud:生产者与消费者 ​

在微服务架构中,生产者和消费者扮演着核心角色。Spring Cloud作为一套强大的微服务框架,提供了丰富的功能和组件,使得开发者能够轻松构建和管理生产者和消费者之间的通信。本文将介绍Spring Cloud中的生产者和消费者概念,并探讨它们之间的交互方式。

1. 什么是生产者和消费者? ​

在微服务架构中,服务被拆分为多个小而自治的服务单元,每个单元都承担着特定的功能。其中,生产者是提供某种服务或数据的服务单元,它将自己的服务注册到注册中心,并等待消费者的请求。消费者则是通过调用生产者提供的服务来完成特定的业务逻辑。

生产者和消费者之间的通信通常是通过API进行,生产者将其可用的API暴露给消费者,消费者通过调用这些API来获取所需的功能或数据。

1.1.Spring Cloud中的生产者 ​

在Spring Cloud中,生产者可以使用Spring Boot快速构建。生产者将自己的服务注册到注册中心,让消费者能够发现并调用它。Spring Cloud提供了多种注册中心的实现,如Netflix Eureka、Consul和Zookeeper等,开发者可以根据实际需求选择适合的注册中心。

通过Spring Cloud提供的注解和组件,生产者可以方便地将自己的服务注册到注册中心,并提供RESTful API或其他形式的接口供消费者调用。同时,Spring Cloud还提供了负载均衡、服务熔断、链路追踪等功能,以提高生产者的性能和可靠性。

1.2 Spring Cloud中的消费者 ​

消费者通过注册中心发现并调用生产者的服务。Spring Cloud提供了多种方式来实现消费者的服务调用,其中最常用的是通过RESTful API进行通信。

在Spring Cloud中,消费者可以使用RestTemplate或Feign来发起对生产者服务的请求。RestTemplate是一个基于HTTP的客户端,可以发送HTTP请求并接收响应。Feign是一个声明式的HTTP客户端,它提供了更简洁的方式来定义和调用RESTful服务。

消费者可以通过注册中心获取生产者的服务实例列表,并使用负载均衡策略选择一个实例进行调用。Spring Cloud还提供了服务熔断和容错机制,以应对网络故障和服务不可用的情况,保证系统的稳定性和可靠性。

2.简单服务间调用代码示例 ​

下面,我们通过一个案例来展示下一个简单的SpringCloud来演示服务之间的调用。

2.1 创建主工程(Maven Project) ​

由于本案例中,会涉及到多个由 Spring Boot 创建的微服务,为了方便管理,这里我们采用 Maven 的多 Module 结构(即一个 Project 包含多个 Module)来构建工程。创建一个名为 spring-cloud-demo 的 Maven 主工程。

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

    <groupId>cn.ywenrou</groupId>
    <artifactId>spring-cloud-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>spring-cloud-demo</name>
    <description>springcloud学习记录</description>
    <url>www.blog.ywenrou.cn</url>

    <packaging>pom</packaging>
    <modules>
        <module>cloud-service1</module>
        <module>cloud-service2</module>
    </modules>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring.boot.version>2.1.7.RELEASE</spring.boot.version>
        <spring.cloud.version>Greenwich.SR2</spring.cloud.version>
    </properties>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>

            <!-- SpringBoot的依赖配置-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringCloud的依赖配置-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>

2.2 创建生产者 ​

选中我们的父工程点击New,在点击Module,创建一个名为 cloud-service1 的springboot项目作为生产者模块,依赖可以选取spring-web。若没有用插件可以复制下面pom.xml文件:

xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-service1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-service1</name>
    <description>cloud-service1</description>
    <parent>
        <groupId>cn.ywenrou</groupId>
        <artifactId>spring-cloud-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

Spring Cloud是基于rest的访问,所以我们添加一个Controller,在该Controller中提供一个访问入口:

java
@RestController
class HelloController {
    @RequestMapping(value = "/service1/hello", method = RequestMethod.GET)
    public String hello() {
        return "Hello Spring Cloud";
    }
}

启动CloudService1Application类中并访问接口localhost:8080/service1/hello:

2.3 创建消费者并进行服务间调用 ​

选中我们的父工程点击New,在点击Module,创建一个名为 cloud-service2 的springboot项目作为消费者模块,依赖选取spring-web,maven配置和生产者类似。此时8080端口以及被占用所以要在application.yml中设置一个未占用的端口,我这里设置server.port=9000 。

java
@RestController
class ConsumerController {

    @RequestMapping(value="/service2/hello")
    public String helloController() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForEntity("http://localhost:8080/service1/hello", String.class).getBody();
    }
}

启动CloudService2Application类并访问localhost:9000/service2/hello:

5. 结论 ​

至此模拟了一个springcloud的简单的例子消费者和生产者之前的调用,但是你有没有发现问题,当消费者需要调用生产者的API时,硬编码主机名和端口号是一种不灵活的做法。为了解决这个问题,Spring Cloud提供了Eureka作为服务注册中心,以便消费者能够动态地发现和调用生产者的服务。下文介绍讲Spring Cloud的Eureka作为服务注册中心

DISCUSSION

评论区

欢迎分享你的思考、补充或问题。

基于 VitePress 搭建