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

一、概述

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

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

  • 步骤1:自动从您的API业务代码中获取swaager定义
  • 步骤2:创建API分组
  • 步骤3:通过API网关的OpenAPI导入API定义,并发布在不同的环境中
  • 步骤4:对API进行各项额外配置

自动获取Swagger定义

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

创建API分组

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

通过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. <通过导入Swagger创建API> 介绍了如何配置可导入API网关的Swagger文件. API网关通过设计swagger支持的扩展内容, 来完成标准swagger的直接导入和带有用户自定义配置的swagger导入.
  2. ImportSwagger接口说明 介绍了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

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

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

如何获取Swagger

为了可以接入用户CICD的流程, 获取swagger内容的接口是必不可少的. 用户启动服务后, 用户可以通过/v2/api-docs接口获取swagger内容. http://localhost:8080/v2/api-docs](http://localhost:8080/v2/api-docs)

2.4 创建API分组

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

2.4.1 通过控制台创建

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

2.4.2 通过OpenAPI创建API分组

通过API网关的openapi提供的CreateApiGroup接口完成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>>)

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

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

我们在<<通过导入Swagger创建API>>一文中查看后端为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-info
  • value: 对应swagger扩展的值.

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

为了示例代码的整洁, 我们根据2.2.3.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流程中成为可能.