Spring Cloud Gateway集成Nacos和Swagger聚合Api文档

一、Gateway服务网关

1.1 什么是网关

服务网关又称API网关,是系统对外的唯一入口,封装了系统的内部架构。所有的客户端和消费端,都通过网关接入微服务,在网关层处理非业务逻辑。API网关不是微服务场景中的必须组件,如图没有网关,微服务一样可以对外提供服务
在这里插入图片描述
但是对应微服务数量较多,复杂度比较高的系统,使用网关可以带来一些好处

  • 聚合接口,使得服务对调研者透明,降低客户端与服务端的耦合度
  • 聚合后台服务,节省流量,提升用户体验
  • 提供安全,流量控制、API监控、计费等功能

1.2 Spring Cloud Gateway

Spring Cloud Gateway做Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,它不仅提供统一的路由方式,并且基于Filter链的方式提供了网关的基本功能。旨在提供一种简单而有些的方法来路由到API。使用Spring Cloud Gateway有如下优点

  • 客户端只与网关交互,降低客户端的复杂度
  • 解决了特定场景的跨越问题
  • 集成actuator,进行监控和健康检查
  • 集成Hystrix,进行服务熔断和限流

解决的问题:
在这里插入图片描述

1.3 其他

网关除了以上功能外,还可以做如下功能

  • 统一的安全认证(token验证),使用全局过滤器
  • 验证码产生与验证、短信验证码认证,使用自定义端点(RouterFunctions)免校验
  • Swagger的Api文档聚合,集成Swagger,过滤Swagger的端点进行处理
  • 无需认证的配置信息,使用自定义端点免校验

二、Gateway环境与配置

2.1 pom.xml

这块所有的版本都在父工程定义好了

  • SpringBoot 2.6.5
  • SpringCloud 2021.0.1
  • SpringCloudAlibaba 2021.0.1.0

2.1.1 gateway

gateway依赖了swagger和openfeign,这两个单独封装成公共包方便使用。自己学习可以合到一起,先看gateway的pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
        <!--添加bootstrap的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <!--gateway 网关依赖,内置webflux 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <!--swagger的依赖-->
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>mms-common-swagger</artifactId>
        </dependency>
         <!--openfeign的依赖-->
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>mms-common-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

2.1.2 sawgger

swagger的使用前面讲过SpringBoot2.6.5集成Swagger3和Knife3,使用相同的依赖即可,替换上面的mms-common-openfeign

2.1.3 openfeign

替换上面的mms-common-swagger

    <!--feign服务间调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--注册中心客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--配置中心客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--客户端负载均衡策略,替换原来的Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

2.2 bootstrap.yml

server:
  port: 8081

logging:
  level:
    com.alibaba.nacos.client.config.impl: ERROR

management:
  endpoints:
    web:
      exposure:
        include: "health,prometheus"
  endpoint:
    health:
      show-details: always
  metrics:
    tags:
      application: ${spring.application.name}

spring:
  application:
    name: gateway-center
  #设置Web模式为reactive
  main:
    web-application-type: reactive
  cloud:
    nacos:
      discovery:
        namespace: 7d720891-624c-4677-90fe-9004a3f73888
        server-addr: http://192.168.136.133:8848
        file-extension: yml
        # Nacos 服务开启认证时需要配置
        # username: 
        # password: 
        # context-path: nacos
      config:
        namespace: 7d720891-624c-4677-90fe-9004a3f73888
        server-addr: http://192.168.136.133:8848
        file-extension: yml
        # 读取Nacos配置时间(默认3000,单位:毫秒)
        # timeout: 3000
        # Nacos 服务开启认证时需要配置
        # username: 
        # password: 
        # context-path: nacos
  gateway:
    authCenter: user-center
    authCenterUrl: /token/check
    routes:
      - id: user
        uri: lb://user-center
        auth: true
        predicates:
          - Path=/user/**
        filters:
          #使用StripPrefixGatewayFilterFactory分割路由,1代表分割1截。作用是将/user去掉
          - StripPrefix=1
          #使用自定义的
          - ValidateCode=true
        urls:
          - pattern: /user/oauth/**
          - pattern: /user/token/logout
      - id: admin
        uri: lb://admin-service
        auth: true
        predicates:
          - Path=/admin/**
        filters:
          - StripPrefix=1

swagger:
  title: mms cloud API
  license:  Powered By yex
  licenseUrl: https://demo.com/
  terms-of-service-url: https://demo.com/
  contact:
   email: xx@qq.com
   url: https://demo.com/about.html
  authorization:
    name: auth-center
    auth-regex: ^.*$
    authorization-scope-list:
      - scope: server
        description: server all
    token-url-list:
      - http://${GATEWAY-HOST:gateway-center}:${GATEWAY-PORT:8081}/auth/oauth/token

三、Swagger聚合配置

聚合Api文档就是将其他微服务的api文档地址合到一起,形成一个下拉选择。启动网关和用户中心看看效果
在这里插入图片描述

3.1 SwaggerProviderConfig

用于读取gateway的路由配置信息,封装成SwaggerResource,这些信息会在/doc.html页面展示

@Slf4j
@Primary
@Component
public class SwaggerProviderConfig implements SwaggerResourcesProvider {

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

    @Autowired
    private SwaggerProperties swaggerProperties;

    @Autowired
    private GatewayProperties gatewayProperties;

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        Set<String> strings = new HashSet<>();// 记录已经添加过的server
        gatewayProperties.getRoutes().stream()
                .filter(routeDefinition -> !swaggerProperties.getIgnoreProviders().contains(routeDefinition.getUri().getHost()))
                .forEach(routeDefinition -> {
                            String url = "/" + routeDefinition.getId() + API_URI;// 拼接url
                            if (!strings.contains(url)) {
                                strings.add(url);
                                SwaggerResource swaggerResource = new SwaggerResource();
                                swaggerResource.setUrl(url);///设置服务文档user-center/v3/api-docs
                                swaggerResource.setName(routeDefinition.getUri().getHost());//设置服务名user-center
                                swaggerResource.setSwaggerVersion("3.0");
                                resources.add(swaggerResource);
                            }
                        }
                );
        return resources;
    }
}

3.2 RouterFunctionConfiguration

gateway使用的webflux,不支持webmvc。对swagger的路由添加处理器,来处理接口请求

@Slf4j
@Configuration
@AllArgsConstructor
public class RouterFunctionConfiguration {

    private final HystrixFallbackHandler hystrixFallbackHandler
    private final SwaggerSecurityHandler swaggerSecurityHandler;
    private final SwaggerUiHandler swaggerUiHandler;
    private final SwaggerResourceHandler swaggerResourceHandler;

    @Bean
    public RouterFunction routerFunction() {
        return RouterFunctions.route(
                RequestPredicates.path("/fallback")
                        .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), hystrixFallbackHandler)
                .andRoute(RequestPredicates.GET("/swagger-resources")
                        .and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
                .andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
                        .and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler)
                .andRoute(RequestPredicates.GET("/swagger-resources/configuration/security")
                        .and(RequestPredicates.accept(MediaType.ALL)), swaggerSecurityHandler);
    }

}

3.3 SwaggerResourceHandler

@Slf4j
@Component
@AllArgsConstructor
public class SwaggerResourceHandler implements HandlerFunction<ServerResponse> {
    private final SwaggerResourcesProvider swaggerResources;

    /**
     * Handle the given request.
     *
     * @param request the request to handler
     * @return the response
     */
    @Override
    public Mono<ServerResponse> handle(ServerRequest request) {
        return ServerResponse.status(HttpStatus.OK)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(swaggerResources.get()));
    }
}

3.4 SwaggerSecurityHandler

@Slf4j
@Component
public class SwaggerSecurityHandler implements HandlerFunction<ServerResponse> {
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;

    /**
     * Handle the given request.
     *
     * @param request the request to handler
     * @return the response
     */
    @Override
    public Mono<ServerResponse> handle(ServerRequest request) {
        return ServerResponse.status(HttpStatus.OK)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(
                        Optional.ofNullable(securityConfiguration)
                                .orElse(SecurityConfigurationBuilder.builder().build())));
    }
}

3.5 SwaggerUiHandler

@Slf4j
@Component
public class SwaggerUiHandler implements HandlerFunction<ServerResponse> {

    @Autowired(required = false)
    private UiConfiguration uiConfiguration;

    /**
     * Handle the given request.
     *
     * @param request the request to handler
     * @return the response
     */
    @Override
    public Mono<ServerResponse> handle(ServerRequest request) {
        return ServerResponse.status(HttpStatus.OK)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(
                        Optional.ofNullable(uiConfiguration)
                                .orElse(UiConfigurationBuilder.builder().build())));
    }
}

四、遇到的问题

4.1 webflux与mvc不兼容

webflux与mvc不兼容会导致各种问题
解决方法一:
在依赖中排除MVC相关的jar包

<!--spring cloud gateway是基于webflux的,与web不兼容-->
<exclusions>
    <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </exclusion>
</exclusions>

排除spring-boot-starter-web之后又可能导致一些类找不到报错,例如我这里使用了CommonResponseDataAdvice implements ResponseBodyAdvice做全局返回值处理,就报ResponseBodyAdvice找不到。排除了CommonResponseDataAdvice 都不行
解决方法二:
在配置文件增加如下配置

spring: 
  #设置Web模式为reactive
  main:
    web-application-type: reactive

使用方案二,完美解决。

4.2 swagger异常

swagger文档出不来,f12发现/v3/api-docs报错,检查SwaggerProviderConfig的配置,一般是url配错。反复调试即可解决

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值