k8s APIServer源码: go-restful框架
基于版本 1.6.7
k8s的APIServer, 使用了go-restful作为其处理框架, 注册资源并接收处理 HTTP 请求.
在阅读APIServer源码之前, 需先理解go-restful主要概念.
intro
package for building REST-style Web Services using Google Go
concepts
- Container: 一组WebService的集合, 目的:
Containers for WebServices on different HTTP endpoints.
- WebService: Route的集合; 为一组Route定义统一的 root path / 请求类型 / 响应类型
- Route: 定义method/ULR path/调用函数/文档/参数/ curly route; 支持正则及动态谭树
- Filter:
Filters for intercepting the request → response flow on Service or Route level
, 可以加global / Webservice / Route
各自的filter
init steps:
- create container
- create resource WebService
-
define route, path, filter and bind to route handler
-
add router to WebService
- add WebService to container
- new server with
Handler=container
- start server
examples
- 示例1: use default containers
ws := new(restful.WebService)
ws.
Path("/users").
Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML)
ws.Route(ws.GET("/{user-id}").To(u.findUser).
Doc("get a user").
Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
Writes(User{}))
...
func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
id := request.PathParameter("user-id")
...
}
- 示例2: 含多个container
// https://github.com/emicklei/go-restful/blob/master/examples/restful-multi-containers.go
// GET http://localhost:8080/hello
// GET http://localhost:8081/hello
package main
import (
"github.com/emicklei/go-restful"
"io"
"log"
"net/http"
)
func main() {
// add to default container
ws := new(restful.WebService)
ws.Route(ws.GET("/hello").To(hello))
restful.Add(ws)
go func() {
log.Fatal(http.ListenAndServe(":8080", nil))
}()
// container 2
container2 := restful.NewContainer()
ws2 := new(restful.WebService)
ws2.Route(ws2.GET("/hello").To(hello2))
container2.Add(ws2)
server := &http.Server{Addr: ":8081", Handler: container2}
log.Fatal(server.ListenAndServe())
}
func hello(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "default world")
}
func hello2(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "second world")
}
- 示例3: 包含 filter
// filter https://github.com/emicklei/go-restful/blob/master/examples/restful-filters.go
// Global Filter
func globalLogging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
log.Printf("[global-filter (logger)] %s,%s\n", req.Request.Method, req.Request.URL)
chain.ProcessFilter(req, resp)
}
func main() {
// install a global (=DefaultContainer) filter (processed before any webservice in the DefaultContainer)
restful.Filter(globalLogging)
restful.Add(NewUserService())
log.Print("start listening on localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func NewUserService() *restful.WebService {
ws := new(restful.WebService)
ws.
Path("/users").
Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML)
// install a webservice filter (processed before any route)
ws.Filter(webserviceLogging).Filter(measureTime)
// install a counter filter
ws.Route(ws.GET("").Filter(NewCountFilter().routeCounter).To(getAllUsers))
// install 2 chained route filters (processed before calling findUser)
ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser))
return ws
}