基于Swagger完成API网关与用户CICD流程整合

本文主要用于介绍用户CICD流程与API网关整合的通用方法实践。该方法的核心是以swagger为桥接,通过API网关的ImportSwagger接口来完成您的API的自动创建和更新。

一、概述

API网关提供了完备的OpenAPI接口,用户可以通过这些接口完成API网关的管理需要。用户CICD集成API网关的核心,其实就是对API网关提供的管理接口进行封装整合。

如下图所示, 一个整合了API网关的通用CICD流程,主要有如下步骤:

  • 步骤1:自动从您的API业务代码中获取swagger定义

  • 步骤2:创建API分组

  • 步骤3:通过API网关的OpenAPI导入API定义,并发布在不同的环境中

  • 步骤4:对API进行各项额外配置

自动获取Swagger定义

用户开发时,可以自行整合一个API DOC框架(本文示例选择的是SpringFox)到自己的后端服务中。这些框架一般对原有代码都是无侵入的,所以接入相对方便。同时,API DOC框架随后端服务启动时,提供Swagger的获取接口。API网关通过访问这些接口,自动获取Swagger定义

创建API分组

用户可以在API网关控制台手动创建分组,或者通过CreateApiGroup - 创建API分组创建分组。用户创建分组后,可以进行绑定独立域名以及绑定证书等操作。

通过OpenAPI导入API并发布

用户通过集成API网关提供的ImportSwagger接口,并将Swagger获取接口获取的swagger数据作为参数,完成API的创建工作。在完成API在API网关的创建后,用户可以将其发布到所需的环境。完成API的发布后,用户即可访问对应的服务。

额外配置

为了更灵活的满足用户个性化管理需求,API网关提供了丰富的插件。包括:流量控制插件,IP访问控制插件,CORS插件以及JWT插件等。并根据需求选择配置相关的插件,来丰富该接口的鉴权及管控能力。

二、实现示例

本章节对提供的示例代码进行讲解说明,本文的示例代码仅提供了最基本的cicd场景,用户可根据实际情况进行调整和扩充。

2.1 示例代码

alibabacloud-cloudapi-java-cicd-demo

2.2 相关技术

本示例主要使用到的相关技术如下:

2.2.1 API网关相关链接

  1. 导入API网关的扩展Swagger定义介绍了如何配置可导入API网关的Swagger文件,API网关通过设计swagger支持的扩展内容,来完成标准swagger的直接导入和带有用户自定义配置的swagger导入。

  2. ImportSwagger - 通过 Swagger 创建 API介绍了ImportSwagger接口。接口中主要参数为:

  • groupId: 用于存储用户swagger导入的API的分组ID。

  • data: 用户的swagger文件 。

  • globalCondition: 用于用户添加自定义的配置内容, 比如通过x-apigateway-backend-info标签,加入用户自定义后端的内容。

2.2.2 SpringFox

为了更直观的展示如何运用swagger便捷的将后端服务同步到API网关中,本文提供了一个使用SpringFox库的后端服务。 SpringFox是一个开源的API DOC的框架,它可以通过为服务Controller接口添加注释的方式,便捷的形成swagger,并在服务运行时,提供获取swagger的接口。

2.3 服务端自动生成swagger定义

服务端创建了一个基于springboot的极简Web服务,用于展示一般用户基于现有服务提供swagger的方法。

2.3.1 依赖库

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

2.3.2 SpringFox的配置

SpringFox是对用户原始服务相对友好的框架。用户无需对现有的接口和模型类进行任何修改,仅需要增加一个SpringFox的配置类,即可完成Springfox框架的接入工作。在服务启动后,该框架会自动解析springboot web框架中的注释,来自动生成swagger中所需的服务信息。同时,对于服务中引用的类进行解析,来生成swagger所需的模型信息。

SpringFox框架的配置项

本示例中,配置项进行了如下核心设置:

  • 指出文档格式(Swagger2)

  • 指出用于生成API DOC的包名

@Configuration
@EnableSwagger2
public class SpringFoxConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
                .paths(PathSelectors.any())
                .build();
    }
}

如何查看Swagger

启动服务后, 可以通过访问https://localhost:8080/swagger-ui.html来打开swagger UI来进行swagger提供的功能,具体查看官网swagger.io说明。

从截图中我们可以看到, 示例代码中的服务接口以及模型类均已被自动解析

如何获取Swagger

为了可以接入用户CICD的流程,获取swagger内容的接口是必不可少的。用户启动服务后,用户可以通过/v2/api-docs接口获取swagger内容。

2.4 创建API分组

用户可以通过以下方式创建分组

2.4.1 通过控制台创建

用户通过在API网关控制台-分组管理界面创建分组。完成分组创建后,可以进入分组详情页,查看对应的分组ID及其他相关信息。

2.4.2 通过OpenAPI创建API分组

通过API网关的openapi提供的CreateApiGroup - 创建API分组接口完成APIGroup的创建。同时,用户可以配合其他API完成用户独立域名以及绑定证书等其他操作。

2.5 ImportSwagger接口的使用

用户能否实现基于API网关的CICD流程,其核心关键是:

  • 是否有接口可以获取swagger

  • 标准swagger如何导入API网关

如2.2.2章节所介绍的内容. 我们已经可以获取描述后端服务所有接口和模型的swagger. 如何将标注的Swagger导入到API网关是我们本章节的重点.

2.5.1 基于API网关的Swagger扩展

API网关为了便于用户体验API网关的能力,支持将原生Swagger导入到API网关中。通过这种方式,API网关会自动创建基于Swagger的所有API,并且其默认后端为MOCK形式。

但是,用户真实的CICD场景往往需要的是API网关创建的API最终真正的访问到用户的后端服务。这样,就需要用户进行后端服务信息的配置。但是,这些信息原生的swagger是不具备的,所以,API网关提供了基于Swagger的扩展。

基于Swagger的扩展主要包括:后端服务配置,后端参数配置,认证方式等API网关所必须的或者特有的内容的配置。这些拓展支持全局配置。同时,也支持每个API中单独配置。 最终达到,用户原生swagger配合API网关swagger扩展,真正实现满足用户生产环境所需的API配置。

本文示例中,仅使用了x-apigateway-backend-info扩展来进行说明。示例中,用户的后端服务HTTP服务,我们假设其线上域名为www.aliyun.com。当然,后段地址也可以通过#环境变量#的形式进行配置。

我们在导入API网关的扩展Swagger定义一文中查看后端为HTTP类型的后端如何配置,其中type和address为必填项,后端path和method为空时,当前API的请求地址和HTTP方法,timeout默认为10000ms。

x-aliyun-apigateway-backend:
  type: HTTP
  address: 'http://www.aliyun.com'
  path: '/builtin/echo'
  method: get
  timeout: 10000

2.5.2 通过ImportSwagger导入用户原生Swagger

ImportSwagger是用户原生Swagger导入到API网关的核心入口。这个接口有三个核心参数:

  • GroupId:用于指定存储swagger导入API的分组。

  • data:用于指定用户原生的Swagger。

  • globalCondition:用于传入用户的自定义配置,如通用后端服务地址。

Maven依赖

        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-cloudapi</artifactId>
            <version>4.9.3</version>
        </dependency>

获取用户原生swagger

上文已经提及,用户在完成SpringFox框架引入和配置后,在服务启动时,就会自动生成/v2/api-docs接口用于获取描述后端服务的swagger。

    private String getSwaggerData(){
        HttpURLConnection connection = null;
        ...
        ...
        String result = null;
        try {
            URL url = new URL(swaggerApiDocUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
                                                ...
            ...
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
                                                ...
            ...
            connection.disconnect();
        }
        return result;
    }

配置基于API网关的Swagger扩展

正确的配置Swagger扩展是用户通过导入Swagger创建满足其需求的API的核心环节. 这些基于API网关的swagger扩展可以通过ImportSwagger接口中的globalCondition参数传入. globalCondition的格式为Json String。

  • key: 基于swagger的API网关扩展的名称, 如:x-apigateway-backend-in

  • value: 对应swagger扩展的值。

示例代码中,通过配置API的通用后端地址,实现导入API网关的API可以访问到其真正的后端服务。

为了示例代码的整洁,我们根据2.5.1中HTTP类型的后端服务说明,创建SwaggerBackendInfoBase类,用于配置后端服务信息。

public class SwaggerBackendInfoBase {
    private String type;
    private String address;
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

我们根据用户的后端服务信息,完成globalCondition参数的赋值。

            // 配置API网关所需的服务后端信息
            SwaggerBackendInfoBase info = new SwaggerBackendInfoBase();
            info.setType("HTTP");
            info.setAddress("http://www.aliyun.com");
            // 将API的后端服务后端信息
            Map<String, String> globalCondition  = new HashMap<>();
            globalCondition.put("x-aliyun-apigateway-backend", JSON.toJSONString(info));

ImportSwagger

上文中,我们已经完成了Group的创建,原生Swagger的获取以及GlobalCondition参数的创建。我们调用API网关openapi提供的ImportSwagger接口完成API的导入,并可以API网关控制台查看导入结果。

2.6 部署API

用户可以在API管理页面选择对应的分组,通过选择需要发布的API进行发布.用户通过发布使导入的API生效。

三、总结

自此, 如何将用户后端服务的API接口快速的同步到API网关已经完成。API网关致力于让用户专注于后端服务的开发, 将认证、流控等通用切面功能交给API网关处理,结合ImportSwagger接口的使用,完成后端服务与API网关的联动,大大减少了API网关的配置过程。同时,让API网关的配置和管理集成到用户的CICD流程中成为可能。