微服务 - GateWay使用

传统的接口实现:
客户端 - 》 控制器A -》 服务1 -》 dao
客户端 - 》 控制器B -》 服务2 -》 dao

网关实现:
客户端 - 》gateway - > 服务1/服务2 -》 dao

gateway 好处
1. 去掉控制器,将http请求无缝接入服务接口
2. 统一出入参格式
3. 统一异常规范
4. 自动检测服务接口规范

客户请求 -> gateway:9001 -> 服务1: 8081 | 服务2: 8082 | other: 808n
具体的微服务IP 端口都不同 ,客户端就不用关心每个微服务的ip端口了,直接通过geteway访问即可(类似nginx网关路由)
通过geteway的yml或.properties配置好映射关系,服务启动后自动会去eureka获取微服务

在SpringCloud 全家桶中网关中提供Zuul 服务组件,后来升级为Gateway
微服务网关有
    路由转发:根据请求的url中的特征匹配到具体微服务中
    权限控制:实现了GlobalFilter接口,请求的url中 可以对token进行验证
    过滤: 如特殊字段 字符的过滤 再做熔断提示
    服务限流:并发请求微服务的阈值
    黑白名单控制等


一、准备
创建网关工程 pom.xml 加入:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
启动类配置
@EurekaClient
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
     public static void main(String[] args) {
         SpringApplication.run(GatewayApplication.class, args);
     }
 }
1.1 :路由
server:
    port: 8080
spring:
    application:
        name: gateway
    devtools: // 热部署 修改自动重启 pom需要引入
        restart:
            enabled: true
    cloud:
        gateway:
            routes:
               - id: service_name           # 微服务名
              uri: https://127.0.0.1:8081 # 微服务uri
              predicates:                # 匹配规则关键字
                 - Path=/**               # 任意字符都可以可以进行路由 routes中一些配置与zuul类似写法的区别
            routes:
               - id: service_name
               uri: https://127.0.0.1:8082
               predicates:
                   - Path=/**
           discovery:                         # 开启服务名称转发 注:开启redis限流此处即可不需要
               locator:
                   enabled: true            # true配置 访问前缀必须有微服务名称 否则 无法访问

# 注册中心地址
eureka:
    client:
        service-url:
            defaultZone: http://127.0.0.1:9091/eureka
    instance:
        instance-id: 127.0.0.1:9091  
        prefer-ip-address: true

1.2 权限
    @Component
    class TokenFilter implements GlobalFilter, Ordered { // GlobalFilter内置的全局过滤器 , Ordered执行顺序级别(很多拦截器)
        @Override
        int getOrder() { return 1; } // 值越小越先执行
        @Override
        Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
             String token = exchange.getRequest().getQueryParams().getFirst("Authroization");
             // 然后根据token结合业务做处理
        // 比如:拿token与jwt或redis 校验 或者只判断是否有token 如果有就放行给微服务去处理 都可以 一般不放行
        // 还有做的完善点的 专门启用一个鉴权客户端服务端工程,然后在鉴权服务端
    ...
        return chain.filter(exchange);
  }
   }

1.3 限流
令牌桶概念:匀速生产令牌 - > 令牌桶容量 - > user去消耗令牌
以下用redis实现桶
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
spring:
    redis:
        host: 192.168.92.10
        port: 6379
        database: 0
    cloud:
        gateway:
            routes:
          - id: service_name
               uri: lb://service_name
               predicates:
         - Path=/serviceName/**
          filters:
      - RewritePath=/serviceName/(?<segment>.*), /$\{segment} # 由于服务名转发注掉 又想根据项目名访问
      - name: RequestRateLimiter # 拦截器 对上面routes进行拦截
      args:
        key-resolver: '#{@uriKeyResolver}'   # redis限流入口
        redis-rate-limiter.replenishRate: 1     # 令牌桶每1s 向令牌桶加一次令牌
        redis-rate-limiter.burstCapacity: 2     # 令牌桶每1s之内 最多访问2次

// redis限流入口 

@Bean
public KeyResolver uriKeyResolver(){
  return new KeyResolver(){
    @Override
    public Mono<String> resolve(ServerWebExchange exchange){
      // 获得用户请求的地址 进行限流
      return Mono.just(exchange.getRequest().getRemoteAddress().getHostAddress()); // 监控远程请求地址
    }
  }
}

posted @ 2020-04-01 11:50  吴某1  阅读(1641)  评论(0编辑  收藏  举报