Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

route plugin support #53

Open
zonghaishang opened this issue Feb 23, 2023 · 0 comments
Open

route plugin support #53

zonghaishang opened this issue Feb 23, 2023 · 0 comments

Comments

@zonghaishang
Copy link
Contributor

zonghaishang commented Feb 23, 2023

背景

路由、负载均衡等都属于扩展SPI,目前客户的路由策略都是写死在mosn中,通过将路由能力抽象成插件的机制,允许根据不同的场景去做灵活的定制。

写死在mosn中有一些弊端:

  • 需要单独维护定制的分支,并且需要重新build mosn,客户增长,代码膨胀不利维护
  • 客户自定义策略,需要原厂研发去编写

什么是路由?

通俗来讲,就是根据一定算法,去筛选目标地址集合得到期望目标地址子集。路由插件化要做的事情:
将编写筛选的算法 开放出去,让客户自行决策,给定目标地址集合,返回目标地址子集。

收益:

  1. 完善Sofa Mesh插件扩展产品矩阵,丰富扩展场景
  2. 支持灵活路由策略,配合智能代码生成,增加产品差异化竞争能力

目标

  • 支持路由plugin级别扩展
  • 支持路由动态配置推送: 动态路由
  • 支持router chain机制

思路
开源侧提供route api, 商业版提供插件装载,形成产品能力,实现灵活扩展

方案设计

开源侧Route SPI ( 放到extensions,api无异议,商业版做完验证,提交pr

package router

import (
	"context"
	"mosn.io/api"
)

// RouteFactory create router handler for filter hosts
type RouteFactory interface {
	// Name router factory name
	// Route factory will be registered as unique component
	Name() string

	// Order parameter is used to sort multiple route plugins.
	// The default value is 0. The smaller the value, the earlier the route plugin is executed.
	Order() int

	// Configurator Dynamic route configuration push is supported
	Configurator() Configurator

	// CreateRouter create route handler with config
	// Configurator returns the latest route configuration for conf
	CreateRouter(ctx context.Context, conf map[string]interface{}) Handler
}

// Handler host list filter handler
type Handler interface {
	// Route filtering by request and invokers address list returns the final list of available services
	// meta: All hosts must contain the same tag, if any
	Route(ctx context.Context, request api.HeaderMap, invokers []api.HostInfo) (meta api.Metadata, hosts []api.HostInfo)
}

// Configurator Route configuration dynamic push feature
type Configurator interface {
	// Configure Transform dynamic configuration into programmable objects
	// The transformed object is passed to the RouterFactory CreateRouter
	// When dynamic configuration is pushed, Configure will be invoked.
	Configure(factory string, config string)

	// Configuration This is the route configuration after the latest conversion
	Configuration() map[string]interface{}
}

------ 以下在商业版mosn中实现, 开源无需关注-----

商业版脚手架支持

yiji@yiji-2 build % tree
.
├── codecs
│   ├── bolt
│   │   ├── codec-bolt-fa3442c8.so
│   │   ├── codec-bolt.md5
│   │   ├── egress_bolt.json
│   │   ├── ingress_bolt.json
│   │   └── metadata.json
│   └── bundle			
│       └── support     
│           └── routers	  // 会在插件包包含激活的 路由插件so和配置
├── image
│   └── Dockerfile
└── sidecar
    └── binary
        ├── mosn
        └── mosn-1.26.0-fdc2aa702.md5

商业版mosn route适配

  • mosn启动会装载包含路由插件的大包,启动期间注册RouteFactory
  • mosn去对接动态配置中心,收到动态推送 会查找RouteFactory 触发 Configurator配置解析,当下一次请求能够感知到最新的路由配置

因为mosn框架要实现路由必须满足RouteHandler接口,但是ClusterManager、ClusterSnapshot、HandlerStatus 开源api、pkg迁不出去:

type RouteHandler interface {
	// IsAvailable returns HandlerStatus represents the handler will be used/not used/stop next handler check
	IsAvailable(context.Context, ClusterManager) (ClusterSnapshot, HandlerStatus)
	// Route returns handler's route
	Route() api.Route
}

目前商业版是通过CloudRouteHandlerCreator去生成RouteHandler:

type CloudRouteHandlerCreator interface {
	RouterSpec
	CreateRouterHandler(ctx context.Context, headers types.HeaderMap, routers types.Routers) types.RouteHandler
}

因此需要针对插件的RouteFactory创建对应的factory.name -> CloudRouteHandlerCreator:

// 支持插件路由handler包装
// 负责解析路由动态配置,并且在实例化RouteHandler进行配置传递
type ConfiguratorRouteHandler interface {
    CloudRouteHandlerCreator

    // 返回关联的plugin factory
    // CloudRouteHandlerCreator返回的RouteHandler 会调用 RouteFactory创建的plugin handler
    RouteFactory() RouteFactory
}

// 实现RouteHandler接口,负责调用RouteFactory的plugin handler
type RouteHandlerAdaptor struct {
    
    conf map[string]interface{} // dynamic conf

    pluginHandler router.Handler // user extension router spi
    
    routers types.Routers		// routers
    headers types.HeaderMap		// request

    route    api.Route				// match header key-value route
    snapshot types.ClusterSnapshot	// cluster snapshot
}

func (r *RouteHandlerAdaptor) IsAvailable(ctx context.Context, manager types.ClusterManager) (types.ClusterSnapshot, types.HandlerStatus) {
	// invoke plugin route here...
    r.pluginHandler.Route(ctx context.Context, request api.HeaderMap, invokers []api.HostInfo)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant