Spring Cloud +Gateway + Nginx +Docker 实现高可用网关集群_docker nginx gateway-程序员宅基地

技术标签: # docker  nginx  spring cloud  # Nginx  # Spring Cloud  gateway  

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文主要介绍实现在 docker 中部署 高可用的网关集群微服务,涉及到的技术栈如下:
 SpringCloud、Eureka、Gateway、Nginx 、Docker 

代码地址: Spring-Cloud-Demo

一、项目搭建

Spring Cloud 中的业务不做展示,这里只展示相关的配置

1、parent

该目录下只有一个 pom.xml 文件,作为所有微服务的 父级pom,便于项目依赖的版本控制,以及不同环境的打包配置等

<?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>2.6.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.study</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <!--    版本控制-->
    <properties>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>2021.0.3</spring-cloud.version>
        <packaging.type>jar</packaging.type>
        <lombok.version>1.18.24</lombok.version>
        <feign-httpClienr.version>10.7.4</feign-httpClienr.version>
        <ribbon.version>2.7.18</ribbon.version>
    </properties>
    <!--maven 仓库-->
    <repositories>
        <repository>
            <id>central</id>
            <name>Nexus aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>
    <!--版本统一控制-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <optional>true</optional>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--        Feign 使用 httpClient -->
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-httpclient</artifactId>
                <version>${feign-httpClienr.version}</version>
            </dependency>
            <!--        ribbon 点对点直连 和 局部负载均衡 不可用-->
            <dependency>
                <groupId>com.netflix.ribbon</groupId>
                <artifactId>ribbon-loadbalancer</artifactId>
                <version>${ribbon.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <!--    打包时按不同环境进行打包-->
    <profiles>
        <profile>
            <id>docker</id>
            <properties>
                <!--                用于配置文件 属性的统一管理-->
                <activated.profile>docker</activated.profile>
                <!-- redis连接 -->
                <redis.host>cloud-redis</redis.host>
                <redis.port>6379</redis.port>
            </properties>
            <build>
                <resources>
                    <resource>
                        <filtering>true</filtering>
                        <directory>src/main/resources</directory>
                    </resource>
                </resources>
            </build>
        </profile>
        <profile>
            <id>dev</id>
            <properties>
                <activated.profile>dev</activated.profile>
                <!-- redis连接 -->
                <redis.host>localhost</redis.host>
                <redis.port>6379</redis.port>
            </properties>
            <build>
                <resources>
                    <resource>
                        <filtering>true</filtering>
                        <directory>src/main/resources</directory>
                        <excludes>
                            <exclude>application-docker.*</exclude>
                        </excludes>
                    </resource>
                </resources>
            </build>
        </profile>
    </profiles>
</project>

2、Eureka

这里 Eureka 注册中心服务启用两个作为示例,相互注册,并进行数据同步,启用 security 安全验证
注意:
两个 Eureka 相互注册,yml 配置文件中,服务端口号不可重复,注册地址为对方地址,应用名称保持一直

2.1 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>com.study</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../parent</relativePath> <!-- lookup parent from repository -->
    </parent>

    <artifactId>eureka01</artifactId>
    <packaging>${packaging.type}</packaging>

    <dependencies>
        <!--        security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!--        eureka service-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <!--        优雅停服-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--        单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.2 SecurityConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * Date: 2022-06-16 星期四
 * Time: 17:11
 * Author: Dily_Su
 * Remark: 两种方式任选其一
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    // 方式一: 弹窗登录
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
    
//        http // 直接disable 会把安全验证也禁用,
//                .csrf().disable().authorizeRequests()
//                .anyRequest()
//                .authenticated()
//                .and()
//                .httpBasic();
//    }

    // 方式二:页内登录
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
        super.configure(http); // 访问eureka 的控制台和/actuator 是可以做安全控制
        http.csrf().ignoringAntMatchers("/eureka/**"); //忽略eureka/**的所有请求
    }
}

2.3 启动类

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

@EnableEurekaServer  // 启用注册中心服务
@SpringBootApplication
public class EurekaApplication {
    

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

}

2.4 application.yml

该文件用可用于本地 Dev 环境,Docker 环境时使用 application-docker.yml

spring:
  application:
    name: eureka                 # 应用名称
  profiles:
    active:
      - "@activated.profile@" # 从 maven parent 的配置中 获取值 # 从 maven parent 的配置中 获取值
  # 安全认证
  security:
    user:
      name: root       # 用户名
      password: 123456 # 密码

server:
  port: 8761                     # 端口
# port: 8762                     # 第二个 Eureka 的端口号

# 注册中心
eureka:
  instance:
    hostname: eureka          # 主机名
    prefer-ip-address: true   # 使用 IP 地址注册
    instance-id: ${
    spring.cloud.client.ip-address}:${
    server.port}

  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: false        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址
      defaultZone: http://root:123456@localhost:8762/eureka/
    # defaultZone: http://root:123456@localhost:8761/eureka/	# 第二个 Eureka 的注册地址

#  server:
#    enable-self-preservation: false # true 开启自我保护, false 关闭自我保护
#    eviction-interval-timer-in-ms: 60000 # 清除隔离(单位:毫秒) 默认 60 * 1000

# 度量指标监控与健康检查
management:
  endpoints:
    web:
      exposure:
        include: shutdown   # 开启 shutdown 端点访问
  endpoint:
    shutdown:
      enabled: true # 开启 shutdown 实现优雅停服

2.5 application-docker.yml

该配置只用于 docker 环境,用于覆盖 application.yml 中的配置

# 注册中心
eureka:
  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: false        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址,这里的 erueka-02 是 docker 中微服务容器名
      defaultZone: http://root:123456@eureka-02:8762/eureka/
    # defaultZone: http://root:123456@eureka-02:8762/eureka/	# 第二个 Eureka 的注册地址				

3、Provider

这里创建两个 Provider 服务,用于提供服务
注意:
两个 Provider 服务,端口号不能重复,应用名称必须一直,用于网关做负载均衡

3.1 目录结构

在这里插入图片描述

3.2 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>com.study</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../parent</relativePath> <!-- lookup parent from repository -->
    </parent>

    <artifactId>provider-eureka-01</artifactId>
    <packaging>${packaging.type}</packaging>

    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--        优雅停服-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.3 application.yml

spring:
  application:
    name: provider                # 应用名称
  profiles:
    active:
      - "@activated.profile@" # 从 maven parent 的配置中 获取值
  # 安全认证
  security:
    user:
      name: root       # 用户名
      password: 123456 # 密码

server:
  port: 7070                  # 端口

# 注册中心
eureka:
  instance:
    hostname: provider          # 主机名
    prefer-ip-address: true   # 使用 IP 地址注册
    instance-id: ${
    spring.cloud.client.ip-address}:${
    server.port}

  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: true        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址, 向两个注册中心注册
      defaultZone: http://root:123456@localhost:8762/eureka/,http://root:123456@localhost:8761/eureka/

#  server:
#    enable-self-preservation: false # true 开启自我保护, false 关闭自我保护
#    eviction-interval-timer-in-ms: 60000 # 清除隔离(单位:毫秒) 默认 60 * 1000

# 度量指标监控与健康检查
management:
  endpoints:
    web:
      exposure:
        include: shutdown   # 开启 shutdown 端点访问
  endpoint:
    shutdown:
      enabled: true # 开启 shutdown 实现优雅停服

3.4 application-docker.yml

# 注册中心
eureka:
  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: true        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址, 地址为 docker 中 eureka 微服务容器名
      defaultZone: http://root:123456@eureka-02:8762/eureka/,http://root:123456@eureka-01:8761/eureka/

4、Consumer

这里使用OpenFeign 进行服务内调用

4.1 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>com.study</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../parent</relativePath> <!-- lookup parent from repository -->
    </parent>

    <artifactId>consumer-eureka-feign</artifactId>
    <packaging>${packaging.type}</packaging>

    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--        优雅停服-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--        负载均衡策略-->
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-loadbalancer</artifactId>
            <scope>compile</scope>
        </dependency>
        <!--        openFeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--        Feign 使用 httpClient -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4.2 启动类

import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

//@EnableEurekaClient //如果配置了注册中心,则会默认开启,无需使用该注解
@SpringBootApplication
public class ConsumerApplication {
    

    @Bean
    @LoadBalanced  // 这个开启后,默认使用 轮询策略,用于服务内部调用
    public RestTemplate restTemplate() {
    
        return new RestTemplate();
    }

    // 全局负载均衡采用 随机策略
//    @Bean
//    public RandomRule randomRule() {
    
//        return new RandomRule();
//    }


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

}

4.3 application.yml

spring:
  application:
    name: consumer                 # 应用名称
  profiles:
    active:
      - "@activated.profile@" # 从 maven parent 的配置中 获取值
  # 安全认证
  security:
    user:
      name: root       # 用户名
      password: 123456 # 密码

# 注册中心
eureka:
  instance:
    hostname: consumer          # 主机名
    prefer-ip-address: true   # 使用 IP 地址注册
    instance-id: ${
    spring.cloud.client.ip-address}:${
    server.port}

  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: true        # 是否从注册中线获取注册信息,默认为 true
    service-url: # 注册中心对外暴露的注册地址
      defaultZone: http://root:123456@localhost:8762/eureka/,http://root:123456@localhost:8761/eureka/
  #
  server:
    enable-self-preservation: false # true 开启自我保护, false 关闭自我保护
    eviction-interval-timer-in-ms: 60000 # 清除隔离(单位:毫秒) 默认 60 * 1000

# 度量指标监控与健康检查
management:
  endpoints:
    web:
      exposure:
        include: shutdown   # 开启 shutdown 端点访问
  endpoint:
    shutdown:
      enabled: true # 开启 shutdown 实现优雅停服

server:
  port: 6061                  # 端口
  # 全局开启压缩
  compression:
    enabled: true
    # 配置压缩支持的 MIME TYPE
    mime-types: application/json,application/xml,text/html,text/xml,text/plain

# 局部 通过 Feign 到 Provider 的请求 进行 Gzip 压缩
feign:
  compression:
    request:
      min-request-size: 512  # 配置压缩数据大小的最小阈值,默认 2048
      mime-types: text/xml,application/xml,application/json  # 配置压缩文件支持的 MIME TYPE
      enabled: true                # 请求是否开启 Gzip 压缩
    response:
      enabled: true                # 响应是否开启 Gzip 压缩
  httpclient:
    enabled: true    # 开始 httpClient
  #  服务内部调用
  client:
    config:
      # 全局 配置请求超时时间
      default:
        connectTimeout: 1000  # 请求连接超时时间 默认为 1s
        readTimeout: 1000     # 请求处理的超时时间
      # 局部 配置 请求请求超时
#      provider: # 服务名
#        OkToRetryOnAllOperations: true   # 对所有请求都进行重试
#        MaxAutoRetries: 2                # 对当前实例的重复次数
#        MaxAutoRetriesNextServer: 0      # 切换实例的重复次数
#        ConnectTimeOut: 3000             # 请求连接超时时间 默认为 1s
#        ReadTimeOut: 3000                # 请求处理的超时时间

4.4 application-docker.yml

# 注册中心
eureka:
  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: true        # 是否从注册中线获取注册信息,默认为 true
    service-url: # 注册中心对外暴露的注册地址
      defaultZone: http://root:123456@eureka-02:8762/eureka/,http://root:123456@eureka-01:8761/eureka/

5、Gateway

使用 令牌桶的模式进行网关流量限制,该策略使用redis,spring 官网使用 spring-boot-starter-data-redis-reactive 作为 redis 连接依赖,不可更改
这里使用两个网关微服务做网关集群模拟,两个微服务端口不可重复,应用名相同

5.1 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>com.study</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../parent</relativePath> <!-- lookup parent from repository -->
    </parent>

    <artifactId>gateway01</artifactId>
    <packaging>${packaging.type}</packaging>

    <dependencies>
    	<!--        gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--        redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

5.2 application.yml

server:
  port: 9000  
# port: 9001 # 第二个网关服务端口
# 注册中心
eureka:
  instance:
    hostname: gateway          # 主机名
    prefer-ip-address: true   # 使用 IP 地址注册
    instance-id: ${
    spring.cloud.client.ip-address}:${
    server.port}

  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: true        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址
      defaultZone: http://root:123456@localhost:8762/eureka/,http://root:123456@localhost:8761/eureka/

spring:
  application:
    name: gateway # 应用名称
  profiles:
    active:
      - "@activated.profile@" # 从 maven parent 的配置中 获取值
  cloud:
      # 路由规则
    gateway:
      discovery:
        locator:
          # 是否与服务发现组件进行结合,通过 serviceId 转发到具体服务
          enabled: true                      # 是否开启基于服务发现的路由规则
          lower-case-service-id: true        # 是否将服务名称转小写
#      default-filters:
#        - PrefixPath=/product
      routes:
        - id: provider                                            # 路由 ID,唯一
          uri: lb://provider                                      # 根据注册中心动态路由
#          uri: http://localhost:7070/                            # 目标 URI,路由到微服务的地址
          predicates:                                             # 断言(判断条件)
            # Path
            - Path=/product/**                                           # 匹配对应的 URL 请求,并追加到 URI 后
            # Query
#            - Query=name                                         # 匹配请求参数中包含 name 的请求
#            - Query=name,abc.+                                   # 匹配请求参数中包含 name 且满足正则表达式 abc. 的请求
            # Method
#            - Method=GET                                         # 匹配 GET 请求
            # Datetime
#            - After=2022-06-27T16:00:00.000+08:00[Asia/Shanghai] # 匹配中国上海 2022-06-27 16:00:00 后的请求
            # RemoteAddr
#            - RemoteAddr=172.16.10.82/0                          # 匹配请求中地址是 172.16.10.82 的请求,/0为子网掩码
            # Header
#            - Header=X-Request-Id, \d+                            # 匹配请求头中包含 X-Request-Id 并且其值匹配正则表达式 \d+ 的请求

          # Filters
          filters:
            # 将 /gateway/product/list 重写为 /product/list
#            - RewritePath=/gateway(?<segment>/?.*),$\{segment}
            # 请求增加前缀
#            - PrefixPath=/product
            # 分割前缀 /api/gateway/product/list
#            - StripPrefix=2
            # 将 /gateway/product/list 重写为 /product/list
#            - SetPath=/product/{segment}
            # 在下游请求中增加 参数 id = 1
#            - AddRequestParameter=id,1
            # 在任何情况下,响应状态码设置为888
#            - SetStatus=888
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1  # 令牌每秒填充数量
                redis-rate-limiter.burstCapacity: 2  # 令牌桶总容量
                key-resolver: "#{@ipKeyResolver}"  # 使用 SpEL 表达式按名称引用 bean

  redis:
    host: localhost
    port: 6379
    database: 1

5.3 application-docker.yml

# 注册中心
eureka:
  client:
    register-with-eureka: true  # 是否将自己注册到注册中心,默认 true ,集群时要为 true,相互注册
    fetch-registry: true        # 是否从注册中线获取注册信息,默认为 true
    service-url:                 # 注册中心对外暴露的注册地址
      defaultZone: http://root:123456@eureka-02:8762/eureka/,http://root:123456@eureka-01:8761/eureka/
spring:
  redis:
    #    从 maven parent 中 获取属性值
    host: '@redis.host@'
    port: '@redis.port@'
    database: 1

二、项目部署

1、项目结构

请添加图片描述

2、配置文件

2.1 nginx.conf

# nginx 配置文件:负载均衡默认为轮询
worker_processes 1;

events { worker_connections 1024; }

http {
    include    /etc/nginx/mime.types;
    sendfile   on;

    proxy_buffer_size   128k;
    proxy_buffers   4 256k;
    proxy_busy_buffers_size   256k;

    client_max_body_size   100m;

    # 网关集群
    upstream gateway {
        # docker 中 localhost 为 镜像容器名
        server gateway-01:9000;
        server gateway-02:9001;
    }

    server {
        listen 8080;

        location / {
            # 将所有请求指向 网关集群
            proxy_pass http://gateway;
        }
    }
}

2.2 dockerFile

# 每个微服务根目录下都要放置一个,用于将打包好的 jar 整理为 docker image
# jdk 版本不能低于自己编译时的版本,否则 docker 启动会报错
FROM openjdk:11.0.15-jre
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
WORKDIR /
ENTRYPOINT ["java","-jar","/app.jar"]

2.3 docker-compose.yml

version: "3.7"
services:
  redis:
    image: redis:latest  # 从 docker hub 中 pull 最新的 redis image
    container_name: cloud-redis # docker 中的容器名称
    ports:               # 对外映射的端口,占用容器内的 6379,本机的26379,不想对外暴漏时,可以省略
      - "26379:6379"
    networks:            # 容器内网关,用于容器内镜像互相调用
      - backend
    environment:         # 设置时区
      - TZ=Asia/Shanghai

  erurka-01:
    build: ./eureka01    # build 存在时,表示从该目录下获取镜像名称
    image: cloud/eureka01:latest # 镜像名称
    container_name: eureka-01 # 容器名称
    ports:
      - "28761:8761"
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  erurka-02:
    build: ./eureka02
    image: cloud/eureka02:latest
    container_name: eureka-02
    ports:
      - "28762:8762"
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  gateway-01:
    build: ./gateway01
    image: cloud/gateway01:latest
    container_name: gateway-01
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  gateway-02:
    build: ./gateway02
    image: cloud/gateway02:latest
    container_name: gateway-02
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  provider-01:
    build: ./provider01
    image: cloud/provider01:latest
    container_name: provider-01
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  provider-02:
    build: ./provider02
    image: cloud/provider02:latest
    container_name: provider-02
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  consumer-eureka:
    build: ./consumer-eureka
    image: cloud/consumer-eureka:latest
    container_name: consumer-eureka
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  consumer-eureka-feign:
    build: ./consumer-eureka-feign
    image: cloud/consumer-eureka-feign:latest
    container_name: consumer-eureka-feign
    networks:
      - backend
    environment:
      - TZ=Asia/Shanghai

  nginx:
    image: nginx
    container_name: cloud-demo-nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 28080:8080
    restart: unless-stopped
    networks:
      - backend

networks: # 该微服务项目在容器中的网关
  backend: 
    name: cloud-demo 

3、docker 部署

3.1 Maven 打包

# 清理 targer 文件,并按照 按照 docker 配置 打包
 mvn clean package -P docker -DskipTests

ker -DskipTests

3.2 docker部署

# build image 并 生成容器,启动 image
docker compose up -d 		
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42151956/article/details/125533954

智能推荐

机器人运动学笔记3——林沛群_林佩群机械臂-程序员宅基地

文章浏览阅读881次。提示:本文上接 机器人运动学笔记2——林沛群文章目录前言一、机械手臂轨迹规划1.1 机械手臂轨迹规划引言1.2 Joint-Space下轨迹规划2.3 Cartesian-Space下轨迹规划1.4 三次多项式(Cubic-Polynomials)1.5 多段Cubic-Polynomials1.6 N段路径的三次多项式(General Cubic Polynomials)二、含抛物线的线性函数2.1 Linear Function with Parabolic Blends2.2 多段Line._林佩群机械臂

【点云PCL入门】可视化(Visualization)_pcl visualization-程序员宅基地

文章浏览阅读2.5k次。索引1.简单点云可视化2. 可视化深度图像3.PCL Visualizer可视化类参考1.简单点云可视化CloudViewer类不能在多线程应用程序中使用!程序出错:“no override found for 'vtkPolyDataMapper”。解决方法是将下列三行代码放在类的最前面,放在其他#include之后也会报错#include <vtkAutoInit.h>VTK_MODULE_INIT(vtkRenderingOpenGL);VTK_MODULE_INIT(vtk_pcl visualization

用VC++制作播放AVI视频流的动画按钮-程序员宅基地

文章浏览阅读100次。Visual C++ 开发环境为控件提供的自绘制功能使程序员能够充分发挥自己的创造性来设计比较漂亮的程序界面。所谓AVI按钮是指每当鼠标从按钮上经过时就播放一段按钮提示的AVI,在许多的游戏程序以及三维动画软件中(如摩托英豪、Cool 3D等)都广泛的采用了这种AVI按钮。它使得程序的用户界面很具有动感,也使得我们的程序至少看上去更专业,本实例借助Visual C++强大的控件自绘制功能来实现这种..._vc animate

用 Flask 来写个轻博客 (20) — 实现注册表单与应用 reCAPTCHA 来实现验证码_flask表单谷歌验证码-程序员宅基地

文章浏览阅读6.3k次,点赞5次,收藏2次。Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog目录目录前文列表reCAPTCHA应用 reCAPTCHA前文列表用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)VC_连接 MyS..._flask表单谷歌验证码

NRA High Power Competition-程序员宅基地

文章浏览阅读1k次。A true-to-life simulation of high power rifle shooting, NRA High Power Competition provides valuable resources which teach the rules, procedures and safety of the sport. One can shoot highly detai_high power competitio

qt5.15.2在银河麒麟v10sp1上编译源码后安装运行_银河麒麟安装qt-程序员宅基地

文章浏览阅读4k次,点赞3次,收藏29次。修改‘/usr/lib/qt5/bin/qmake‘为实际安装路径如:/home/drs/QT_Source/qt-everywhere-src-5.15.2/qtbase/bin。编译进程在文件数为[1/605]的时候循环,文件数不会减少,此时报错信息为源码文件下的一个头文件中,出现了不允许的数据类型转换。找到该文件,修改相应语句。在银河麒麟软件商店中下载Qt creator,配置Qt套件kits,Qt version路径为/usr/local/Qt-5.15.2/bin/qmake。_银河麒麟安装qt

随便推点

C++ 并发指南<future>(2)std::packaged_task-程序员宅基地

文章浏览阅读1.8k次。std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task 与 std::function 类似,只不过 std::packaged_task 将其包装的可调用对象的执行结果传递给一个 std::future 对象(该对象通常在另外一个线程中获取 std::packaged_task 任务的执行结果)。std::packaged_task 对象内部包含了两个最基本元素:被包装的任务(stored _std::packaged_task

Android点击事件之多点触摸与手势识别-程序员宅基地

文章浏览阅读2.7k次,点赞4次,收藏15次。前言最近遇到想要实现三指滑动监听的需求,实现代码不方便贴出来,但是思路还是可以记录一下。Muilti-touch 双指缩放探索首先要实现OnTouchListener接口,然后重写方法:public boolean onTouch(View v, MotionEvent event); 从这个方法中我们就可以获取实现两指缩放功能的全部信息。View v是触发事件的源,MotionEvent event即一个触摸事件。对屏幕的几乎所有操作都会触发事件,如点击、放开、滑动等。不同的

maven插件之maven之maven-surefire-plugin_the parameter forkmode is deprecated since version-程序员宅基地

文章浏览阅读6k次。1.maven-surefire-plugin是个什么鬼?如果你执行过 mvn test 或者执行其他maven命令时跑了测试用例,你就已经用过 maven-surefire-plugin 了。 maven-surefire-plugin 是maven里执行测试用例的插件,不显示配置就会用默认配置。这个插件的 surefire:test 命令会默认绑定maven执行的 test 阶段。_the parameter forkmode is deprecated since version 2.14. use forkcount and r

LCD 移植的那些坑-LCD屏幕配置常见的问题解决方案_lvds hspw-程序员宅基地

文章浏览阅读3.5k次,点赞3次,收藏34次。在使用飞凌嵌入式开发板过程中,关于LCD屏幕配置有一些常见的问题问题1,如何修改开机默认的屏幕尺寸?全平台都可以通过uboot的选择菜单来选择默认的显示,对应配置方式可以参阅对应平台的应用手册。i.MX6DL/i.MX6Q系列uboot已开源,可以通过直接修改uboot源码文件include/configs/mx6sabre_common.h(参考linux4.1.15内核版本)如果是客..._lvds hspw

街景字符编码识别项目学习笔记(三)_convnext能不能用作汉字识别-程序员宅基地

文章浏览阅读344次。学习目标:学习CNN基础和原理;使用Pytorch框架构建CNN模型,并完成训练1 卷积神经网络CNN1.1 CNN简介卷积神经网络(简称CNN)是是一类特殊的人工神经网络,是深度学习中重要的一个分支。它专门用来处理具有类似网格结构的数据,比如说时间序列数据(可以认为是在时间轴上有规律地采样形成的一维网格)以及图像数据(二维像素网格)。CNN在很多领域都表现优异,精度和速度比传统计算学习算法高很多。特别是在计算机视觉领域,CNN是解决图像分类、人脸识别、图像检索、物体检测和语义分割的主流模型。近._convnext能不能用作汉字识别

电子白板是什么?-程序员宅基地

文章浏览阅读469次。电子白板是汇集了尖端电子技术、软件技术等多种高科技手段研发的高新技术产品,它通过应用电磁感应原理,结合计算机和投影机,可以实现无纸化办公及教学。电子白板由普通白板发展而来,最早出现的电子白板为复印型电子白板,随着技术的发展及市场的需要,出现了交互式的电子白板。目前市场上这两种电子白板并存,以下分别介绍这两类电子白板。 复印式电子白板 所谓复印式电子白板即通过用户的简单操作便可将白板上书写的内容通过一定的方式扫描并打印出来。其功能完成过程与普通的复印过程一样,首先由图像传感器件对白板上的内容进行采集,采集信号_电子白板是什么