Nirvana  - 致力于让业务无感知的 API 框架
小码哥 2019-08-17 14:43:47

Nirvana:涅槃

Nirvana,梵语中的涅槃,寓意让 API 从对框架的依赖中涅槃重生,它致力于成为让业务无感知的框架。

Nirvana 借鉴了 Kubernetes 声明式 API 的设计,巧妙规避了框架对 API 的侵入。同时,为了实现业务和框架的隔离,它定义一个规范,让 API 按照规范书写,完全屏蔽了框架对 API 的影响。

一言以蔽之,Nirvana 框架的设计思路始终围绕工程师们亲历的种种痛点:

  • 构建风格一致的 API 项目;

  • 使用统一的 RESTful 路由与声明式 API 定义,避免业务对框架产生依赖;

  • 使用统一的错误生成和处理方式;

  • 提供开箱即用的基础功能,包括 Prometheus metrics、tracing、profiling 等;

  • 自动生成 API 文档和客户端代码。

特性:

  • 统一所有 Golang 项目中的 API 行为、结构和布局

  • 通过 openAPI 和客户端生成等方式提高工程效率

  • 可以通过将验证方法声明为 API 定义的一部分来添加验证

  • 开箱即用的工具支持,例如度量、分析与跟踪等

  • 简单和标准的配置管理,以及标准的 cli 接口

此外,Nirvana 还具有可扩展性和高性能的特点,其目标是支持开发的快速迭代。

在 Nirvana 中,使用一套 API Definition 来声明式地描述业务 API。下面是一个列出消息列表 API 的例子:

Definition{
    // 这个 API 返回的是资源数组,所以使用 List 方法。
    Method:     def.List,
    // Summary 是一个短语,用于描述这个 API 的用途。这个短语在生成文档和客户端的时候用于区分 API。
    // 这个字符串去掉空格后会作为生成客户端时的函数名,因此请确保这个字符串是有意义的。
    Summary:    "List Messages",
    // 详细描述这个 API 的用途。
    Description: "Query a specified number of messages and returns an array",
    // 业务函数
    Function:   message.ListMessages,
    // 对应业务函数的参数信息。用于告知 Nirvana 从请求的那一部分取得数据,然后传递给业务函数。
    Parameters: []def.Parameter{
        {
            // 参数来源
            Source:     def.Query,
            // 参数名称,作为 key 从 Source 里取值。
            // 与业务函数的参数名称无关。
            Name:       "count",
            // 默认值
            Default:    10,
            // 参数描述
            Description: "Number of messages",
        },
    },
    // 对应业务函数的返回结果。用于告知 Nirvana 业务函数返回结果如何放到请求的响应中。
    Results: def.DataErrorResults("A list of messages"),
}

而对应业务 API 的形式则是:

type Message struct {

    ID      int `json:"id"`
    Title   string `json:"title"`
    Content string `json:"content"`
}

func ListMessages(ctx context.Context, count int) ([]Message, error) {
    messages := make([]Message, count)
    for i := 0; i < count; i++ {
        messages[i].ID = i
        messages[i].Title = fmt.Sprintf("Example %d", i)
        messages[i].Content = fmt.Sprintf("Content of example %d", i)
    }
    return messages, nil
}

很显然,业务函数并不关心自身是如何暴露给外部的,实现方法也和其他内部函数没有差别(这只是一个简单的例子,更多详细内容请查阅 Nirvana Definition 文档

在这个例子里,API Definition 描述了完整的 API 结构,包括 RESTful 路径、请求方法、请求描述、请求参数、请求响应和请求 handler。框架只需要解析 API Definition,就能得到业务逻辑的入口和出口处理方式。对开发者而言,API 的开发过程从命令式路由 + 数据转换 + 业务逻辑变成了API Definition + 业务逻辑。框架与业务逻辑之间通过 API Definition 进行桥接。

接下来的目标:

  • 持续优化扩展文档和客户端生成的能力,降低开发者在这两块上的心智负担;

  • 持续优化 metrics、profiling、tracing 的能力,并增加新的云原生能力,让这些能力成为云原生应用的标配;

  • 框架模块化加强,让 Nirvana 的每一块代码皆可定制;

  • 优化框架性能,降低反射对服务的影响;

  • 让 Nirvana 成为 Golang 的 CloudNative & SOA 框架。

感谢参与开源本项目的所有开发者!

Nirvana GitHub:https://github.com/caicloud/nirvana

Nirvana 文档:https://caicloud.github.io/nirvana/zh-hans/