Polaris系列-04.启动分析三

接上篇继续,从第117行开始分析:
在这里插入图片描述
进入StartBootstrapInOrder(s, cfg),先贴出整个方法的代码:
在这里插入图片描述
在这里插入图片描述
开始分析:
在这里插入图片描述
再次查看下启动配置文件内容:这2配置作者也说了,是为了不让db崩掉…
在这里插入图片描述
进入下面代码:
在这里插入图片描述
如果是boltdb:

// CreateTransaction create store transaction
func (m *boltStore) CreateTransaction() (store.Transaction, error) {
	return &transaction{handler: m.handler}, nil
}
type transaction struct {
	handler BoltHandler
}

如果是mysql: 创建开启事务…
在这里插入图片描述
这里我们只分析boltdb.
进入428行:
在这里插入图片描述
在这里插入图片描述
至此StartBootstrapInOrder(s, cfg)介绍完毕,对boltdb来说,似乎…只创建了一个transaction对象…

开始进入第123行 StartComponents(ctx, cfg)中:
在这里插入图片描述
先贴出整个方法代码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
开始分析:
在这里插入图片描述

// Initialize 初始化
func Initialize(ctx context.Context, cacheOpt *Config, storage store.Store) error {
	var err error
	once.Do(func() {
		// 进入这看看:
		err = initialize(ctx, cacheOpt, storage)
	})
	if err != nil {
		return err
	}
	finishInit = true
	return nil
}
// initialize cache 初始化
func initialize(ctx context.Context, cacheOpt *Config, storage store.Store) error {
	var err error
	cacheMgn, err = newCacheManager(ctx, cacheOpt, storage)
	return err
}

整个newCacheManager(ctx, cacheOpt, storage) 代码如下:
在这里插入图片描述
初始化CacheManager, 它管理着16个配置项(通过数组切片管理)
在这里插入图片描述
在这里插入图片描述
CacheManager管理着这些配置项,下面就看这些配置项如何注册(被管理)上的:
在这里插入图片描述
先看mgr.RegisterCacher方法:
一个萝卜一个坑:每个配置项占位一个数组下标

func (nc *CacheManager) RegisterCacher(cacheType types.CacheIndex, item types.Cache) {
	nc.caches[cacheType] = item
}

下面说缓存模块初始化,因为模块比较多,我们挑几个来看看:

1.第92行:cachens.NewNamespaceCache(storage, mgr)

func NewNamespaceCache(storage store.Store, cacheMgr types.CacheManager) types.NamespaceCache {
	return &namespaceCache{
		BaseCache: types.NewBaseCache(storage, cacheMgr), // 看这里
		storage:   storage,
	}
}

type namespaceCache struct {
	*types.BaseCache // 基类
	storage store.Store // 持有存储的引用
	ids     *utils.SyncMap[string, *model.Namespace]
	updater *singleflight.Group // 达到串行化操作目的
	// exportNamespace 某个命名空间下的所有服务的可见性
	exportNamespace *utils.SyncMap[string, *utils.SyncSet[string]]
}

namespace模块从字段数量来看,算比较少的,我们需要关注里面几个点:

  1. 几乎每个模块都持有store.Store的引用
  2. 每个模块都持有缓存管理器CacheManager的引用
  3. 里面有很多*utils.SyncMap[...]使用(读写锁 + 普通map)
  4. 它们都有一个基类:types.BaseCache

我们看看 基类:types.BaseCache

func NewBaseCache(s store.Store, cacheMgr CacheManager) *BaseCache {
	c := &BaseCache{
		s:        s,
		CacheMgr: cacheMgr,
	}
	c.initialize() // 我们看看如何初始化
	return c
}

// BaseCache 对于 Cache 中的一些 func 做统一实现,避免重复逻辑
type BaseCache struct {
	lock sync.RWMutex // 操作保护锁
	// firstUpdate Whether the cache is loaded for the first time
	// this field can only make value on exec initialize/clean, and set it to false on exec update
	firstUpdate           bool
	s                     store.Store // boltdb存储dao引用
	lastFetchTime         int64
	lastMtimes            map[string]time.Time
	CacheMgr              CacheManager // 缓存管理器
	reportMetrics         func() // prometheus度量/logger/其它统计 相关
	lastReportMetricsTime time.Time
}
// 只是初始化几个字段
func (bc *BaseCache) initialize() {
	bc.lock.Lock()
	defer bc.lock.Unlock()

	bc.lastFetchTime = 1
	bc.firstUpdate = true
	bc.lastMtimes = map[string]time.Time{}
}

2.第94行:cachesvc.NewServiceCache(storage, mgr)

// NewServiceCache 返回一个serviceCache
func NewServiceCache(storage store.Store, cacheMgr types.CacheManager) types.ServiceCache {
	return &serviceCache{
		BaseCache:   types.NewBaseCache(storage, cacheMgr),
		storage:     storage,
		alias:       newServiceAliasBucket(), // 看这里
		serviceList: newServiceNamespaceBucket(), // 看这里
	}
}

func newServiceAliasBucket() *serviceAliasBucket {
	return &serviceAliasBucket{
		alias: make(map[string]map[string]map[string]*model.Service),
	}
}
type serviceAliasBucket struct {
	lock sync.RWMutex
	// aliase namespace->service->alias_id
	alias map[string]map[string]map[string]*model.Service
}

func newServiceNamespaceBucket() *serviceNamespaceBucket {
	return &serviceNamespaceBucket{
		names: map[string]*serviceNameBucket{},
	}
}
type serviceNamespaceBucket struct {
	lock     sync.RWMutex
	revision string
	names    map[string]*serviceNameBucket
}

因为serviceCache属性字段比较多,先不一一介绍,先关注代码中显式初始化的字段,从上面代码可以看到 别名的组织方式:
// aliase namespace->service->alias_id
一个命名空间下的服务:
names map[string]*serviceNameBucket

3.第104行:cacheconfig.NewConfigFileCache(storage, mgr)

// NewConfigFileCache 创建文件缓存
func NewConfigFileCache(storage store.Store, cacheMgr types.CacheManager) types.ConfigFileCache {
	fc := &fileCache{
		storage:   storage,
	}
	// 新的一种初始化形式
	fc.BaseCache = types.NewBaseCacheWithRepoerMetrics(storage, cacheMgr, fc.reportMetricsInfo)
	return fc
}

func NewBaseCacheWithRepoerMetrics(s store.Store, cacheMgr CacheManager, reportMetrics func()) *BaseCache {
	c := &BaseCache{
		s:             s,
		CacheMgr:      cacheMgr,
		reportMetrics: reportMetrics, // 多了度量方法
	}

	c.initialize()
	return c
}

4.最后举例,再看第110行:cacheclient.NewClientCache(storage, mgr)北极星SDK Client

// NewClientCache 新建一个clientCache
func NewClientCache(storage store.Store, cacheMgr types.CacheManager) types.ClientCache {
	return &clientCache{
		BaseCache: types.NewBaseCache(storage, cacheMgr),
		storage:   storage,
		clients:   map[string]*model.Client{},
	}
}
// clientCache 客户端缓存的类
type clientCache struct {
	*types.BaseCache

	storage         store.Store
	lastMtimeLogged int64
	clients         map[string]*model.Client // instance id -> instance
	lock            sync.RWMutex
	singleFlight    *singleflight.Group
	lastUpdateTime  time.Time
}
// Client 客户端上报信息表
type Client struct {
	proto      *apiservice.Client
	valid      bool
	modifyTime time.Time
}
type Client struct {
	Host                 *wrapperspb.StringValue `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"`
	Type                 Client_ClientType       `protobuf:"varint,2,opt,name=type,proto3,enum=v1.Client_ClientType" json:"type,omitempty"`
	Version              *wrapperspb.StringValue `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
	Location             *model.Location         `protobuf:"bytes,4,opt,name=location,proto3" json:"location,omitempty"`
	Id                   *wrapperspb.StringValue `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"`
	Stat                 []*StatInfo             `protobuf:"bytes,6,rep,name=stat,proto3" json:"stat,omitempty"`
	Ctime                *wrapperspb.StringValue `protobuf:"bytes,7,opt,name=ctime,proto3" json:"ctime,omitempty"`
	Mtime                *wrapperspb.StringValue `protobuf:"bytes,8,opt,name=mtime,proto3" json:"mtime,omitempty"`
	XXX_NoUnkeyedLiteral struct{}                `json:"-"`
	XXX_unrecognized     []byte                  `json:"-"`
	XXX_sizecache        int32                   `json:"-"`
}

client 和 server端通过grpc协议交互,protobuf序列化传输,实锤了。

最后注册上的灰色发布:

type grayCache struct {
	*types.BaseCache
	storage       store.Store
	grayResources *utils.SyncMap[string, []*apimodel.ClientLabel]
	updater       *singleflight.Group
}
type ClientLabel struct {
	Key                  string       `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
	Value                *MatchString `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
	XXX_unrecognized     []byte       `json:"-"`
	XXX_sizecache        int32        `json:"-"`
}

也证实了确实是通过标签Label去实现的。

注册上了16个缓存模块后,最后是cacheManager的初始化:
在这里插入图片描述

// Initialize 缓存对象初始化
func (nc *CacheManager) Initialize() error {
	if config.DiffTime != 0 {
		types.DefaultTimeDiff = -1 * (config.DiffTime.Abs())
	}
	if types.DefaultTimeDiff > 0 {
		return fmt.Errorf("cache diff time to pull store must negative number: %+v", types.DefaultTimeDiff)
	}
	return nil
}

时间单位是:纳秒
在这里插入图片描述
这个值是我们配置的,不配置的默认值也是 5s (-5s), 取绝对值就没区别了:
在这里插入图片描述
至此,缓存初始化完毕。我们代码往下到了:
在这里插入图片描述
func StartComponents(ctx context.Context, cfg *boot_config.Config) error 方法比较复杂,还没完,下篇继续…

总结,本篇 缓存初始化 介绍了:

  1. 创建缓存管理器cacheManager
  2. cacheManager注册了16个缓存配置项并初始化
  3. cachemanager初始化

相关推荐

  1. 【QEMU系统分析启动篇(九)】

    2024-07-18 11:58:04       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 11:58:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 11:58:04       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 11:58:04       58 阅读
  4. Python语言-面向对象

    2024-07-18 11:58:04       69 阅读

热门阅读

  1. python logging 避免日志重复打印

    2024-07-18 11:58:04       21 阅读
  2. 23、nc文件快速切片与索引

    2024-07-18 11:58:04       23 阅读
  3. 【Nginx】控制允许可上传的文件大小

    2024-07-18 11:58:04       19 阅读
  4. Docker 容器中的 Docker Compose 简介

    2024-07-18 11:58:04       23 阅读
  5. Spring boot 2.0 升级到 3.3.1 的相关问题 (三)

    2024-07-18 11:58:04       23 阅读
  6. NLP篇10 NLP总结

    2024-07-18 11:58:04       19 阅读
  7. 自然语言处理NLP--文本相似度面试题

    2024-07-18 11:58:04       17 阅读
  8. vue中获取剪切板中的内容

    2024-07-18 11:58:04       23 阅读
  9. 面向过程编程和面向对象编程

    2024-07-18 11:58:04       19 阅读