在微服务的架构中,不同模块的请求接口可能来自于不同的服务,而不同的服务要放在不同的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服务的地址

然后查看浏览器返回结果

springcloud gateway获取前端主动断开 springcloud中的gateway_spring


我们再在浏览器中输入http://localhost:8021/provider/getProviderStr

然后再查看浏览器返回结果

springcloud gateway获取前端主动断开 springcloud中的gateway_spring_02


我们通过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观察浏览器的返回结果

springcloud gateway获取前端主动断开 springcloud中的gateway_ci_03


我们可以看到返回的状态码是406,与我们代码中返回的结果相吻合。

接下来我们测试下带token参数的结果如何

springcloud gateway获取前端主动断开 springcloud中的gateway_ci_04


带token的可以正常访问API