聊聊dubbo-go-proxy的DiscoveryService

本文主要研究一下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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章