Consul + Spring Cloud OpenFeign 搭建分布式微服务

390 阅读2分钟

Consul + Spring Cloud OpenFeign 搭建分布式微服务

项目工程结构

.
├── service.consumer
│   ├── pom.xml
│   └── src
│       └── main
│           ├── java
│           │   └── com
│           │       └── kabai
│           │           ├── ConsumerController.java
│           │           ├── ConsumerServiceApplication.java
│           │           └── ProviderClient.java
│           └── resources
│               └── application.yml
└── service.provider
    ├── pom.xml
    └── src
        └── main
            ├── java
            │   └── com
            │       └── kabai
            │           ├── ProviderController.java
            │           └── ProviderServiceApplication.java
            └── resources
                └── application.yml

在构建分布式微服务系统时,使用Consul作为服务注册中心和OpenFeign作为服务之间通信的工具可以极大地简化开发和部署过程。本文将介绍如何使用Consul和OpenFeign搭建一个简单的微服务架构,包括服务注册中心、服务提供者和服务消费者。

版本

我这里本地配置了两个版本,这里演示项目,需要用到jdk17,maven 3.9.7。

  • jdk17
  • maven 3.9.7
  • Spring Boot 3.3.0
  • Packaging jar
# 配置JDK路径
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home

# 默认使用 JDK8
export JAVA_HOME=$JAVA_8_HOME
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.

# 配置alias命令动态切换JDK版本
alias jdk8='export JAVA_HOME=$JAVA_8_HOME'
alias jdk17='export JAVA_HOME=$JAVA_17_HOME'

export JAVA_HOME
export CLASSPATH

# 配置maven路径
export MAVEN_3_6_1_HOME=/Users/mac/env/apache-maven-3.6.1
export MAVEN_3_9_7_HOME=/Users/mac/env/apache-maven-3.9.7

# 默认使用 3.6.1
export MAVEN_HOME=$MAVEN_3_6_1_HOME
export PATH=$MAVEN_HOME/bin:$PATH

# 配置alias命令动态切换MAVEN版本
alias mvn3.6='export MAVEN_HOME=$MAVEN_3_6_1_HOME && export PATH=$MAVEN_HOME/bin:${PATH//:$MAVEN_3_9_7_HOME\/bin/}'
alias mvn3.9='export MAVEN_HOME=$MAVEN_3_9_7_HOME && export PATH=$MAVEN_HOME/bin:${PATH//:$MAVEN_3_6_1_HOME\/bin/}'

# 导出MAVEN_HOME和PATH变量
export MAVEN_HOME
export PATH

步骤 1: 安装Consul配置中心

确保Consul安装并运行。你可以在本地或者服务器上安装并运行Consul,以下是一些基本步骤:

# 下载并解压Consul
wget https://releases.hashicorp.com/consul/1.10.3/consul_1.10.3_linux_amd64.zip
unzip consul_1.10.3_linux_amd64.zip

# 运行Consul
/root/consul agent -dev -client=0.0.0.0

步骤 2: 创建springboot项目 - 从springboot官网

步骤 3: 创建服务提供者(service-provider)

接下来,我们创建一个服务提供者,它将向Consul注册自己的服务,并提供API服务。

  1. 创建一个新的Spring Boot应用程序
  • @EnableDiscoveryClient
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderServiceApplication {

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

}
  1. 添加consul-discovery和Spring Web的依赖pom.xml文件中。
  • consul-discovery
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
  • 完整pom.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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kabai</groupId>
    <artifactId>service.provider</artifactId>
    <version>1.0.0-RELEASE</version>
    <name>service.provider</name>
    <description>consul config server center for provider</description>
    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2023.0.2</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <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.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. 配置provider-service连接属性,以连接到Consul服务器。
spring:
  application:
    name: provider-service
  cloud:
    consul:
      host: 60.35.xx.xx
      port: 8500
      discovery:
        instance-id: provider-service:myhost:12345
        service-name: provider-service
        heartbeat:
          enabled: true
      config:
        enabled: true
        format: yaml
        default-context: application
        profile-separator: ','
        fail-fast: true
        data-key: application.yml
  config:
    import: "optional:consul:"
server:
  port: 8081
  1. 创建一个REST控制器,提供API服务。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProviderController {

    @GetMapping("/hello")
    public String sayHello(@RequestParam String name) {
        return "Hello, " + name;
    }
}

步骤 4: 创建服务消费者(service-consumer)

最后,我们创建一个服务消费者,它将使用Feign来调用服务提供者的API。

  1. 创建一个新的Spring Boot应用程序
  • @EnableDiscoveryClient
  • @EnableFeignClients
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerServiceApplication {

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

}
  1. 添加OpenFeign、Consul Discovery Client和Spring Web的依赖pom.xml文件中。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 完整pom.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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kabai</groupId>
    <artifactId>service.consumer</artifactId>
    <version>1.0.0-RELEASE</version>
    <name>service.consumer</name>
    <description>consul config server center for consumer</description>
    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2023.0.2</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <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.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. 配置consumer-service连接属性,以连接到Consul服务器。
spring:
  application:
    name: consumer-service
  cloud:
    consul:
      host: 60.35.xx.xx
      port: 8500
      discovery:
        instance-id: consumer-service:myhost:67890
        service-name: consumer-service
        heartbeat:
          enabled: true
      config:
        enabled: true
        format: yaml
        default-context: application
        profile-separator: ','
        fail-fast: true
        watch:
          delay: 10s
server:
  port: 8082
  1. 创建一个Feign客户端接口,用于声明服务提供者的API。
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "provider-service")
public interface ProviderClient {

    @GetMapping("/hello")
    String sayHello(@RequestParam String name);
}
  1. 暴露一个HTTP接口 来调用sayHello方法。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConsumerController {

    @Autowired
    private ProviderClient providerClient;

    @GetMapping("/say-hello")
    public String sayHello(@RequestParam String name) {
        return providerClient.sayHello(name);
    }
}

项目启动

确认服务环境

  • jdk:jdk17
  • maven:3.9.4

依次启动

  • Consul
  • service-provider
  • service-consumer

编译、打包、运行

  • 运行Consul
/root/consul agent -dev -client=0.0.0.0
  • service.provider
jdk17
mvn3.9
mvn clean package
cd target
java -jar service.provider-1.0.0-RELEASE.jar

compressed_WX20240603-220638@2x.png

  • service.consumer
jdk17
mvn3.9
mvn clean package
cd target
java -jar service.consumer-1.0.0-RELEASE.jar

compressed_WX20240603-220701@2x.png

Consul Dashboard

http://60.35.xx.xx:8500/ui

compressed_WX20240605-114954@2x.png

浏览器访问测试接口

http://localhost:8082/say-hello?name=World

compressed_WX20240605-115028@2x.png