说明
- 项目运行的前提条件:服务注册中心已经启动。
- 本项目的服务注册与发现是基于 Spring Cloud Consul 实现。具体内容博主写在另一篇博客:
- 本博客是 Spring Cloud 微服务化(精简完整版)的一部分。
简介
- 首先,这是一个标准的 Spring Boot 项目
- 其次,它实现基于
Spring Cloud Consul
的服务注册功能 - 最后,它通过
Spring Cloud Gateway
实现路由转发- 如果转发的请求报错(超时、返回信息异常等),则返回 fallback 信息(通过
Spring Cloud Netflix Hystrix
实现)
- 如果转发的请求报错(超时、返回信息异常等),则返回 fallback 信息(通过
创建项目
- 博主使用的开发工具是 IntelliJ IDEA。创建出来的项目结构如下所示:
- 主要包含五部分内容
- 依赖信息:pom.xml
- 配置信息:application.yml
- 启动类: GatewayApplication.java
- 路由配置类:AwesomeRouter.java
- 服务熔断类:FallbackController.java
- 主要包含五部分内容
依赖
- 主要引入依赖:
- spring-cloud-starter-consul-all:注册服务到 Consul
- spring-cloud-starter-gateway :支持网关服务
- spring-cloud-starter-netflix-hystrix :支持熔断服务
- 完整 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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>andy.wanna.sing</groupId> <artifactId>awesome-gateway</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>awesome-gateway Maven Webapp</name> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-all</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-stub-runner</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-web</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <build> <finalName>awesome-gateway</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
配置信息
-
主要配置内容:
- 服务注册中心(Spring Cloud Consul 配置)
- 运行的端口号
- 健康检查暴露的端点
- application.yml
-
spring: application: name: awesome-gateway cloud: consul: host: localhost port: 8500 discovery: enabled: true register: true healthCheckInterval: 10s instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}} server: port: 9001 management: endpoints: web: exposure: include: metrics,env,beans,mappings,health
启动类
- 标准的 Spring Boot 项目启动类
-
package awesome.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * 网关启动类 * * * @author: Andy * @time: 2019/4/15 15:39 * @since */ @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class,args); } }
路由配置类
- 网关核心类,它的作用是请求转发。
- 注意:
@Configuration
注解不可缺少。 -
package awesome.gateway.router; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; /** * 路由类 * * * @author: Andy * @time: 2019/4/15 15:43 * @since */ @Configuration public class AwesomeRouter { @Bean public RouteLocator myRoutes(RouteLocatorBuilder builder) { return builder.routes() // 匹配的请求转发到 awesome-user-api 服务 .route(p -> p .path("/api/user/*") .filters(f -> f.hystrix(config -> config.setFallbackUri("forward:/fallback"))) .uri("lb://awesome-user-api")) // 匹配的请求转发到 awesome-product-api 服务 .route(p -> p .path("/api/product/*") .filters(f -> f.hystrix(config -> config.setFallbackUri("forward:/fallback"))) .uri("lb://awesome-product-api")) .build(); } }
服务熔断类
- 和上面的路由类(AwesomeRouter.java )配合使用,它的作用是:当服务不可用时,返回默认的错误信息。
-
package awesome.gateway.fallback; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 服务熔断类 * * * @author: Andy * @time: 2019/4/15 15:46 * @since */ @RestController public class FallbackController { @RequestMapping("/fallback") public ResponseEntity<?> fallback() { return new ResponseEntity<>("API请求失败!", HttpStatus.INTERNAL_SERVER_ERROR); } }
测试
- 上面我们构建了一个网关。它的作用是:
- 把匹配
/api/user/*
的请求转发到awesome-user-api
服务 - 把匹配
/api/product/*
的请求转发到awesome-product-api
服务 - 当服务不可用时,返回
/fallback
接口返回的内容作为默认错误信息。 - 为了完成这个测试,我们需要要 awesome-user-api 和 awesome-product-api 服务。
- awesome-user-api 和 awesome-product-api 必须是 Web 项目,并且注册到服务注册中心。
- 由于本博客是 Spring Cloud 微服务化(精简完整版)的一部分,所以awesome-user-api 和 awesome-product-api 这两个 WEB 项目除了实现注册服务功能,还实现了 基于 Spring Cloud Feign 的远程服务调用。具体内容博主写在另一个博客:
- awesome-user-api 和 awesome-product-api 必须是 Web 项目,并且注册到服务注册中心。
- 把匹配
服务正常可用
- 使 awesome-user-api 服务的 /api/user/1 接口正常可用。
- 访问网关:http://localhost:9001/api/user/1
- 返回结果:
服务异常不可用
- 使 awesome-user-api 服务的 /api/user/1 接口不可用。
- 访问网关:http://localhost:9001/api/user/1
- 返回结果:
- 返回结果:
- 访问网关:http://localhost:9001/api/user/1