goa Runtime 运行时

发布于 2024-10-13 08:42:28 字数 4733 浏览 10 评论 0

goa Runtime 在 goa package 中做了实现,包括 HTTP request stateresponse 行为管理、基本数据结构和算法的实现、日志记录、错误处理和支持版本控制等功能。

Goa 行为上下文管理(action context)

Goa 通过实现一个数据结构,并存在于所有的 Goa controller 实现(以第一个参数传参的方式),来实现行为的上下文管理。该方法是参考 google 实现的接口间信息传递的方法,同时根据 Goa 自身情况做了修改。

与其他 Go 实现的 web 框架类似,Goa 的 REST 资源(行为上下文)会开放接口供外部访问。像路径参数、查询结果这样的 API 可以直接通过 GET 方法来获取返回值。在此基础上 Goa 更进一步,用户通过 goagen 工具生成的代码中,根据 design 中指定的参数 type 进行强制准入检验。比如,我们在 design 时定义一个类型为 IntegerID ,则 goagen 生成的 ID 字段中也会定义为 int ,并对该资源的访问进行健壮性检验(比如对 ID 赋值 string 时会返回错误),防止在 server 内部将收到的值赋值给结构体时发生错误。

同样,在 writing response 阶段,Goa 根据设计时的 media type 需求,对返回值进行写入操作。

之前讲到,每个 controller 的 Action 全过程都有一个 action context 管理,因此在开发过程中,每个 Action 的实现都包含 deadlinecancelation 信号管理。同时 Goa 内嵌 Timeout 中间件,可以为所有 request 定义 timeout 值。

Goa 功能支持

Server Mux

Goa 通过实现 ServeMux 接口来管理请求的路由,该接口包含一个 Handle 方法,可以将 HTTP 请求的 method 和 url 路径交付给指定 HandleFunc ,通过此函数进行信息处理和反馈。 HandleFunc 作为 Handle method 的最后一个参数,基本不需要人为修改,其作用主要是为 goagen 生成的代码服务。

This function is intended for the controller generated code. User code should not need to call it directly.

另外, ServeMux 接口有个 version 方法,可以通过其进行版本控制。对不同版本的 HTTP 请求做对应版本的路由处理。该功能通过函数 SelectVersionFunc 实现,实现代码为:

// PathSelectVersionFunc returns a SelectVersionFunc that uses the given path pattern to extract the
// version from the request path. Use the same path pattern given in the DSL to define the API base
// path, e.g. "/api/:version".
// If the pattern matches zeroVersion then the empty version is returned (i.e. the unversioned
// controller handles the request).
func PathSelectVersionFunc(pattern, zeroVersion string) SelectVersionFunc {
	rgs := design.WildcardRegex.ReplaceAllLiteralString(pattern, `/([^/]+)`)
	rg := regexp.MustCompile("^" + rgs)
	return func(req *http.Request) (version string) {
		match := rg.FindStringSubmatch(req.URL.Path)
		if len(match) > 1 && match[1] != zeroVersion {
			version = match[1]
		}
		return
	}

同时 Goa 也提供其他访问方式的 version 路由管理。包括 PathSelectVersionFuncHeaderSelectVersionFuncQuerySelectVersionFunc

日志、错误处理及服务退出

日志存在于 Goa server 的整个运行时,同时包含通信过程中的全部信息: server namecontroller nameaction name 和一个全局唯一的 request ID

所有 Goa 的 Action 均会返回一个类型为 error 的变量,当此 error 变量不是 nil 时,定义的 controller error handler 会自动调用。默认情况下发生访问错误时会返回一个 500 ERROR 和具体的报错信息。

Goa server 通过 NewGraceful 方式,在保证所有已发送的请求全部处理过后,再进行终止服务。

定制开发

Error Handling

Goa 可以通过 SetHandler 方法来重写默认的 service 错误处理。同时 Goa 也提供两个内嵌 error handlers:

  • DefaultErrorHandler :当发生 BadRequestError 接口类 error 时返回 400,否则返回 500,并 response body 中记录错误日志。
  • TerseErrorHandler :返回错误的逻辑与 DefaultErrorHandler 相同,只不过该 Handler 不会将内部(internal)错误写入 response body 中。

路由规则和 API 版本控制

正如之前所讲,Goa 支持 API 路由到不同的版本中,该功能可以在设计阶段通过 Version 字段进行指定:

e.g.:

package design

import (
        . "github.com/goadesign/goa/design"
        . "github.com/goadesign/goa/design/dsl"
)

var _ = API("cellar", func() {
        Description("A basic example of an API implemented with goa")
        Scheme("http")
        Host("localhost:8080")
})

var _ = Version("1.0", func() {
        Title("The virtual winecellar v1.0 API")
        // ... other API level properties
})

var _ = Version("2.0", func() {
        Title("The virtual winecellar v2.0 API")
        // ... other API level properties
})

var _ = Resource("bottle", func() {
        BasePath("/bottles")
        Version("1.0")
        Version("2.0")
        // ... other resource properties
})

var _ = Resource("bottle", func() {
        BasePath("/bottles")
        Version("3.0")
        // ... other resource properties
})

在代码生成阶段,goagen 会将不同版本的 ServerMux 接口挂载到对应版本的 API 路由中。

在 Design 阶段中设计的每一个版本的 API 都会生成一个独立的 package,来包含其对应的 API controllers

在 Goagen 所生成的 server 代码中,全部都是围绕着 ServerMux 方法来检索(retrieve)顶层路由。而 Goa 底层路由的实现则是依赖于包 httprouter 。其他中间层路由均可 ServerMux 接口实现。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

奢望

暂无简介

0 文章
0 评论
831 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文