sentinel-java和sentinel-go的设计有何不同

99 阅读2分钟

概述

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

细节

共同点

sentinel的文档总结的很精辟:Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic)和判断部分(rule checking)。

因此,无论用什么语言实现,他们的共同需求和实现思想是:

  1. 责任链模式:对应于slotChain
  2. 资源管理:一种resource对应于一个path
  3. 统计数据部分
  4. rule判断部分

java

在不看源码的情况下,仅从文档可以尝试猜测架构设计

  1. SlotChain
  2. NodeSeletorSlot:构造树形结构,产出路径
  3. Entry:表示一个资源的判断结果

go

从example中可以找到重要结构体:

conf := config.NewDefaultConfig()
// 初始化sentinel的全局Env
err := sentinel.InitWithConfig(conf)
// 修改全局rules
_, err = flow.LoadRules([]*flow.Rule{
		{
			Resource:               resName,
			TokenCalculateStrategy: flow.Direct,
			ControlBehavior:        flow.Reject,
			Threshold:              10,
			StatIntervalInMs:       1000,
		},
	})
e, b := sentinel.Entry(resName, sentinel.WithTrafficType(base.Inbound))
// passed
if b == nil {
    e.Exit()
}
  1. config: 初始化sentinel的配置
  2. flow.Rule:配置限流的参数(每种资源对应一个rule)
  3. resName(string):用户维护的资源的URI
  4. Entry:表示一个资源的判断结果

源码中看不出slotChain的存在,因为创建Entry时,如果用户没有指定slotChain,那么会使用默认slotChain

func Entry(resource string, opts ...EntryOption) (*base.SentinelEntry, *base.BlockError) {
	options := entryOptsPool.Get().(*EntryOptions)
	defer func() {
		options.Reset()
		entryOptsPool.Put(options)
	}()

	for _, opt := range opts {
		opt(options)
	}
	if options.slotChain == nil {
		options.slotChain = GlobalSlotChain()
	}
	return entry(resource, options)
}

func BuildDefaultSlotChain() *base.SlotChain {
	sc := base.NewSlotChain()
	sc.AddStatPrepareSlot(stat.DefaultResourceNodePrepareSlot)

	sc.AddRuleCheckSlot(system.DefaultAdaptiveSlot)
	sc.AddRuleCheckSlot(flow.DefaultSlot)
	sc.AddRuleCheckSlot(isolation.DefaultSlot)
	sc.AddRuleCheckSlot(hotspot.DefaultSlot)
	sc.AddRuleCheckSlot(circuitbreaker.DefaultSlot)

	sc.AddStatSlot(stat.DefaultSlot)
	sc.AddStatSlot(log.DefaultSlot)
	sc.AddStatSlot(flow.DefaultStandaloneStatSlot)
	sc.AddStatSlot(hotspot.DefaultConcurrencyStatSlot)
	sc.AddStatSlot(circuitbreaker.DefaultMetricStatSlot)
	return sc
}

参考

sentinel-java原理 sentinel-go example