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

DiscoveryService

dubbo-go-proxy/pkg/service/discovery_service.go

// APIDiscoveryService api discovery service interface
type APIDiscoveryService interface {
    AddAPI(router.API) error
    GetAPI(string, config.HTTPVerb) (router.API, error)
}

// DiscoveryService is come from envoy, it can used for admin

// ListenerDiscoveryService
type ListenerDiscoveryService interface {
    AddListeners(request DiscoveryRequest) (DiscoveryResponse, error)
    GetListeners(request DiscoveryRequest) (DiscoveryResponse, error)
}

// RouteDiscoveryService
type RouteDiscoveryService interface {
    AddRoutes(r DiscoveryRequest) (DiscoveryResponse, error)
    GetRoutes(r DiscoveryRequest) (DiscoveryResponse, error)
}

// ClusterDiscoveryService
type ClusterDiscoveryService interface {
    AddClusters(r DiscoveryRequest) (DiscoveryResponse, error)
    GetClusters(r DiscoveryRequest) (DiscoveryResponse, error)
}

// EndpointDiscoveryService
type EndpointDiscoveryService interface {
    AddEndpoints(r DiscoveryRequest) (DiscoveryResponse, error)
    GetEndpoints(r DiscoveryRequest) (DiscoveryResponse, error)
}
discovery_service.go定义了四种DiscoveryService接口,分别是APIDiscoveryService、ListenerDiscoveryService、RouteDiscoveryService、ClusterDiscoveryService、EndpointDiscoveryService

DiscoveryRequest

dubbo-go-proxy/pkg/service/discovery_service.go

// DiscoveryRequest a request for discovery
type DiscoveryRequest struct {
    Body []byte
}

// NewDiscoveryRequest return a DiscoveryRequest with body
func NewDiscoveryRequest(b []byte) *DiscoveryRequest {
    return &DiscoveryRequest{
        Body: b,
    }
}
DiscoveryRequest定义了Body属性

DiscoveryResponse

dubbo-go-proxy/pkg/service/discovery_service.go

// DiscoveryResponse a response for discovery
type DiscoveryResponse struct {
    Success bool
    Data    interface{}
}

// NewDiscoveryResponseWithSuccess return a DiscoveryResponse with success
func NewDiscoveryResponseWithSuccess(b bool) *DiscoveryResponse {
    return &DiscoveryResponse{
        Success: b,
    }
}

// NewDiscoveryResponse return a DiscoveryResponse with Data and success true
func NewDiscoveryResponse(d interface{}) *DiscoveryResponse {
    return &DiscoveryResponse{
        Success: true,
        Data:    d,
    }
}

var EmptyDiscoveryResponse = &DiscoveryResponse{}
DiscoveryResponse定义了Success及Data属性

LocalMemoryAPIDiscoveryService

dubbo-go-proxy/pkg/service/api/discovery_service.go

// Init set api discovery local_memory service.
func Init() {
    extension.SetAPIDiscoveryService(constant.LocalMemoryApiDiscoveryService, NewLocalMemoryAPIDiscoveryService())
}

// LocalMemoryAPIDiscoveryService is the local cached API discovery service
type LocalMemoryAPIDiscoveryService struct {
    router *router.Route
}

// NewLocalMemoryAPIDiscoveryService creates a new LocalMemoryApiDiscoveryService instance
func NewLocalMemoryAPIDiscoveryService() *LocalMemoryAPIDiscoveryService {
    return &LocalMemoryAPIDiscoveryService{
        router: router.NewRoute(),
    }
}

// AddAPI adds a method to the router tree
func (ads *LocalMemoryAPIDiscoveryService) AddAPI(api fr.API) error {
    return ads.router.PutAPI(api)
}

// GetAPI returns the method to the caller
func (ads *LocalMemoryAPIDiscoveryService) GetAPI(url string, httpVerb config.HTTPVerb) (fr.API, error) {
    if api, ok := ads.router.FindAPI(url, httpVerb); ok {
        return *api, nil
    }

    return fr.API{}, errors.New("not found")
}
LocalMemoryAPIDiscoveryService定义了router属性;它实现了APIDiscoveryService的AddAPI及GetAPI方法,均是代理给了router

InitAPIsFromConfig

dubbo-go-proxy/pkg/service/api/discovery_service.go

// InitAPIsFromConfig inits the router from API config and to local cache
func InitAPIsFromConfig(apiConfig config.APIConfig) error {
    localAPIDiscSrv := extension.GetMustAPIDiscoveryService(constant.LocalMemoryApiDiscoveryService)
    if len(apiConfig.Resources) == 0 {
        return nil
    }
    // load pluginsGroup
    plugins.InitPluginsGroup(apiConfig.PluginsGroup, apiConfig.PluginFilePath)
    // init plugins from resource
    plugins.InitAPIURLWithFilterChain(apiConfig.Resources)
    return loadAPIFromResource("", apiConfig.Resources, nil, localAPIDiscSrv)
}
InitAPIsFromConfig根据config.APIConfig的配置来加载plugin对应的filter方法

loadAPIFromResource

dubbo-go-proxy/pkg/service/api/discovery_service.go

func loadAPIFromResource(parrentPath string, resources []config.Resource, parentHeaders map[string]string, localSrv service.APIDiscoveryService) error {
    errStack := []string{}
    if len(resources) == 0 {
        return nil
    }
    groupPath := parrentPath
    if parrentPath == constant.PathSlash {
        groupPath = ""
    }
    fullHeaders := parentHeaders
    if fullHeaders == nil {
        fullHeaders = make(map[string]string, 9)
    }
    for _, resource := range resources {
        fullPath := groupPath + resource.Path
        if !strings.HasPrefix(resource.Path, constant.PathSlash) {
            errStack = append(errStack, fmt.Sprintf("Path %s in %s doesn't start with /", resource.Path, parrentPath))
            continue
        }
        for headerName, headerValue := range resource.Headers {
            fullHeaders[headerName] = headerValue
        }
        if len(resource.Resources) > 0 {
            if err := loadAPIFromResource(resource.Path, resource.Resources, fullHeaders, localSrv); err != nil {
                errStack = append(errStack, err.Error())
            }
        }

        if err := loadAPIFromMethods(fullPath, resource.Methods, fullHeaders, localSrv); err != nil {
            errStack = append(errStack, err.Error())
        }
    }
    if len(errStack) > 0 {
        return errors.New(strings.Join(errStack, "; "))
    }
    return nil
}
loadAPIFromResource用于加载指定resources的api,它借用了loadAPIFromMethods

loadAPIFromMethods

dubbo-go-proxy/pkg/service/api/discovery_service.go

func loadAPIFromMethods(fullPath string, methods []config.Method, headers map[string]string, localSrv service.APIDiscoveryService) error {
    errStack := []string{}
    for _, method := range methods {
        api := fr.API{
            URLPattern: fullPath,
            Method:     method,
            Headers:    headers,
        }
        if err := localSrv.AddAPI(api); err != nil {
            errStack = append(errStack, fmt.Sprintf("Path: %s, Method: %s, error: %s", fullPath, method.HTTPVerb, err.Error()))
        }
    }
    if len(errStack) > 0 {
        return errors.New(strings.Join(errStack, "\n"))
    }
    return nil
}
loadAPIFromMethods遍历methods创建fr.API,并执行localSrv.AddAPI(api)

小结

discovery_service.go定义了四种DiscoveryService接口,分别是APIDiscoveryService、ListenerDiscoveryService、RouteDiscoveryService、ClusterDiscoveryService、EndpointDiscoveryService;LocalMemoryAPIDiscoveryService定义了router属性;它实现了APIDiscoveryService的AddAPI及GetAPI方法,均是代理给了router。

doc


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...