sequence

This paper focuses on DiscoveryService of dubo-go-proxy

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)
}
Copy the code

Go defines four DiscoveryService interfaces. They are APIDiscoveryService, ListenerDiscoveryService, RouteDiscoveryService, ClusterDiscoveryService, and 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, } }Copy the code

DiscoveryRequest defines the Body property

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{}
Copy the code

DiscoveryResponse defines the Success and Data attributes

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")
}
Copy the code

LocalMemoryAPIDiscoveryService defines the router attribute; It implements AddAPI and GetAPI methods of APIDiscoveryService, both of which are delegated to the 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)
}
Copy the code

InitAPIsFromConfig loads the plugin’s corresponding filter method according to config.APIConfig configuration

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 }Copy the code

LoadAPIFromResource is used to load the API for the specified resources, which borroves 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 }Copy the code

LoadAPIFromMethods Iterate over methods to create fr.API and execute localsrv.addAPI (API)

summary

Go defines four DiscoveryService interfaces. APIDiscoveryService, ListenerDiscoveryService, RouteDiscoveryService, ClusterDiscoveryService, and EndpointDiscoveryService respectively. LocalMemoryAPIDiscoveryService defines the router attribute; It implements AddAPI and GetAPI methods of APIDiscoveryService, both of which are delegated to the Router.

doc

  • dubbo-go-proxy