goa-3-Goa.runtime总结 | KaiQ.Gu|KerwinKoo Blog
goa Runtime 在goa package中做了实现,包括HTTP request state和response行为管理、基本数据结构和算法的实现、日志记录、错误处理和支持版本控制等功能。
Goa 行为上下文管理(action context)
Goa 通过实现一个数据结构,并存在于所有的Goa controller实现(以第一个参数传参的方式),来实现行为的上下文管理。该方法是参考google实现的接口间信息传递的方法,同时根据Goa自身情况做了修改。
与其他Go实现的web框架类似,Goa的REST 资源(行为上下文)会开放接口供外部访问。像路径参数、查询结果这样的API可以直接通过GET方法来获取返回值。在此基础上Goa更进一步,用户通过goagen工具生成的代码中,根据design中指定的参数type进行强制准入检验。比如,我们在design时定义一个类型为Integer的ID,则goagen生成的ID字段中也会定义为int,并对该资源的访问进行健壮性检验(比如对ID赋值string时会返回错误),防止在server内部将收到的值赋值给结构体时发生错误。
同样,在writing response阶段,Goa根据设计时的media type需求,对返回值进行写入操作。
之前讲到,每个controller的Action全过程都有一个action context管理,因此在开发过程中,每个Action的实现都包含deadline和cancelation信号管理。同时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实现,实现代码为:
1 | // PathSelectVersionFunc returns a SelectVersionFunc that uses the given path pattern to extract the |
同时Goa也提供其他访问方式的version 路由管理。包括PathSelectVersionFunc、HeaderSelectVersionFunc和QuerySelectVersionFunc。
日志、错误处理及服务退出
日志存在于Goa server的整个运行时,同时包含通信过程中的全部信息:server name、controller name、action 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.:
1 | package design |
在代码生成阶段,goagen会将不同版本的ServerMux接口挂载到对应版本的API路由中。
在Design阶段中设计的每一个版本的API都会生成一个独立的package,来包含其对应的API controllers。
在Goagen所生成的server代码中,全部都是围绕着ServerMux方法来检索(retrieve)顶层路由。而Goa底层路由的实现则是依赖于包httprouter。其他中间层路由均可ServerMux接口实现。