
什么是API?我们为什么需要它?
API网关是坐在API(应用编程接口)前面的编程,是定义的后端API和微服务(可以是内部和外部的)的单一入口点。坐在API的前面,网关起到保护作用,管理安全性和可扩展性,以及高可用性。简单地说,API网关接收来自客户的所有API请求,确定哪些服务是需要的,并将它们组合成一个统一的、无缺陷的用户体验。
API网关的优势
- 它提高了微服务的安全性,因为我们限制外部调用对我们所有服务的访问。
- 诸如认证、监控/指标和弹性等交叉问题只需要在API网关中实现,因为我们的所有调用都将通过它进行路由。
- 客户不知道我们的微服务系统的内部架构。客户端将无法确定微服务实例的位置。
- 简化了客户的互动,因为他只需要为所有的需求访问一个单一的服务。
Spring Cloud Gateway架构?
Spring Cloud Gateway是SpringCloud团队在Spring反应式生态系统之上的 API网关实现。它由以下构建模块组成:
路由:关于Apache Airflow的简介路线是网关的基本构件。它由一个ID、目的地URI、谓词集合和过滤器集合组成。如果集合谓词为真,则路由被匹配。
谓词:这类似于Java 8的函数Predicate。使用这个功能,我们可以匹配HTTP请求,如头文件、URL、cookies或参数。
过滤器:这些是Spring Framework GatewayFilter的实例。使用它,我们可以根据需求修改请求或响应。

春天云网关架构
实现Spring Cloud API Gateway
使用Spring Cloud Gateway,我们可以通过以下两种方式创建路由
- 使用基于java的配置以编程方式创建路由
- 使用基于属性的配置(即application.properties或application.yml)来创建路由。
在本教程中,我们将使用基于属性的配置实现Spring Cloud Gateway。
我们将实现Spring Cloud Gateway应用程序,该应用程序根据URL模式将请求路由到其他两个微服务。

实现第一个微服务
Maven项目的内容如下

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>2.6.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>first-microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>first-microservice</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.0</spring-cloud.version>
</properties>
<dependencies>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
定义application.yml的内容如下
spring:
application:
name: first-microservice
server:
port: 8081
eureka:
instance:
hostname: localhost
创建一个暴露GET REST服务的控制器类,如下所示
package com.firstmicroservice.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/first")
public class FirstController {
@GetMapping("/message")
public String test() {
return "Hello this is my first microservice";
}
}
创建带有@SpringBootApplication注解的主类
package com.firstmicroservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FirstMicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(FirstMicroserviceApplication.class, args);
}
}
实现第二个微服务
Maven项目的内容如下

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>2.6.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>second-microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>second-microservice</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.0</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-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
定义application.yml的内容如下
spring:
application:
name: second-microservice
server:
port: 8082
eureka:
instance:
hostname: localhost
创建一个暴露GET REST服务的控制器类,如下所示
package com.secondmicroservice.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/second")
public class SecondController {
@GetMapping("/message")
public String test() {
return "Hello this is my Second Service";
}
}
创建带有@SpringBootApplication注解的主类
package com.secondmicroservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SecondMicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(SecondMicroserviceApplication.class, args);
}
}
实现Eureka服务器
Eureka服务器是一个持有信息的应用程序,在所有客户端服务应用程序之上。每个微服务都将注册到Eureka服务器,Eureka服务器知道所有在每个端口和IP地址上运行的客户端应用程序。Eureka服务器也被称为发现服务器。
构建一个Eureka服务器
Eureka服务器是与Spring Cloud捆绑在一起的。因此, 我们需要开发Eureka服务器,并在默认端口8761上运行。
Maven项目的内容如下

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>2.6.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>eurekaserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eurekaserver</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.0</spring-cloud.version>
</properties>
<dependencies>
<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-test</artifactId>
<scope>test</scope>
</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>
定义application.yml的内容如下
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
server:
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: localhost
创建带有@SpringBootApplication注解的主类。
package com.example.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaserverApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaserverApplication.class, args);
}
}

使用基于属性的配置实现Spring Cloud Gateway
Maven项目的内容如下

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>2.6.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>springcloud-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.0</spring-cloud.version>
<!-- <spring-cloud.version>Greenwich.SR2</spring-cloud.version>-->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</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>
</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>
定义application.yml的内容如下
server:
port: 8080
eureka:
instance:
hostname: localhost
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: first-microservice
uri: http://localhost:8081/
predicates:
- Path=/first/**
- id: second-microservice
uri: http://localhost:8082/
predicates:
- Path=/second/**
创建带有@SpringBootApplication注解的主类
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class SpringcloudGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudGatewayApplication.class, args);
}
}
启动我们已经开发的三个微服务
- 转到网址 - localhost:8080/first/message

转到URL - localhost:8080/second/message

结论
API网关是一个重要的设计概念。随着微服务数量的增加,拥有一个通用的模式变得非常重要,它可以处理这些服务的很多共同的工作负载,而API网关可以帮助实现这一点。