三个文件帮你搞定 Spring Cloud Gateway (Alibaba体系)
在微服务架构中,网关是必不可少的重要组件。
这关系到了客户端“如何访问”每个服务。
以前主流的方式就是使用Netfilx的Zuul组件。但是,因为某些奇妙的原因,Netfilx全家桶都停止维护了。
我之前也写过Zuul的配置和使用方法:
Spring Cloud Netflix Zuul 使用自带的 Hystrix 实现回退机制 , 并实现请求在Zuul内部的聚合功能
那么,既然Zuul这套东西不维护了,迟早也就是抛弃的份。这时候就到Gateway上场了。
说起Getway的工作流程,大概是这样子的: 客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后最终返回结果。
这么一说…是不是感觉这套流程和 SpringMVC 有点像。这么一看一下子Gateway的流程就感觉铭然于心了有木有。
进入正题,开始上手 Spring Cloud Getway 的配置和使用。
当然,路由网关,也是一个项目。
难么必不可少的 项目依赖管理配置文件、应用配置文件、启动类 是肯定需要的。
而他,真的就只需要这几个东西就能完成基本的路由、负载均衡功能。
既然要建立项目,pom.xml就是第一个。
Spring Cloud Getway 有一个特别的地方。
那就是他不使用 Web 作为服务器,而是使用 WebFlux 作为服务器。
基于此,那么 spring-boot-starter-web 这依赖就不能上了。
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> <parent> <groupId>com.skypyb</groupId> <artifactId>sc-demo-alibaba-dependencies</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../sc-demo-alibaba-dependencies/pom.xml</relativePath> </parent> <artifactId>sc-demo-alibaba-gateway</artifactId> <packaging>jar</packaging> <name>sc-demo-alibaba-gateway</name> <url>http://www.skypyb.com</url> <inceptionYear>2019-Now</inceptionYear> <dependencies> <!-- Spring Boot Begin --> <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> <!-- Spring Boot End --> <!-- Spring Cloud Begin --> <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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Spring Cloud End --> <!-- Commons Begin --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!-- Commons Begin --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.skypyb.provider.NacosConsumerApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>
这pom.xml真是又丑又长。我怎么就用了maven没用gradle呢? 不禁陷入了深深的思考
既然是Alibaba体系,那么Sentinel、Nacos等依赖也是需要的。 和之前写过的几个Spring Cloud Alibaba组件的使用结合到一起。
在此之上去掉web依赖,引入 org.springframework.cloud:spring-cloud-starter-gateway 依赖就可以了。
由于过滤器等功能依然需要 Servlet 支持,故这里在依赖一个 javax.servlet:javax.servlet-api
pom.xml搞定,接下来就是最最最最重要的 application.yml:
spring: application: # 应用名称 name: sc-demo-alibaba-gateway cloud: nacos: discovery: server-addr: 192.168.3.105:8848 #注册进nacos # 使用 Sentinel 作为熔断器 sentinel: transport: port: 18102 dashboard: 192.168.3.105:8858 # 路由网关配置 gateway: # 这里是设置与服务注册发现组件结合,这样可以采用服务名的路由策略 discovery: locator: enabled: true # 配置路由规则 routes: - id: ROUTER#sc-demo-alibaba-consumer #这个是路由ID,需要保证在所有路由定义中唯一,值随便写就是了 # 采用 LoadBalanceClient 方式请求,以 lb:// 开头,后面的是注册在 Nacos 上的服务名 uri: lb://sc-demo-alibaba-consumer predicates: # Method ,这里是匹配 GET 和 POST 请求 - Method=GET,POST - id: ROUTER#sc-demo-alibaba-provider uri: lb://sc-demo-alibaba-provider predicates: - Method=GET,POST server: port: 8888 feign: sentinel: enabled: true management: endpoints: web: exposure: include: "*" # 配置日志级别,方别调试 logging: level: org.springframework.cloud.gateway: debug
其他的不说,最主要的是spring.cloud.gateway.route下面的配置。
在这里有几个很重要的点,要重点说一下。
id: 这个是路由ID,值可以随便写,但是一定要保证在整个微服务中此值是唯一的
uri: lb://是固定写法,表示开启负载均衡。后边跟着的是你注册进nacos的其他服务名字
predicates: 这个是谓词。谓词这个词语一说出来很多人都会蒙圈。但是如果是熟悉JDK1.8的人肯定对这个有印象,Stream API里filter()方法入参就是一个Predicate,返回一个boolean类型的值。虽说Gateway里的和Strean API里的肯定不一样。但是可以这么理解,他是为了判断请求是否满足一个条件而存在的。而我设置的 – Method=GET,POST 表示匹配 GET 和 POST 请求,这俩种类型的请求就可以路由。
predicate当然不止Method这一个玩意,他总共有这么些设置:
After | After=2017-01-20T17:42:47.789-07:00[America/Denver]
Before | Before=2017-01-20T17:42:47.789-07:00[America/Denver]
Between | 2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
Cookie | Cookie=chocolate, ch.p
Header | Header=X-Request-Id, \d+
Host | Host=**.somehost.org
Method | Method=GET
Path | Path=/foo/{segment}
Query | Query=baz
RemoteAddr | RemoteAddr=192.168.1.1/24
参考: https://cloud.spring.io/spring-cloud-gateway/2.0.x/single/spring-cloud-gateway.html#gateway-request-predicates-factories
那么现在
nacos也注册进去了
setinel熔断也开了
路由设置也配好了
还要什么自行车,一个启动类,给他 Run 起来,就可以搞起
package com.skypyb.gateway; 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//nacos使用spring cloud 原生注解 @EnableFeignClients //Feign注解 public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
注意,访问路径是: http://路由网关IP:路由网关Port/服务名/** (和Zuul一样的)
随便调用个接口,能够成功获取响应就是成功啦!多开几个同样的服务跑起来就会知道,负载均衡也是实现了的。
至此 Spring Cloud Gateway 结合Spring Cloud Alibaba全家桶的路由功能、负载均衡功能已经配置完毕。