在微服务的架构中,不同模块的请求接口可能来自于不同的服务,而不同的服务要放在不同的IP地址中(最次也得是端口不一样)。
如果前端人肉记下每个服务的地址端口,那前端人员一定会崩溃掉。
而解决此种困境的正式微服务中一个重要的组成部分–网关路由。它的作用简言之就是为微服务提供统一的访问入口,并按照设定好的访问规则将请求路由至对应的服务。
SpringCloud官方为我们提供了一种解决方案,那就是我们标题中说到的Gateway
使用
添加依赖:springboot选择的是2.2.2.Release
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.1.RELEASE</version>
</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>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
bootstrap.yml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
profiles:
active: dev
application.yml
server:
port: 8021
spring:
application:
name: server-gateway
cloud:
gateway:
routes:
- id: consumer
uri: lb://service-consumer
predicates:
- Path=/consumer/**
- id: provider
uri: lb://service-provider
predicates:
- Path=/provider/**
discovery:
locator:
enabled: true
routes就是路由规则的配置内容
id:可以随便,但是不能重复
uri:要路由的目标地址,因为我们使用nacos,所以我们这里直接写服务名称即可,而lb的意思是负载均衡(load balance)
predicates:断言,符合断言规则的则路由至对应的服务
关于predicates和filter更多用法可以查看官网
在service-consumer服务中创建一个API
@GetMapping("/getConsumer")
public String getConsumer(@RequestParam(value = "p1",required = false)String p1, @RequestParam(value = "p2",required = false)String p2){
return "1234567890-";
}
再在service-provider服务中创建一个API
@GetMapping("/getProviderStr")
public String getProviderStr(){
return "fucking idiot";
}
两个服务都注册在nacos中
然后我们打开浏览器,输入http://localhost:8021/consumer/getConsumer,注意8021是Gateway服务的地址
然后查看浏览器返回结果
我们再在浏览器中输入http://localhost:8021/provider/getProviderStr
然后再查看浏览器返回结果
我们通过Gateway服务地址能够成功的访问目标API则证明Gateway生效了
我们可以自定义全局的filter,以使不满足要求的请求不被路由。
比如我们要求请求参数中必须带有token,则可以创建如下filter
@Component
public class MyFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if(StringUtils.isEmpty(token)){
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return response.setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
启动gateway之后,我们在浏览器中输入地址 localhost:8021/consumer/getConsumer观察浏览器的返回结果
我们可以看到返回的状态码是406,与我们代码中返回的结果相吻合。
接下来我们测试下带token参数的结果如何
带token的可以正常访问API