本文次要钻研一下dubbo-go-proxy的DiscoveryService

DiscoveryService

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

// APIDiscoveryService api discovery service interfacetype APIDiscoveryService interface {    AddAPI(router.API) error    GetAPI(string, config.HTTPVerb) (router.API, error)}// DiscoveryService is come from envoy, it can used for admin// ListenerDiscoveryServicetype ListenerDiscoveryService interface {    AddListeners(request DiscoveryRequest) (DiscoveryResponse, error)    GetListeners(request DiscoveryRequest) (DiscoveryResponse, error)}// RouteDiscoveryServicetype RouteDiscoveryService interface {    AddRoutes(r DiscoveryRequest) (DiscoveryResponse, error)    GetRoutes(r DiscoveryRequest) (DiscoveryResponse, error)}// ClusterDiscoveryServicetype ClusterDiscoveryService interface {    AddClusters(r DiscoveryRequest) (DiscoveryResponse, error)    GetClusters(r DiscoveryRequest) (DiscoveryResponse, error)}// EndpointDiscoveryServicetype 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 discoverytype DiscoveryRequest struct {    Body []byte}// NewDiscoveryRequest return a DiscoveryRequest with bodyfunc NewDiscoveryRequest(b []byte) *DiscoveryRequest {    return &DiscoveryRequest{        Body: b,    }}
DiscoveryRequest定义了Body属性

DiscoveryResponse

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

// DiscoveryResponse a response for discoverytype DiscoveryResponse struct {    Success bool    Data    interface{}}// NewDiscoveryResponseWithSuccess return a DiscoveryResponse with successfunc NewDiscoveryResponseWithSuccess(b bool) *DiscoveryResponse {    return &DiscoveryResponse{        Success: b,    }}// NewDiscoveryResponse return a DiscoveryResponse with Data and success truefunc 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 servicetype LocalMemoryAPIDiscoveryService struct {    router *router.Route}// NewLocalMemoryAPIDiscoveryService creates a new LocalMemoryApiDiscoveryService instancefunc NewLocalMemoryAPIDiscoveryService() *LocalMemoryAPIDiscoveryService {    return &LocalMemoryAPIDiscoveryService{        router: router.NewRoute(),    }}// AddAPI adds a method to the router treefunc (ads *LocalMemoryAPIDiscoveryService) AddAPI(api fr.API) error {    return ads.router.PutAPI(api)}// GetAPI returns the method to the callerfunc (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 cachefunc 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

  • dubbo-go-proxy