kubernetesソースコード解析----apiserverルーティング解析(1)
7569 ワード
kubernetesソースコード解析----apiserverルーティング解析(1)
apiserverはk 8 sクラスタの唯一のエントリとして、内部には主に2つの機能が実現されている.1つは要求のルーティングと処理であり、簡単に言えば1つのポートを傍受し、受信した要求を適切に対応する処理ロジックに転送し、もう1つの機能は認証と権限制御である.本文は主にapiserverのルーティング構築過程を解析する.apiserverはgo-restfulを使用してREST-style Webサービスを構築しているので、まずapiserverのソースコードをよりよく理解するために、このパッケージに関する内容を理解してみましょう.
(kubernetesコードバージョン:1.3.6 Commit id:ed 3 a 29 bd 6 aeb)
go-restful
Package restful, a lean package for creating REST-style WebServices without magic.
go-restfulはREST-style Webサービスを構築するためのgolangパッケージで、その由来はgo-restful-api-designを参照して、大体javaerがgolangの中でついでのREST-basedサービス構築パッケージを見つけていないことを意味しているので、Javaでよく使われるJAX-RSの設計に従ってgolangの中で車輪を作った.
go-restfulの中のいくつかのコンポーネントと特性 Routeルーティングは、標準JSR 311インタフェース仕様の実装RouterJSR 311と、高速ルーティングCurlyRouterの2つを含む.CurlyRouterは正規表現と動的パラメータをサポートし、RouterJSR 311よりも軽量級であり、apiserverではこのルーティングが使用されている.1つのRouteの設定には、要求メソッド(Http Method)、要求パス(URL Path)、処理メソッド、およびオプションの受信コンテンツタイプ(Content-Type)、応答コンテンツタイプ(Accept)などが含まれる. WebService WebServiceは論理的にRouteの集合であり、機能的には主にRouteのセットにroot path、リクエスト応答のデータ型など、いくつかの共通の属性を統一的に設定する.WebServiceが有効になるにはContainerに加入する必要があります. Container Containerは論理的にWebServiceの集合であり,機能的にマルチ端末の効果を実現できる.たとえば、次のコードでは2つのContainerが作成され、それぞれ異なるport上でサービスが提供されます. Filter Filterは、動的なブロッキング要求および応答のために使用され、対応するコンポーネントの前に配置されたフックと同様に、対応するコンポーネント機能の実行前に要求または応答をキャプチャし、主にlogの記録、検証、リダイレクトなどの機能に使用される.go-restfulには3種類のFilterがあります. Container Filterは、Container内のすべてのWebServiceが実行される前に実行されます. WebService Filterは、WebService内のすべてのRouteが実行される前に実行されます. Route Filterは、Routeバインディングのメソッドを呼び出す前に実行されます.
使用例
次のコードは、公式に提供された例です.
上記の例ではRestfulサービスを構築し、いくつかのステップに分けてapiserverでも同様です. Containerを作成します. カスタムResource Handleを作成し、Resource関連の処理方法を実装します. Resourceに対応するWebServiceを作成し、WebServiceに対応するRouteを追加し、ContainerにWebServiceを追加します. リスニングサービスを開始します.
転載先:https://www.cnblogs.com/ldaniel/p/5868384.html
apiserverはk 8 sクラスタの唯一のエントリとして、内部には主に2つの機能が実現されている.1つは要求のルーティングと処理であり、簡単に言えば1つのポートを傍受し、受信した要求を適切に対応する処理ロジックに転送し、もう1つの機能は認証と権限制御である.本文は主にapiserverのルーティング構築過程を解析する.apiserverはgo-restfulを使用してREST-style Webサービスを構築しているので、まずapiserverのソースコードをよりよく理解するために、このパッケージに関する内容を理解してみましょう.
(kubernetesコードバージョン:1.3.6 Commit id:ed 3 a 29 bd 6 aeb)
go-restful
Package restful, a lean package for creating REST-style WebServices without magic.
go-restfulはREST-style Webサービスを構築するためのgolangパッケージで、その由来はgo-restful-api-designを参照して、大体javaerがgolangの中でついでのREST-basedサービス構築パッケージを見つけていないことを意味しているので、Javaでよく使われるJAX-RSの設計に従ってgolangの中で車輪を作った.
go-restfulの中のいくつかのコンポーネントと特性
func InstallVersionHandler(mux Mux, container *restful.Container) {
// Set up a service to return the git code version.
versionWS := new(restful.WebService)
versionWS.Path("/version")
versionWS.Doc("git code version from which this is built")
versionWS.Route(
versionWS.GET("/").To(handleVersion).
Doc("get the code version").
Operation("getCodeVersion").
Produces(restful.MIME_JSON).
Consumes(restful.MIME_JSON).
Writes(version.Info{}))
container.Add(versionWS)
}
func main() {
ws := new(restful.WebService)
ws.Route(ws.GET("/hello").To(hello))
// ws container restful.DefaultContainer
restful.Add(ws)
go func() {
// restful.DefaultContainer 8080
http.ListenAndServe(":8080", nil)
}()
container2 := restful.NewContainer()
ws2 := new(restful.WebService)
ws2.Route(ws2.GET("/hello").To(hello2))
// ws2 container container2
container2.Add(ws2)
// container2 8081
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")
}
// install a (global) filter for the default container (processed before any webservice)
restful.Filter(globalLogging)
// install a webservice filter (processed before any route)
ws.Filter(webserviceLogging).Filter(measureTime)
// install 2 chained route filters (processed before calling findUser)
ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser))
使用例
次のコードは、公式に提供された例です.
package main
import (
"github.com/emicklei/go-restful"
"log"
"net/http"
)
type User struct {
Id, Name string
}
type UserResource struct {
// normally one would use DAO (data access object)
users map[string]User
}
func (u UserResource) Register(container *restful.Container) {
// WebService
ws := new(restful.WebService)
// WebService ("/users") MIME (restful.MIME_XML/ restful.MIME_JSON)
ws.
Path("/users").
Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well
// : GET /{user-id} --> u.findUser
ws.Route(ws.GET("/{user-id}").To(u.findUser))
// : POST / --> u.updateUser
ws.Route(ws.POST("").To(u.updateUser))
// : PUT /{user-id} --> u.createUser
ws.Route(ws.PUT("/{user-id}").To(u.createUser))
// : DELETE /{user-id} --> u.removeUser
ws.Route(ws.DELETE("/{user-id}").To(u.removeUser))
// WebService Container
container.Add(ws)
}
// GET http://localhost:8080/users/1
//
func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
id := request.PathParameter("user-id")
usr := u.users[id]
if len(usr.Id) == 0 {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusNotFound, "User could not be found.")
} else {
response.WriteEntity(usr)
}
}
// POST http://localhost:8080/users
// 1 Melissa Raspberry
//
func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) {
usr := new(User)
err := request.ReadEntity(&usr)
if err == nil {
u.users[usr.Id] = *usr
response.WriteEntity(usr)
} else {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusInternalServerError, err.Error())
}
}
// PUT http://localhost:8080/users/1
// 1 Melissa
//
func (u *UserResource) createUser(request *restful.Request, response *restful.Response) {
usr := User{Id: request.PathParameter("user-id")}
err := request.ReadEntity(&usr)
if err == nil {
u.users[usr.Id] = usr
response.WriteHeader(http.StatusCreated)
response.WriteEntity(usr)
} else {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusInternalServerError, err.Error())
}
}
// DELETE http://localhost:8080/users/1
//
func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) {
id := request.PathParameter("user-id")
delete(u.users, id)
}
func main() {
// Container
wsContainer := restful.NewContainer()
// CurlyRouter
wsContainer.Router(restful.CurlyRouter{})
// Resource Handle( UserResource)
u := UserResource{map[string]User{}}
// WebService, WebService Container
u.Register(wsContainer)
log.Printf("start listening on localhost:8080")
server := &http.Server{Addr: ":8080", Handler: wsContainer}
//
log.Fatal(server.ListenAndServe())
}
上記の例ではRestfulサービスを構築し、いくつかのステップに分けてapiserverでも同様です.
転載先:https://www.cnblogs.com/ldaniel/p/5868384.html