(一)什么是微服务网关
后端写完所有的微服务之后,最终是要交给前端去调用。我们都知道每个微服务都有各自的端口号,如果前端直接通过IP加端口的方式去调用微服务会很麻烦。如果想对请求增加限制也会变得十分困难。这个时候微服务网关就出现了。
微服务网关又成为API网关,它是系统对外的唯一入口。APl网关封装了系统内部架构,为每个客户端提供一个定制的APl。API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
听起来有些抽象,下面就做一张图给大家展示一下:前端的请求统一由微服务网关进行管理,微服务网关可以调用各个微服务,同时自身还有多种功能。
API网关的职责有身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理,最重要的功能是和外界联系。
常见的API网关实现方式有Zuul,traefix,Spring Cloud Gateway等等。目前主流的微服务网关是Spring Cloud Gateway。
(二)Spring Cloud Gateway网关
Spring Cloud Gateway是Spring 官方基于Spring 5.0,Spring Boot 2.0和Project Reactor 等技术开发的网关,旨在为微服务架构提供一种简单而有效的统一的API路由管理方式,统一访问接口。Spring Cloud Gateway作为Spring Cloud 生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。
2.1 核心概念:
路由(route):路由是网关最基础的部分,路由信息由一个ID,一个目的URL,一组断言工厂和一组Filter组成。
断言(predicates):java8中的断言函数,Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自Http Request中的任何信息。当断言为真时,则匹配路由。
过滤器(filter):对请求和响应进行过滤
下面通过实践来操作微服务网关,本项目有依赖于Nacos与Sentinel,如果不需要这部分的内容可以在配置文件中去除。
2.2 搭建环境:
1、引入工程导入依赖
创建api_gateway_server工程,在工程中的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>
<groupId>com.javayz</groupId>
<artifactId>nacos-discovery-spring-cloud-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>nacos-discovery-spring-cloud-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<projec.build.sourceEncoding>UTF-8</projec.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--springcloudgateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>
<!--当前项目继承的依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</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>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、配置启动类
创建GatewayApplication类
@EnableDiscoveryClient
@SpringBootApplication
public class NacosDiscoverySpringCloudGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(NacosDiscoverySpringCloudGatewayApplication.class, args);
}
}
3、编写配置文件
这里对配置文件的编写使用.yml格式的配置文件,在resource文件夹下创建applicaiion.yml。这里需要注意的是gateway下routes的配置,首先用id自定义网关;接着定义uri,意思是当访问的是9090端口(即访问的是网关时),就自动把ip和端口号变成该uri;最后写断言predicates,这里的Path=/index
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);
}
@Override
protected int getHttpStatus(Map<String, Object> errorAttributes) {
return (int) errorAttributes.get("status");
}
private String buildMessage(ServerRequest request,Throwable ex){
StringBuilder builder = new StringBuilder("Failed to handle request:");
builder.append(request.methodName());
builder.append(" ");
builder.append(request.uri());
if (ex!=null){
builder.append(ex.getMessage());
}
return builder.toString();
}
public static Map<String,Object> response(int status,String errorMsg,Object data){
Map<String,Object> map=new HashMap<>();
map.put("code",status);
map.put("message",errorMsg);
map.put("data",data);
return map;
}
}