当前位置: 首页 > news >正文

公司网站建设怎么南宁做网站在哪了

公司网站建设怎么,南宁做网站在哪了,乐陵市seo关键词优化,企业展厅设计公司图片欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)#xff1a;https://github.com/zq2599/blog_demos 《client-go的Indexer三部曲》全部链接 基本功能性能测试源码阅读 本篇概览 本文是《client-go的Indexer三部曲》系列的终篇#xff0c;主要任务是阅读和…欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)https://github.com/zq2599/blog_demos 《client-go的Indexer三部曲》全部链接 基本功能性能测试源码阅读 本篇概览 本文是《client-go的Indexer三部曲》系列的终篇主要任务是阅读和分析Indexer相关的源码最终目的是深入理解Indexer原理以及在各个典型场景的用法如此一来既抓住了细节又能中整体上理解其存在的目的相信您也会收获满满接口源码位置client-go/tools/cache/index.go实现源码位置client-go/tools/cache/store.go 强烈建议 建议您预先阅读过《client-go的Indexer三部曲之一》此文内用多种pod的分类进行举例今天的源码分析中依旧以此为例来说明唯有如此才能避免读代码时的抽像和索然无味回顾之前的pod分类下面的表格说明了nginx、tomcat、mysql这些pod的两个label的具体值 pod语言类型(language)服务类型(business-service-type)nginxcwebtomcatcwebmysqljavastorage 接口定义 Indexer是个接口咱们先看和它相关的源码第一个要看的是Indexers的定义注意是Indexers不是Indexer其实就是map type Indexers map[string]IndexFunc在《client-go的Indexer三部曲之一》中其实咱们已经用过Indexers了回顾如下图key是个字符串其实就是分类方式的名称例如按照语言分类就用indexer_languagevalue就是分类操作的具体实现下图展示的是取出pod的label值所以不同的label值导致各个pod被分为不同类别c语言类、java类等 有Indexers撑起了完整的业务分类逻辑接下来Indexer就能以此为基础实现各种功能了该接口每个方法的分析分析如下 type Indexer interface {// 存储相关的不在本章讨论Store// indexName表示分类方式obj表示用来查询的对象// 例如indexName等于BY_LANGUAGEobj等于nginx的pod对象// 那么Index方法就会根据BY_LANGUAGE去获取pod对象的语言类型即c语言再返回所有c语言类型的对象// 简而言之就是查找和obj同一个语言类型的所有对象Index(indexName string, obj interface{}) ([]interface{}, error)// indexName表示分类方式indexedValue表示分类的值// 例如indexName等于BY_LANGUAGEindexedValue等于c// 那么IndexKeys方法就会返回所有语言类型等于c的对象的keyIndexKeys(indexName, indexedValue string) ([]string, error)// indexName表示分类方式// 例如indexName等于BY_LANGUAGE// ListIndexFuncValues返回的就是java和cListIndexFuncValues(indexName string) []string// indexName表示分类方式indexedValue表示分类的值// 例如indexName等于BY_LANGUAGEindexedValue等于c// 那么ByIndex方法就会返回所有语言类型等于c的对象ByIndex(indexName, indexedValue string) ([]interface{}, error)// Indexers是个mapkey是分类方式// 本文中key有两个分别是BY_LANGUAGE和BY_SERVICE// value则是个方法// key等于BY_LANGUAGE的时候该方法的入参是个对象pod返回值是这个pod的语言// key等于BY_SERVICE的时候该方法的入参是个对象pod返回值是这个pod的服务类型GetIndexers() Indexers// 添加IndexersAddIndexers(newIndexers Indexers) error } 可见Indexer继承了Store接口这个Store其实就是基础的增删改查所以Indexer既能按照指定分类方式管理也有最基础的增删改查能力 type Store interface {// Add adds the given object to the accumulator associated with the given objects keyAdd(obj interface{}) error// Update updates the given object in the accumulator associated with the given objects keyUpdate(obj interface{}) error// Delete deletes the given object from the accumulator associated with the given objects keyDelete(obj interface{}) error// List returns a list of all the currently non-empty accumulatorsList() []interface{}// ListKeys returns a list of all the keys currently associated with non-empty accumulatorsListKeys() []string// Get returns the accumulator associated with the given objects keyGet(obj interface{}) (item interface{}, exists bool, err error)// GetByKey returns the accumulator associated with the given keyGetByKey(key string) (item interface{}, exists bool, err error)// Replace will delete the contents of the store, using instead the// given list. Store takes ownership of the list, you should not reference// it after calling this function.Replace([]interface{}, string) error// Resync is meaningless in the terms appearing here but has// meaning in some implementations that have non-trivial// additional behavior (e.g., DeltaFIFO).Resync() error }此刻通过接口定义已经了解了Indexer的大致功能接下来可以看看具体实现 接口实现 Indexer的实现是cache这个结构体它的第一个字段容易理解Indexer本质是个缓存功能cacheStorage就是真正保存数据的地方第二个keyFunc就是往Indexers中添加记录的时候为该记录生成对象主键的方法 type cache struct {// cacheStorage bears the burden of thread safety for the cachecacheStorage ThreadSafeStore// keyFunc is used to make the key for objects stored in and retrieved from items, and// should be deterministic.keyFunc KeyFunc }关于对象主键就是这个对象在Indexer中的唯一身份在《client-go的Indexer三部曲之一》中basic/get_obj_keys_by_language_name?languagec这个接口返回的就是所有语言类型是c语言的pod的对象主键接口返回内容如下所示每个主键都是namespace和podName拼接出来的而负责这个拼接逻辑的就是keyFunc稍后咱们会去寻找找这个keyFunc的源码 HTTP/1.1 200 OK Content-Type: application/json; charsetutf-8 Date: Wed, 14 Jun 2023 22:56:37 GMT Content-Length: 219 Connection: close{language: [indexer-tutorials/mysql-556b999fd8-22hqh,indexer-tutorials/nginx-deployment-696cc4bc86-2rqcg,indexer-tutorials/nginx-deployment-696cc4bc86-bkplx,indexer-tutorials/nginx-deployment-696cc4bc86-m7wwh] }来看cache是如何创建的这里有个公共方法可见cache的两个字段都是通过NewIndexer方法的入参来设置的 func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {return cache{cacheStorage: NewThreadSafeStore(indexers, Indices{}),keyFunc: keyFunc,} }上述NewIndexer是在controller.go的NewIndexerInformer方法中被调用的 func NewIndexerInformer(lw ListerWatcher,objType runtime.Object,resyncPeriod time.Duration,h ResourceEventHandler,indexers Indexers, ) (Indexer, Controller) {// This will hold the client state, as we know it.clientState : NewIndexer(DeletionHandlingMetaNamespaceKeyFunc, indexers)return clientState, newInformer(lw, objType, resyncPeriod, h, clientState) }这个NewIndexerInformer方法咱们应该有印象吧《client-go的Indexer三部曲之一》中正是用的这个方法来实例化Informer的如下图 回到NewIndexerInformer看看NewIndexer的两个入参第二个参数indexers咱们已经熟悉了是Indexers类型刚刚已经分析过现在要关注的是第一个参数DeletionHandlingMetaNamespaceKeyFunc如下图黄色箭头所示 上述DeletionHandlingMetaNamespaceKeyFunc对应的是方法MetaNamespaceKeyFunc这就是生成对象key的具体逻辑了用namespace和对象的name拼接而成前面咱们曾调用接口返回的对象key就是这里的代码生成的 func MetaNamespaceKeyFunc(obj interface{}) (string, error) {if key, ok : obj.(ExplicitKey); ok {return string(key), nil}meta, err : meta.Accessor(obj)if err ! nil {return , fmt.Errorf(object has no meta: %v, err)}if len(meta.GetNamespace()) 0 {return meta.GetNamespace() / meta.GetName(), nil}return meta.GetName(), nil }新增对象到缓存的逻辑 接下来看个关键逻辑新增对象到缓存时执行了哪些代码首先还是要从NewInformer方法开始可见Indexer接口的实现对象作为入参被传入了newInformer方法 展开newInformer方法源码和分析如下图所示此刻只剩下感慨了代码写得真好不用层层展开所有重要逻辑一目了然 这里对着上面的图把逻辑捋一下假设咱们用kubectl apply -f xxx.yml命令新增了一个pod此刻client-go就会收到api-server发来的事件类型是pod新增该事件进入先入先出队列fifo然后应该会有段逻辑从队列中取出数据记住这句话稍后要验证的再调用processor依次处理这些从队列中取出来的数据具体的处理逻辑就是上图的4和5d.Object就是新增的对象拿到后调用clientState.Add方法把对象添加到缓存中上面提到一句然后应该会有段逻辑从队列中取出数据是时候找到这段逻辑了回到《client-go的Indexer三部曲之一》中的例子咱们当时初始化Indexer的时候有一段关键代码如下图黄色箭头所示也就是informer.Run方法 展开informer.Run如下图黄色箭头所示关键代码在processLoop方法中看名字就像 展开processLoop方法如下所示这里会不断从队列中取出数据交给c.config.Process处理而这个c.config.Process就是newInformer方法中的Process对象里面是写入Indexer的逻辑 func (c *controller) processLoop() {for {obj, err : c.config.Queue.Pop(PopProcessFunc(c.config.Process))if err ! nil {if err ErrFIFOClosed {return}if c.config.RetryOnError {// This is the safe way to re-enqueue.c.config.Queue.AddIfNotPresent(obj)}}} }至此新增对象时client-go将数据输入存入Indexer的代码已经看过了再进入Indexer实现类的内部看看Store.Add方法具体做了什么 存入缓存的具体逻辑 实现Store接口的Add方法是由Controller来完成的在阅读代码前咱们先结合《client-go的Indexer三部曲之一》中的例子做个分析再去看真实代码来印证这个分析这学习效果比抽象的阅读代码要好很多在前面的例子中咱们在Indexer缓存中对pod做了两种分类按编程语言分类有c和java两种、还有按照服务类型分类有存储和web两种在这种前提下一旦有新资源加入Indexer此时的Indexer应该要做什么操作呢 每个对象都有对象key这是它在Indexer缓存中的唯一身份这个必须要生成提取出这个pod的语言类型和服务类型例如语言类型是java服务类型是web在语言类型分类的映射关系中建立java和此pod的映射关系这样通过按语言分类 java这个组合就能找到这个pod在服务类型分类的映射关系中建立web和此pod的映射关系这样通过按服务类型分类 web这个组合就能找到这个pod维护好语言类型具体有哪些这里应该是c和java维护好服务类型具体有哪些这里应该是存储和web 只有把上述事情都做了Indexer接口定义的那些方法才能正常工作例如IndexKeys方法输入按语言分类和java这两个参数返回的就是所有符合条件的pod的对象key 猜到Indexer在新增对象时要做的事情接下来读代码就非常轻松了代码入口位置如下图所示先算出对象key然后调用方法 再打开上图中的c.cacheStorage.Add方法的源码我滴个乖乖真的好清晰整齐先把旧数据暂存在一个变量中再把新数据放入真正存数据的地方items然后才去更新各种和该数据有关的索引信息这么简洁清晰的代码读起来是享受 展开updateIndices方法一切都是那么顺理成章前面的推测都在此被印证 // updateIndices modifies the objects location in the managed indexes, if this is an update, you must provide an oldObj // updateIndices must be called from a function that already has a lock on the cache func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, key string) {// if we got an old object, we need to remove it before we add it again// 如果有旧数据那么此刻应该也有旧数据的索引信息例如java对应的pod的对象key此处应该清理掉if oldObj ! nil {c.deleteFromIndices(oldObj, key)}// c.indexers就是所有分类方式在本文中就是按语言和按服务类型两种方式分类// 这里用每一种分类方式分别对新增的对象做处理for name, indexFunc : range c.indexers {// indexFunc是我们按照业务需求自己写的例如按照语言分类的时候就是取出pod的language这个label的值indexValues, err : indexFunc(newObj)if err ! nil {panic(fmt.Errorf(unable to calculate an index entry for key %q on index %q: %v, key, name, err))}// c.indices是个mapkey是分类方式例如按语言分类,indexer_language,value是Index对象// Index对象也是个mapkey是该分类下的某个值例如javavalue是个集合所有pod语言类型是java的pod它们的对象key组成了这个集合index : c.indices[name]if index nil {index Index{}c.indices[name] index}// 每一种分类方式都有一个index例如按语言分类有自己的index// 在语言分类的index中每种语言都有一个集合这里面是所有该语言的pod的对象key// 这里的index应该有c和java两个keyc这个key对应的集合里面有nginx和mysql的pod的对象keyjva这个key对应的集合里面有tomcat这个pod的对象key// 下面的代码就是把pod的对象key放入对应的集合中for _, indexValue : range indexValues {set : index[indexValue]if set nil {set sets.String{}index[indexValue] set}set.Insert(key)}} }上述代码清晰的展现了如何通过map和set将pod的对象key进行管理以便查询时可以通过这些map快速查到对应的pod对象中文注释对map和sets都做了详细说明不过Index对象需要再细说一下c.indices是个map这个map的key是分类方式例如按语言分类key就是indexer_language按服务类型分类key就是indexer_business_service_type这都是《client-go的Indexer三部曲之一》中咱们自己写的代码而这个map的value则是Index对象也就是说每种分类方式都有一个Index对象来看看按语言分类时对应的Index对象到底是啥如下图index对象自己也是个map里面的key是所有的语言value是sets集合c语言对应的sets里就是mysql和nginx这些pod的对象key 现在咱们已经看完了新增对象时Indexer的内部逻辑简单的说就是先保存对象再更新Index 缓存的使用 既然已经详细分析了缓存更新的代码那么使用缓存的逻辑也就很明白了无非就是Indexer对象的使用呗咱们挑一个接口的实现代码看看是否如此就看Indexer.IndexKeys方法吧指定分类方式是按语言分类指定语言是java看IndexKeys如何找到tomcat这个pod的对象key 以下是IndexKeys方法的源码可见真实逻辑在c.cacheStorage.IndexKeys func (c *cache) IndexKeys(indexName, indexKey string) ([]string, error) {return c.cacheStorage.IndexKeys(indexName, indexKey) }打开c.cacheStorage.IndexKeys方法如下所示没有任何意外只要找到Index就算成功了 func (c *threadSafeMap) IndexKeys(indexName, indexedValue string) ([]string, error) {c.lock.RLock()defer c.lock.RUnlock()indexFunc : c.indexers[indexName]// 通过indexFunc来判断这个分类方式是否存在if indexFunc nil {return nil, fmt.Errorf(Index with name %s does not exist, indexName)}// 拿到按照语言分类的Index对象index : c.indices[indexName]// index对象中有每一种语言对于的pod的对象key取出来直接返回即可set : index[indexedValue]return set.List(), nil }轻轻松松Indexer的源码阅读就算完成了总的来说代码并不复杂把涉及到的几个map梳理清楚基本上就能弄明白完整的逻辑了现在咱们已经掌握了Indexer的底层实现在今后的开发中相信您就能根据这些map的关系巧妙的设计出与业务匹配的定制化Indexer让这个优秀的缓存工具在云开发中充分的发挥作用至此《client-go的Indexer三部曲》系列也到了结束的时候然而client-go大系列不会结束后面欣宸还会更新client-go相关的原创与大家一起继续学习这个优秀的框架 你不孤单欣宸原创一路相伴 Java系列Spring系列Docker系列kubernetes系列数据库中间件系列DevOps系列
http://www.hkea.cn/news/14397511/

相关文章:

  • 唐山市住房和城乡建设局门户网站c#网站开发视频教程 高清
  • 猎头公司网站建设创网网络
  • 自适应网站运动div如何设置的南通市区有哪几家做网站的
  • 西宁网站建设加盟代理深圳官方网站制作
  • 北京个人制作网站有哪些网站建设费 开办费
  • pc端网页百度网站排名优化工具
  • 网站用心简约网站欣赏
  • 做兼职比较正规的网站树荫营销网站
  • 不是做有网站都叫jwthwordpress的排版
  • 曲阜公司网站建设价格电商网站的付款功能
  • 长沙建站公司模板创建外卖平台
  • 榆林做网站的公司电话网站ppt缩略图
  • 电子商务企业网站建设实训报告江苏建筑培训网
  • 营销型网站建设合同打折网站模板
  • 临沂科技学校网站建设wap卖料建站系统
  • 厦门网站建设一般多少钱太原网站建设价格
  • 集团公司网站方案安阳公司做网站
  • vip解析网站如何做杭州互联网大厂
  • 祥符网站建设免费网络节点
  • 网站建设大忌交易链接
  • 制作好网站怎么导入温州做微网站设计
  • 湖南地税局官网站水利建设基金自己怎么制作logo图标
  • 成都装修网站制作指数是什么
  • 网站模板建站教程视频教程网站维护哪些
  • 网站内容衡水做企业网站的公司
  • 微站官网专业软文平台
  • 梨园网站建设公司门户网站建设特点
  • 企业如何建自己的网站wordpress 网站访问认证页面
  • 建设工程标准在线网站广东建设工程协会网站
  • 做电容元器件的网站有哪些网站开发项目需求