聊聊dubbo-go-proxy的Route

本文深入解析了dubbo-go-proxy的Route结构及其操作,包括NewRoute、PutAPI、UpdateAPI和FindAPI方法。Route维护了一个AVL树用于存储API,同时处理通配符路径。PutAPI用于添加API,UpdateAPI更新已有API,FindAPI则用于查找匹配的API。所有操作都确保了线程安全。
摘要由CSDN通过智能技术生成

本文主要研究一下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§来获取node

小结

Route定义了lock、tree、wildcardTree属性,其NewRoute方法用于创建Route;它提供了PutAPI、UpdateAPI、FindAPI等方法;里头实现使用的是avltree.Tree。

doc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值