序
本文次要钻研一下 dubbo-go-proxy 的 Route
Route
dubbo-go-proxy/pkg/router/route.go
// Route defines the tree of router APIs
type Route struct {
lock sync.RWMutex
tree *avltree.Tree
wildcardTree *avltree.Tree
}
// NewRoute returns an empty router tree
func 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 resource
func (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 node
func (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 the
func (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。
doc
- dubbo-go-proxy