5.【threeking】增加网关Gateway

5.增加网关Gateway

实际开发过程中,前端有很多调用方,不可能实际调用每一个底层服务,spring cloud之前采用netfix出的zuul来解决,后来因为开源问题,spring boot团队自己开发了Gateway来代替之前的zuul。

1.创建独立的Gateway网关项目

引用spring cloud gateway包,

 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

因为我们使用nacos,所以将spring-cloud-starter-alibaba-nacos-discovery也引进来

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

修改驱动项增加@EnableDiscoveryClient

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ThreekingGatewayApplication {

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

}

bootstrap.yml文件中添加配置

spring:
  application:
    name: threeking-gateway
  cloud:
    nacos:
      discovery:
        namespace: f9432bb6-6ba5-4f5a-998b-c2b2e7815528 #nacos分组,不配置默认为public
        password: nacos
        server-addr: 127.0.0.1:8848
        username: nacos
    gateway:
      discovery:
        locator:
          enabled: true #locator 采用路由匹配
      routes:
        - id: threeking-user
          uri: lb://threeking-user  #服务项目名,和nacos上服务对应
          predicates:
            #- Method=GET,POST
            - Path=/user/**		#匹配路由规则
          filters:
            - StripPrefix=1  #截取地址一节
server:
  port: 6600

nacos上的展示效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xmy8Yjvl-1604471421732)(C:\Users\yonghu\AppData\Roaming\Typora\typora-user-images\image-20201023153636235.png)]

访问地址:http://localhost:6600/user/hello

解析:

  • http://localhost:6600 为网关地址
  • /use为路由指定标识
  • /hello为user服务hello接口
2.全局过滤

GatewayFilter Factories

Global Filters

3.网关限流

3.1 使用Gateway进行限流,三种方式

  • url限流
  • 参数限流
  • IP限流

RequestRateLimiter GatewayFilter Factory

需要使用redis 所以要添加spring-boot-starter-data-redis-reactive

<!-- redis依赖包-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!--commons-pool2 对象依赖池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

3.2 使用Sentinel

Sentinel中文文档

spring cloud alibaba sentinel 和spring cloud gateway整合

4.GateWay整合swagger

swagger常用的有两种UI,一种是swagger-ui、swagger-bootstrap-ui

  • swagger-ui 官方的,没啥不好,可以用
  • swagger-bootstrap-ui 国内大佬开发的,很多人都在用
  • swagger-bootstrap-ui新版已经改为knife4j了

引包

<!-- swagger2 start -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>
<!-- swagger2 end -->

为啥要单独说gateway和swagger2整合,是因为swagger的资源接口支持的是spring MVC模式,而Gateway采用是webflux,因此,3.0.0之前都需要自己手动写配置

4.1旧版解决方案

扩展SwaggerResourcesProvider,springfox-swagger包可以试3.0.0之下的依赖

package com.threeking.gateway.swagger;

import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.ArrayList;
import java.util.List;

@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider {
 
    public static final String API_URI = "/v2/api-docs";
 
    private final RouteLocator routeLocator;
 
    private final GatewayProperties gatewayProperties;
 
    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();
 
        // 取出gateway的route
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        // 结合配置的route-路径(Path),和route过滤,只获取有效的route节点
        // 打开下面注释可以自动扫描接入gateway的服务,为了演示,只扫描system
        gatewayProperties.getRoutes().stream().filter(routeDefinition ->  routes.contains(routeDefinition.getId()))
                .forEach(routeDefinition ->
                         routeDefinition.getPredicates().stream()
                        .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                        .forEach(predicateDefinition -> resources
                                .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs()
                                        .get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI)))));
        return resources;
    }
 
    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}
package com.threeking.gateway.swagger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import springfox.documentation.swagger.web.*;
import java.util.Optional;

@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
 
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;
 
    @Autowired(required = false)
    private UiConfiguration uiConfiguration;
 
    private final SwaggerResourcesProvider swaggerResources;
 
    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }
 
    @GetMapping("/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {

        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()),
                HttpStatus.OK));
    }
 
    @GetMapping("/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()
                        ), HttpStatus.OK));
    }


 
    @SuppressWarnings("rawtypes")
    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRBRnW5Z-1604471421735)(C:\Users\wanghui\AppData\Roaming\Typora\typora-user-images\image-20201024145448128.png)]

4.2新版解决方案

因为swagger2之前的不支持webflux,所以3.0之后解决了这个问题,我们不用自己再转换一套swagger-resources

直接创建一个SwaggerResourcesProvider即可

package com.threeking.gateway.swagger;

import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.*;

///**
// * 以gateway方式聚合各个服务的swagger接口文档(还可以加入healthy,去逐个匹配healthy,判断是否存活,活的话加入SwaggerResource列表,否则不加入)
// *
// */
@Component
@Primary
@AllArgsConstructor
public class Swagger3Provider implements SwaggerResourcesProvider {

    public static final String API_URI = "/v2/api-docs";

    private final RouteLocator routeLocator;

    private final GatewayProperties gatewayProperties;

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();

        // 取出gateway的route
        routeLocator.getRoutes()
                .filter(route -> route.getUri().getHost() != null)
                .filter(route -> Objects.equals(route.getUri().getScheme(), "lb"))
            	// .filter(route -> !self.equals(route.getUri().getHost()))
                .subscribe(route -> routes.add(route.getUri().getHost()));
        // 结合配置的route-路径(Path),和route过滤,只获取有效的route节点
        // 打开下面注释可以自动扫描接入gateway的服务,为了演示,只扫描system
        gatewayProperties.getRoutes().stream().filter(routeDefinition ->  routes.contains(routeDefinition.getId()))
                .forEach(routeDefinition ->
                        routeDefinition.getPredicates().stream()
                                .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                                .forEach(predicateDefinition -> resources
                                        .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs()
                                                .get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI)))));
        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}

这种是使用Gateway方式,读取yml文件中的配置,我只识别了开启动态创建路由的方式,如果使用未使用RouteLocator的.filter(route -> !self.equals(route.getUri().getHost()))改用这个过滤器即可

4.3 使用knife4j
<!-- 注释掉swagger-bootstrap-ui,引用knife4j-spring-boot-starter-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0</version>
</dependency>

其他的和4.2一样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值