首頁>技術>

本文主要研究一下dubbo-go-proxy的Route

Route

dubbo-go-proxy/pkg/router/route.go

// Route defines the tree of router APIstype Route struct {    lock         sync.RWMutex    tree         *avltree.Tree    wildcardTree *avltree.Tree}// NewRoute returns an empty router treefunc NewRoute() *Route {    return &Route{        tree:         avltree.NewWithStringComparator(),        wildcardTree: avltree.NewWithStringComparator(),    }}

Route定義了lock、tree、wildcardTree屬性,其NewRoute方法用於建立Route

PutAPI

dubbo-go-proxy/pkg/router/route.go

// PutAPI puts an api into the resourcefunc (rt *Route) PutAPI(api router.API) error {    lowerCasePath := strings.ToLower(api.URLPattern)    node, ok := rt.findNode(lowerCasePath)    rt.lock.Lock()    defer rt.lock.Unlock()    if !ok {        wildcard := strings.Contains(lowerCasePath, constant.PathParamIdentifier)        rn := &Node{            fullPath: lowerCasePath,            methods:  map[config.HTTPVerb]*config.Method{api.Method.HTTPVerb: &api.Method},            wildcard: wildcard,            headers:  api.Headers,        }        if wildcard {            rt.wildcardTree.Put(lowerCasePath, rn)        }        rt.tree.Put(lowerCasePath, rn)        return nil    }    return node.putMethod(api.Method, api.Headers)}

PutAPI方法根據lowerCasePath去查詢node,若沒有找到則加鎖建立Node,然後放到tree中,若是path是wildcard的則也會加入到wildcardTree中;如果有找到則執行node.putMethod(api.Method, api.Headers)

UpdateAPI

dubbo-go-proxy/pkg/router/route.go

// UpdateAPI update the api method in the existing router nodefunc (rt *Route) UpdateAPI(api router.API) error {    node, found := rt.findNode(api.URLPattern)    if found {        if _, ok := node.methods[api.Method.HTTPVerb]; ok {            rt.lock.Lock()            defer rt.lock.Unlock()            node.methods[api.Method.HTTPVerb] = &api.Method        }    }    return nil}

UpdateAPI方法先根據api.URLPattern查詢node,若找不到返回nil,找到的話再去找node.methods[api.Method.HTTPVerb],若找到則將api.Method賦值給node.methods[api.Method.HTTPVerb]

FindAPI

dubbo-go-proxy/pkg/router/route.go

// FindAPI returns the api that meets thefunc (rt *Route) FindAPI(fullPath string, httpverb config.HTTPVerb) (*router.API, bool) {    if n, found := rt.findNode(fullPath); found {        rt.lock.RLock()        defer rt.lock.RUnlock()        if method, ok := n.methods[httpverb]; ok {            return &router.API{                URLPattern: n.fullPath,                Method:     *method,                Headers:    n.headers,            }, ok        }    }    return nil, false}

FindAPI方法先透過findNode找node,再透過node.methods[httpverb]找method

findNode

dubbo-go-proxy/pkg/router/route.go

func (rt *Route) findNode(fullPath string) (*Node, bool) {    lowerPath := strings.ToLower(fullPath)    var n interface{}    var found bool    if n, found = rt.searchWildcard(lowerPath); !found {        rt.lock.RLock()        defer rt.lock.RUnlock()        if n, found = rt.tree.Get(lowerPath); !found {            return nil, false        }    }    return n.(*Node), found}

findNode方法透過searchWildcard來查詢node,找不到則從node的tree.Get方法查詢

searchWildcard

dubbo-go-proxy/pkg/router/route.go

func (rt *Route) searchWildcard(fullPath string) (*Node, bool) {    rt.lock.RLock()    defer rt.lock.RUnlock()    wildcardPaths := rt.wildcardTree.Keys()    for _, p := range wildcardPaths {        if wildcardMatch(p.(string), fullPath) != nil {            n, ok := rt.wildcardTree.Get(p)            return n.(*Node), ok        }    }    return nil, false}

searchWildcard方法遍歷wildcardTree.Keys(),挨個執行wildcardMatch,若匹配到則透過wildcardTree.Get(p)來獲取node

小結

Route定義了lock、tree、wildcardTree屬性,其NewRoute方法用於建立Route;它提供了PutAPI、UpdateAPI、FindAPI等方法;裡頭實現使用的是avltree.Tree。

docdubbo-go-proxy

13
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • C#之異常處理