springcloud中gateway的实际应用

之前我一直用的是Zuul网关,用过gateway以后感觉比Zuul功能还是强大很多。

Spring Cloud Gateway是基于Spring5.0,Spring Boot2.0和Project Reactor等技术开发的,用来为微服务架构提供一种简单有效统一的API路由管理方式。

相比Zuul,GateWay不仅仅提供统一的路由方式,还提供了例如:安全,限流,监控/指标,重试机制,熔断回调,过滤等功能,这些都是可配置的。

原理什么的就不多说了,可以看下官方文档

首先添加Maven依赖

<!-- gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 熔断器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!-- 限流 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <!-- eureka-client -->
        <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-actuator</artifactId>
        </dependency>
        <!-- zipkin-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

yml配置详情如下:

#连接Eureka配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
server:
  port: 8770
spring:
  main:
    banner-mode:
  application:
    name: dkjk-gateway-service #应用程序名
#  redis:
#    host: localhost
#    port: 6379
  cloud:
    gateway:
      routes:
      - id: my-service-one   #我们自定义的路由 ID,保持唯一
        #目标服务地址,也可以是http://localhost:8182  PS: 当所用协议为lb时,
        #gateway将使用 LoadBalancerClient把服务名通过eureka解析为实际的主机和端口,并进行负载均衡。
        uri: lb://Eureka中的服务名称1  
#        order: 0
        #路由规则,Predicate 接受一个输入参数,返回一个布尔值结果。
#该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。 predicates: # PS:以下规则可以组合使用 #接收一个匹配路径的参数来判断是否走路由。当访问地址 http:
//localhost:8770/spring-cloud时
#会自动转发到地址:
http://www.ityouknow.com/spring-cloud - Path=/em/** #可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。可以用postman测试,如果符合规则进行路由,否则不进行路由(报404) # - Method=GET #请求时间在 2019年11月04日6点6分6秒之前可以进行路由,在这时间之后停止路由(报404) # - Before=2019-11-04T06:06:06+08:00[Asia/Shanghai] #请求时间在 2019年11月04日16点31分00秒之前不可以进行路由(报404),在这时间之后可以进行路由 # - After=2019-11-05T16:31:00+08:00[Asia/Shanghai] #在这个时间段内可以匹配到此路由,超过这个时间段范围则不会进行匹配(报404)。可以用在限时抢购的一些场景中。 # - Between=2019-11-04T06:06:06+08:00[Asia/Shanghai], 2019-11-06T06:06:06+08:00[Asia/Shanghai] #两个参数:1.请求头中属性名称2.正则表达式(也可以是固定值),可以用postman测试,如果符合规则进行路由,否则不进行路由(报404) # - Header=apikey, \d+ #两个参数:1.Cookie name 值2.正则表达式(也可以是固定值),可以用postman测试,如果符合规则进行路由,否则不进行路由(报404) # - Cookie=apikey, \d+ #只要请求中包含apikey属性的参数即可匹配路由。如果符合规则进行路由,否则不进行路由(报404) # - Query=apikey # - Host=**.ityouknow.com #通过设置某个 ip 区间号段的请求才会路由,即符合这个网段的可以访问,例如:http://192.168.1.131:8770/ # - RemoteAddr=192.168.1.1/24 # 过滤规则 filters: #截取路径的个数 - StripPrefix=1 #在URL路径前面添加一部分的前缀,例如:配置 - Path=/** , 请求路径为localhost:8770/idcard,
#会转变为localhost:8770/identity/idcard # - PrefixPath=/identity - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback #如果服务调用异常会回调自定义的/fallback请求 - id: credit-service uri: lb://Eureka中的服务名称2 predicates: - Path=/credit/** filters: - StripPrefix=1 - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback #如果服务调用异常会回调自定义的/fallback请求 - name: RequestRateLimiter #名称必须是 RequestRateLimiter args: redis-rate-limiter.replenishRate: 2 #允许用户每秒处理多少个请求 redis-rate-limiter.burstCapacity: 3 #令牌桶的容量,允许在一秒钟内完成的最大请求数 key-resolver: "#{@userKeyResolver}" #使用 SpEL 按名称引用 bean - name: Retry args: #重试次数,默认值是3次 retries: 3 series: - SERVER_ERROR #满足的status statuses: - BAD_GATEWAY methods: - GET - POST exceptions: - java.io.IOException - java.util.concurrent.TimeoutException - java.lang.RuntimeException #是否与服务注册于发现组件进行结合,通过 serviceId 转发到具体的服务实例。
#默认为 false,设为 true 便开启通过服务中心的自动根据 serviceId 创建路由的功能。 #这个不用配置也可以 # discovery: # locator: # enabled: true # hystrix 信号量隔离,30秒后自动超时 hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 30000 logging: level: org.springframework.cloud.gateway: debug

 

以上配置启动类中用到的注解

package com.dkjk.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class DkjkGatewayServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(DkjkGatewayServiceApplication.class, args);
    }

}

限流配置代码

package com.dkjk.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

/**
 * @Description:
 * @Author: qjc
 * @Date: 2019/11/6
 */
@Configuration
public class Config {
    @Bean
    KeyResolver userKeyResolver() {
//        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));//根据请求参数中的 user 字段来限流
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());//根据请求 IP 地址来限流
    }
}

熔断回调代码:

package com.dkjk.gateway.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description:
 * @Author: qjc
 * @Date: 2019/11/6
 */
@RestController
@Slf4j
public class FallbackController {

    @GetMapping("/fallback")
    public String fallback() {
        log.info("回调了");
        return "Hello World!\nfrom gateway";
    }

}

 

posted @ 2019-11-27 17:47  劈天造陆  阅读(1557)  评论(0编辑  收藏  举报