Skip to content
New issue

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

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

Already on GitHub? # 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)
}
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant