2023-07-26

15 篇热帖

1. 90 后是不是玩不动游戏了?
按照这个标准
4090+i9 13900ks 搞一套,安装完系统 就后悔了,今天正在退货呢

日常工作 MaMacBook Apple M2 Max
大约 2018 年买的外星人 R7 日常 Windows 挂机
前几天通过 steam 下载了战神 4 卡的不行
索性就组个好点的机器吧

退款原因 玩了一次战神 4 特效全开没有现象中好 ,突然就有了个想法 为什么不买个 ps5 才$500 !
买完 ps5 玩一次就退货了
玩不动了 不想玩了
是不是这一代人 都是有我这样想法吗
2. 特斯拉为啥卖的这么好?

2023 年 6 月 销量中 Model 3 22741 在同款中排第二。

周围的人总是问我,为啥特斯拉卖的这么好? 有没有大佬说一下,为啥呢

3. 求推荐个实用的密码管理器
好用 , 安全
能支持多平台, 像有谷歌的插件,安卓,mac
是免费的就最好啦
4. 一个人做低代码平台,还有机会吗?

是的,你没看错,是一个人做一个低代码平台。
一人肝了好几年了,基本思路:
1 、前端可视化拖拽,逻辑编排+脚本支持,react 实现
该部分前端已发布一个开源项目: https://github.com/codebdy/rxdrag
2 、后端基于微内核(或者微服务),UML 类图转 Grahpql 接口。
通过微服务扩展复杂逻辑或者基础设施,通过脚本跟逻辑编排扩展业务逻辑。
该部分基本流程已经跑通,代码开源( golang+mysql )

相关文章:
实践,制作一个高扩展、可视化低代码前端,详实、完整(掘金)
实践,制作一个高扩展、可视化低代码前端,详实、完整(知乎)
挑战零代码:可视化逻辑编排(知乎)
挑战零代码:可视化逻辑编排(掘金)

目标:
做一个低代码平台,取名乐搭( Leda )。

目前整个项目组,只有一个人,有机会吗?

6. 求助!有人知道怎么向境外银行一次性汇款 50 万美金的渠道吗?
最近在办 A 国永居(不注销国籍),有个前提是需要一次性汇一笔 50 万美元到自己名下在 A 国开立的银行账户,这笔钱必须是从 A 国以外的地区直接汇入,直接从咱们国家汇出有外汇管制,但我只有国内资产,其他国家的海外资产很少,也没有海外信任的人可以帮忙。从国内出金汇入 A 国账户有没有风险和成本比较低的渠道可以实现?
7. 2023 年了,你还在学 Nginx 吗

Higress 介绍

Higress 是基于阿里巴巴内部两年多的 Envoy Gateway 实践沉淀,以开源 Istio 与 Envoy 为核心构建的下一代云原生网关。Higress 实现了安全防护网关、流量网关、微服务网关三层网关合一,可以显著降低网关的部署和运维成本。

官网地址: https://higress.cn

GitHub 地址: https://github.com/alibaba/higress

Higress 作为云原生网关的核心优势如下:

易用性

“云原生”已经不再是一个新鲜词,但企业对云原生技术的学习使用成本仍有许多顾虑,对云原生新标准的追赶又有很多焦虑;

Higress 同时提供了本地安装/生产部署的 quickstart ,可以一键部署,并通过控制台操作快速上手;基于简单易用的控制台,Higress 可以封装 Ingress/Gateway API 的标准细节,根治技术追赶焦虑。

标准化

K8s 带来了云原生的路由标准 Ingress/Gateway API ,如同 POSIX 定义 Unix 可移植操作系统标准,历时 35 年经久不衰,云原生的路由标准的生命周期一定会远超过 K8s 本身;

Higress 结合阿里内部实践以及阿里云产品沉淀,积累了基于 Ingress API 的丰富的路由策略扩展能力,同时还兼容大部分 Nginx Ingress 能力,这些能力后续也将在 Gateway API 上支持。

高集成

企业内有大量传统架构部署的服务,会成为向云原生架构演进的技术负担,要求云原生网关具备对接异构服务架构的能力;

基于 Higress 提供的多种服务发现机制,网关路由不仅可以转发到 K8s 服务,也可以直接配置 IP 转发到到物理机上的服务;基于 Nacos/ZooKeeper 等注册中心对接,还可以轻松实现 Spring Cloud 和 Dubbo 微服务的路由,无论其是否部署在 K8s 内。

易扩展

基于扩展机制进行二次开发的能力,是云原生网关在不同业务场景下都能适配落地的关键;

Higress 提供了灵活的插件扩展机制,目前插件市场已经推出多个官方插件,并支持用户通过控制台直接上传自己开发的插件,同时开源社区的插件市场生态也在不断建设中。

热更新

传统 Nginx 更新规则需要 reload 会导致链接抖动,导致流量损失,对实时通信、视频、IOT 无法容忍;

对于路由规则,Wasm 插件逻辑更新,以及证书改动等等,Higress 全部支持热更新,不会造成任何连接抖动。

Higress 全局配置

下文将介绍 Higress 全局配置控制面实现机制,Higress 数据面基于 Envoy 是 C++ 语言开发,控制面则是基于 Go 语言开发。控制面的开发上手门槛还是很低的,欢迎有更多同学参与贡献。社区也有多个学习兴趣小组,欢迎加入学习: https://github.com/alibaba/higress/issues?q=is%3Aopen+is%3Aissue+label%3A%22learning+to+share%22

Higress 有个全局配置 ConfigMap 对象 higress-config ,参考配置如下:

apiVersion: v1
data:
  higress: |-
    tracing:
      enable: true
      sampling: 100
      timeout: 500
      skywalking:
       service: skywalking-oap-server.op-system.svc.cluster.local
       port: 11800
...
...
kind: ConfigMap
metadata:
  name: higress-config
  namespace: higress-system

具体配置说明请参考 Higress 全局配置说明文档, 本文介绍以 Tracing 为例,详细说明 Tracing 全局配置是如何转成 EnvoyFilter 和如何同时实现实时下发到 Higress Gateway 过程。

本文涉及整体架构流程、初始化过程和启动、higress-config 变更和处理流程、通知 XDSUpdater 、构建 EnvoyFilter 和下发以及如何扩展全局配置等内容。

整体架构流程

1. 整体架构

img.png

2. 核心组件

  • IngressConfig

IngressConfig 是 Higress 一个核心结构体, 负责监控 Ingress ,McpBridge, Http2Rpc, WasmPlugin 等 k8s 资源, 同时集成 ConfigStore Interface ,通过 List 接口下发 VirtualService, DestinationRule, EnvoyFilter, ServiceEntry, WasmPlugin 等 CR 资源。

  • ConfigmapMgr

ConfigmapMgr 结构体负责整个核心流程,包括通过 Informer List/Watch 机制监控 higress-config 的变更,同时遍历 ItemControllers 下发变更通知,提供构建 EnvoyFilter 列表等功能。

  • TracingController

TracingController 结构体负责具体的 Tracing 数据校验,构建 Tracing EnvoyFilter, 以及通过 ItemEventHandler 下发变更通知等。

  • HigressConfig

HigressConfig 是 higress-config Configmap 所对应数据的结构体。

3. 核心流程

  • 用 Informer List/Watch 机制监控 higress-config 变更,校验变更,同时保存变更后数据。
  • 用变更数据构建 EnvoyFilter 。
  • 通知 XDSUpdater ,EnvoyFilter 有变更,重新拉取新的 EnvoyFilter 列表。

初始化过程

1. 初始化入口

初始化过程入口在 NewIngressConfig , 初始化 IngressConfig 时同时构建 HigressConfigController 和 ConfigmapMgr 。

// pkg/ingress/config/ingress_config.go
func NewIngressConfig(localKubeClient kube.Client, XDSUpdater model.XDSUpdater, namespace, clusterId string) *IngressConfig {
	// ...
	
	// 构建 controller 和 configmapMgr
	higressConfigController := configmap.NewController(localKubeClient, clusterId, namespace)
	config.configmapMgr = configmap.NewConfigmapMgr(XDSUpdater, namespace, higressConfigController, higressConfigController.Lister())

	return config
}

2. HigressConfigController 初始化

通过 Higress 提供 NewCommonController 初始化 HigressConfigController 用于监听 higress-system 命名空间下 Configmap 的变化。

// pkg/ingress/kube/configmap/controller.go
type HigressConfigController controller.Controller[listersv1.ConfigMapNamespaceLister]

func NewController(client kubeclient.Client, clusterId string, namespace string) HigressConfigController {
	informer := client.KubeInformer().Core().V1().ConfigMaps().Informer()
	return controller.NewCommonController("higressConfig", client.KubeInformer().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace),
		informer, GetConfigmap, clusterId)
}

func GetConfigmap(lister listersv1.ConfigMapNamespaceLister, namespacedName types.NamespacedName) (controllers.Object, error) {
	return lister.Get(namespacedName.Name)
}

3. ConfigmapMgr 初始化

ConfigmapMgr 初始化具体步骤如下:

  • 构建 ConfigmapMgr
  • 设置 HigressConfigController configmap 新增或者更新回调函数为 configmapMgr.AddOrUpdateHigressConfig
  • 设置 HigressConfig 结构体默认值
  • 初始化 TracingController
  • 把 tracingController 添加到 configmapMgr itemControllers 数组里
  • 初始化 ItemEventHandler , 同时遍历 itemControllers ,设置 ItemEventHandler
// pkg/ingress/kube/configmap/controller.go
func NewConfigmapMgr(XDSUpdater model.XDSUpdater, namespace string, higressConfigController HigressConfigController, higressConfigLister listersv1.ConfigMapNamespaceLister) *ConfigmapMgr {
    //  构建 ConfigmapMgr
	configmapMgr := &ConfigmapMgr{
		XDSUpdater:              XDSUpdater,
		Namespace:               namespace,
		HigressConfigController: higressConfigController,
		HigressConfigLister:     higressConfigLister,
		higressConfig:           atomic.Value{},
	}
	// 设置 HigressConfigController configmap 新增或者更新回调函数 configmapMgr.AddOrUpdateHigressConfig
	configmapMgr.HigressConfigController.AddEventHandler(configmapMgr.AddOrUpdateHigressConfig)
	// 设置 HigressConfig 结构体默认值
	configmapMgr.SetHigressConfig(NewDefaultHigressConfig())

	// 初始化 TracingController
	tracingController := NewTracingController(namespace)
	// 把 tracingController 添加到 configmapMgr itemControllers 里
	configmapMgr.AddItemControllers(tracingController)
	// 初始化 itemEventHandler , 同时遍历 itemControllers ,设置 itemEventHandler
	configmapMgr.initEventHandlers()

	// 返回 configmapMgr
	return configmapMgr
}

启动

在 IngressConfig 添加 HigressConfigController Run() 和 HasSynced() 控制流程。

// pkg/ingress/config/ingress_config.go
func (m *IngressConfig) Run(stop <-chan struct{}) {
	// ...
	// 启动 HigressConfigController
	go m.configmapMgr.HigressConfigController.Run(stop)
}

func (m *IngressConfig) HasSynced() bool {
	// ....
	if !m.configmapMgr.HigressConfigController.HasSynced() {
		return false
	}
}

higress-config 变更和处理流程

1. configmapMgr 变更处理

ConfigmapMgr 通过收到 HigressConfigController 通知来处理变更请求。

具体变更流程如下:

  • 判断是否 higress-system 命名空间下 name 为 higress-config Configmap 发生了变化,如果不是就返回。
  • 获取 higress-config 内容。
  • 遍历 ItemControllers, 校验 higress-config 配置是否合法,如果有一个返回不合法,就返回。
  • 和上次保存在本地 higressConfig 比对, 检查这次数据是否有变化,如果没有变化就返回。
  • 如果数据有变化,就遍历 ItemControllers 通知每个 itemController 数据有变化,同时保存这次变化到本地 higressConfig 。
// pkg/ingress/kube/configmap/controller.go
func (c *ConfigmapMgr) AddOrUpdateHigressConfig(name util.ClusterNamespacedName) {
	// 只监听 higress-system 命名空间下 name 为 higress-config Configmap 的变化
	if name.Namespace != c.Namespace || name.Name != HigressConfigMapName {
		return
	}
    // ...
	// 获取 higress-config 内容
	higressConfigmap, err := c.HigressConfigLister.Get(HigressConfigMapName)
	
	// 通过 yaml.Unmarshal 转成 HigressConfig
	newHigressConfig := NewDefaultHigressConfig()
	if err = yaml.Unmarshal([]byte(higressConfigmap.Data[HigressConfigMapKey]), newHigressConfig); err != nil {
		IngressLog.Errorf("data:%s,  convert to higress config error, error: %+v", higressConfigmap.Data[HigressConfigMapKey], err)
		return
	}

	// ...
	// 遍历 ItemControllers, 校验配置是否合法
	for _, itemController := range c.ItemControllers {
		if itemErr := itemController.ValidHigressConfig(newHigressConfig); itemErr != nil {
			IngressLog.Errorf("configmap %s controller valid higress config error, error: %+v", itemController.GetName(), itemErr)
			return
		}
	}

	// 和上次比对这次数据是否有变更
	oldHigressConfig := c.GetHigressConfig()
	result, _ := c.CompareHigressConfig(oldHigressConfig, newHigressConfig)
    // ...
	// 如果数据有变更,就遍历 ItemControllers 通知每个 itemController 数据有变更,同时保存这次变更到本地。
	if result == ResultReplace || result == ResultDelete {
		for _, itemController := range c.ItemControllers {
			IngressLog.Infof("configmap %s controller AddOrUpdateHigressConfig", itemController.GetName())
			if itemErr := itemController.AddOrUpdateHigressConfig(name, oldHigressConfig, newHigressConfig); itemErr != nil {
				IngressLog.Errorf("configmap %s controller AddOrUpdateHigressConfig error, error: %+v", itemController.GetName(), itemErr)
			}
		}
		// 保存这次变更
		c.SetHigressConfig(newHigressConfig)
	}
}

2. TracingController 变更处理

TracingController 变更处理就比较简单:

  • 检查 Tracing 这部分数据是否有变更。
  • 如果有变更,DeepCopy 一份 Tracing 数据保存到本地,同时通过 eventHandler 下发变更通知。
// pkg/ingress/kube/configmap/tracing.go
func (t *TracingController) AddOrUpdateHigressConfig(name util.ClusterNamespacedName, old *HigressConfig, new *HigressConfig) error {
	// ...
	// 检查 Tracing 部分数据是否有变更
	result, _ := compareTracing(old.Tracing, new.Tracing)

	// 如果有变更,DeepCopy 一份 Tracing 数据保存到本地,同时通过 eventHandler 下发变更通知
	switch result {
	case ResultReplace:
		if newTracing, err := deepCopyTracing(new.Tracing); err != nil {
			IngressLog.Infof("tracing deepcopy error:%v", err)
		} else {
			t.SetTracing(newTracing)
			IngressLog.Infof("AddOrUpdate Higress config tracing")
			t.eventHandler(higressTracingEnvoyFilterName)
			IngressLog.Infof("send event with filter name:%s", higressTracingEnvoyFilterName)
		}
	case ResultDelete:
		t.SetTracing(NewDefaultTracing())
		IngressLog.Infof("Delete Higress config tracing")
		t.eventHandler(higressTracingEnvoyFilterName)
		IngressLog.Infof("send event with filter name:%s", higressTracingEnvoyFilterName)
	}

	return nil
}

通知 XDSUpdater

在 ConfigmapMgr 初始化时候调用 configmapMgr.initEventHandlers(), 这个 func 会创建 ItemEventHandler, 同时遍历 ItemControllers 设置 ItemEventHandler 。

// pkg/ingress/kube/configmap/config.go
type ItemEventHandler = func(name string)

// pkg/ingress/kube/configmap/controller.go
func (c *ConfigmapMgr) initEventHandlers() error {
    itemEventHandler := func(name string) {
    c.XDSUpdater.ConfigUpdate(&model.PushRequest{
        Full: true,
        ConfigsUpdated: map[model.ConfigKey]struct{}{{
            Kind:      gvk.EnvoyFilter,
            Name:      name,
            Namespace: c.Namespace,
        }: {}},
        Reason: []model.TriggerReason{ModelUpdatedReason},
        })
    }
    
    for _, itemController := range c.ItemControllers {
		itemController.RegisterItemEventHandler(itemEventHandler)
    }
    
    return nil
}

这里 XDSUpdater 是从 IngressConfig 初始化传入,XDSUpdater.ConfigUpdate() 用于更新通知下发。

进一步跟踪可以发现在 Higress controller server 启动时执行 s.initXdsServer 函数创建 s.xdsServer ,具体逻辑不在本文讨论范围, 有兴趣可以进一步阅读源码。

// pkg/bootstrap/server.go
func NewServer(args *ServerArgs) (*Server, error) {
	// ...
	s := &Server{
		ServerArgs:      args,
		httpMux:         http.NewServeMux(),
		environment:     e,
		readinessProbes: make(map[string]readinessProbe),
		server:          server.New(),
	}
	s.environment.Watcher = mesh.NewFixedWatcher(&v1alpha1.MeshConfig{})
	s.environment.Init()
	initFuncList := []func() error{
		s.initKubeClient,
		s.initXdsServer,
		s.initHttpServer,
		s.initConfigController,
		s.initRegistryEventHandlers,
		s.initAuthenticators,
	}

	for _, f := range initFuncList {
		if err := f(); err != nil {
			return nil, err
		}
	}

	// ...
	return s, nil
}

// pkg/bootstrap/server.go
func (s *Server) initXdsServer() error {
    log.Info("init xds server")
    s.xdsServer = xds.NewDiscoveryServer(s.environment, nil, PodName, PodNamespace, s.RegistryOptions.KubeOptions.ClusterAliases)
    // ...
    return s.initGrpcServer()
}

构建和下发 EnvoyFilters

1. IngressConfig List 下发 EnvoyFilters 列表

IngressConfig List 用于 VirtualService, DestinationRule, EnvoyFilter, ServiceEntry, WasmPlugin 等 CR 资源下发, 这里主要关注 EnvoyFilter CR 资源下发。

// pkg/ingress/config/ingress_config.go
func (m *IngressConfig) List(typ config.GroupVersionKind, namespace string) ([]config.Config, error) {
	if typ != gvk.Gateway &&
		typ != gvk.VirtualService &&
		typ != gvk.DestinationRule &&
		typ != gvk.EnvoyFilter &&
		typ != gvk.ServiceEntry &&
		typ != gvk.WasmPlugin {
		return nil, common.ErrUnsupportedOp
	}
	// ...
	if typ == gvk.EnvoyFilter {
		m.mutex.RLock()
		defer m.mutex.RUnlock()
		var envoyFilters []config.Config
		
		// 调用 ConfigmapMgr ConstructEnvoyFilters 获取需要下发 EnvoyFilter 列表
		configmapEnvoyFilters, err := m.configmapMgr.ConstructEnvoyFilters()
		if err != nil {
			IngressLog.Errorf("Construct configmap EnvoyFilters error %v", err)
		} else {
			for _, envoyFilter := range configmapEnvoyFilters {
				envoyFilters = append(envoyFilters, *envoyFilter)
			}
			IngressLog.Infof("Append %d configmap EnvoyFilters", len(configmapEnvoyFilters))
		}
		if len(envoyFilters) == 0 {
			IngressLog.Infof("resource type %s, configs number %d", typ, len(m.cachedEnvoyFilters))
			return m.cachedEnvoyFilters, nil
		}
		// 需要下发 configmap EnvoyFilter 列表 和 m.cachedEnvoyFilters 列表聚合一下下发
		envoyFilters = append(envoyFilters, m.cachedEnvoyFilters...)
		IngressLog.Infof("resource type %s, configs number %d", typ, len(envoyFilters))
		return envoyFilters, nil
	}
	
}	

调用 ConfigmapMgr ConstructEnvoyFilters 获取需要下发 EnvoyFilter 列表, 同时和 m.cachedEnvoyFilters 列表聚合一下再下发。

这里 m.cachedEnvoyFilters 是在构建 VirtualService 时生成,有兴趣可以进一步阅读 IngressConfig 源码。

2. ConfigmapMgr 构建 EnvoyFilter 列表

这里比较简单,遍历一下 ItemControllers ,聚合每个 itemController 返回的 EnvoyFilters.

// /pkg/ingress/kube/configmap/controller.go
func (c *ConfigmapMgr) ConstructEnvoyFilters() ([]*config.Config, error) {
	configs := make([]*config.Config, 0)
	for _, itemController := range c.ItemControllers {
		IngressLog.Infof("controller %s ConstructEnvoyFilters", itemController.GetName())
		if itemConfigs, err := itemController.ConstructEnvoyFilters(); err != nil {
			IngressLog.Errorf("controller %s ConstructEnvoyFilters error, error: %+v", itemController.GetName(), err)
		} else {
			configs = append(configs, itemConfigs...)
		}
	}
	return configs, nil
}

3. TracingController 构建 EnvoyFilters

这里就比较简单,根据保存的 Tracing 数据构建对应的 EnvoyFilter

// pkg/ingress/kube/configmap/tracing.go
func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
	// ...
	tracingConfig := t.constructTracingTracer(tracing, namespace)
	if len(tracingConfig) == 0 {
		return configs, nil
	}

	config := &config.Config{
		Meta: config.Meta{
			GroupVersionKind: gvk.EnvoyFilter,
			Name:             higressTracingEnvoyFilterName,
			Namespace:        namespace,
		},
		Spec: &networking.EnvoyFilter{
			ConfigPatches: []*networking.EnvoyFilter_EnvoyConfigObjectPatch{
				{
					ApplyTo: networking.EnvoyFilter_NETWORK_FILTER,
					Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
						Context: networking.EnvoyFilter_GATEWAY,
						ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
							Listener: &networking.EnvoyFilter_ListenerMatch{
								FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
									Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
										Name: "envoy.filters.network.http_connection_manager",
									},
								},
							},
						},
					},
					Patch: &networking.EnvoyFilter_Patch{
						Operation: networking.EnvoyFilter_Patch_MERGE,
						Value:     util.BuildPatchStruct(tracingConfig),
					},
				},
				{
					ApplyTo: networking.EnvoyFilter_HTTP_FILTER,
					Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
						Context: networking.EnvoyFilter_GATEWAY,
						ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
							Listener: &networking.EnvoyFilter_ListenerMatch{
								FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
									Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
										Name: "envoy.filters.network.http_connection_manager",
										SubFilter: &networking.EnvoyFilter_ListenerMatch_SubFilterMatch{
											Name: "envoy.filters.http.router",
										},
									},
								},
							},
						},
					},
					Patch: &networking.EnvoyFilter_Patch{
						Operation: networking.EnvoyFilter_Patch_MERGE,
						Value: util.BuildPatchStruct(`{
							"name":"envoy.filters.http.router",
							"typed_config":{
								"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router",
								"start_child_span": true
							}
						}`),
					},
				},
			},
		},
	}

	configs = append(configs, config)
	return configs, nil
}

如何扩展全局配置

1. HigressConfig 结构体添加对应的扩展配置

type HigressConfig struct {
	Tracing *Tracing `json:"tracing,omitempty"`
	// 在这里添加对应的数据结构来扩展配置
}

2. 增加扩展配置默认值

// pkg/ingress/kube/configmap/config.go
func NewDefaultHigressConfig() *HigressConfig {
	higressConfig := &HigressConfig{
		Tracing: NewDefaultTracing(),
		// 在这里增加扩展配置默认值
	}
	return higressConfig
}

3. 实现 ItemController interface

type ItemController interface {
	GetName() string
	AddOrUpdateHigressConfig(name util.ClusterNamespacedName, old *HigressConfig, new *HigressConfig) error
	ValidHigressConfig(higressConfig *HigressConfig) error
	ConstructEnvoyFilters() ([]*config.Config, error)
	RegisterItemEventHandler(eventHandler ItemEventHandler)
}

4. 初始化扩展配置,同时添加到 ItemControllers

func NewConfigmapMgr(XDSUpdater model.XDSUpdater, namespace string, higressConfigController HigressConfigController, higressConfigLister listersv1.ConfigMapNamespaceLister) *ConfigmapMgr {
	// ...
	tracingController := NewTracingController(namespace)
	configmapMgr.AddItemControllers(tracingController)
	// ...
	// 在这里初始化扩展配置,同时添加到 ItemControllers
	configmapMgr.initEventHandlers()

	return configmapMgr
}

参与社区贡献

Higress 开源贡献小组正在火热招募贡献者。早期参与开源更容易成为项目 Committer ,并有更多机会成为 Higress PMC(Project Management Committee) 的一员,参与主导 Higress 社区的前进方向。 欢迎加入 Higress 社区群:

8. 新房 2 月份装修好,散了五个月甲醛了,现在可以入住了么?

原计划 9 月底搬新家,但是手头拮据,提前 2 个月搬的话可以省出 7000rmb

主要家里有三岁小孩,放置这么长时间也是处于此考虑。


主要异味来源是木工打的衣柜、书柜、餐边柜,柜体兔宝宝生态板,柜门千年舟,

是那种带着芬香气味的味道,现在虽然没有一开始浓重但是还是能闻出来。

9. 大家有什么可以提高幸福感的小玩意推荐吗?

由于我司一个神奇的活动,获得了一个 5k 块代付机会。规则是物品价格上限 10k ,但报销最多 5k ,不可买加油卡,购物卡,京东卡这种类似折现的东西。

突然发现平时也不怎么会省钱,所以想要的,能买得起的东西基本都买了,想来想去也想不出买点啥。

所以就想问问大家,有什么 5k 块左右可以提升幸福感的小玩意推荐。 这次买不上的,收录到我的败家 list 里面,嘿嘿~

10. 真是绝了, github 上 YunaiV/ruoyi-vue-pro 项目打着开源的旗号收费

今天无意中在 github 上发现了这个项目,点开发现 stars 挺多的,在 gitee 上 stars 更是惊人,有 73.4K 之多,想着 stars 这么多,项目应该不错,就 clone 到本地看下,准备看文档启动的时候问题来了,访问文档地址竟然要登录,这都没啥,你点击快速启动以及功能列表,会有个弹窗,要求你先 star 才能看。“后端手册”手册就更离谱了,要求你微信扫码加入星球,而加入星球需要支付 199 元人民币,也就是说,你要看到完整的文档,需要 star+支付 199 元人民币……

他项目的 README.md 写着“芋道,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用”,代码可以免费使用,文档要收费,没毛病[手动狗头]

11. 你不止活一世

不谈灵性,也不谈科学。

简单的问问你自己:此刻的你正在思考,你能意识到自己的存在。死是什么意思?为什么你会意识不到自己的存在?

12. Telegram 是如何做到十几个万人群还是如此流畅的?
1 、Android 、iOS 都非常流畅,除了 Web 网页版有时候略卡
十几个万人群,要做到这种流畅程度,有哪些值得学习的?

2 、本地缓存极少
设置本地缓存仅保存 1 周,所有内容存储云端。目前本地缓存总共占 300M 。

3 、多端同步
Android 、iOS 、Web 三端都在使用,同步做得非常好。它还包括 Windows 、Linux 、macOS 等客户端,如此多的平台支持,同步功能能做到如此程度,简直奇迹。

我的日常使用:
1 )聊天沟通;
2 )听歌(自己上传的音频);看 MV ( B 站收集的音乐视频);
3 )文件备份(中文搜索很烂,目前加标签、主动加分隔符号将就用);
4 )树洞(建个私有频道,写些乱七八糟的东西);
5 )结合 Tasker + 脚本,进行指定图片、短信的备份;

有没有大佬就 1 、2 个点分析下自己的见解,Telegram 有哪些值得学习的地方?
13. 你们有更新强迫症吗
系统、软件都更新到最新版,各种依赖包更新到最新版
14. 有便宜的机场推荐吗?最好是月付 1-3 元的

之前一直用的一元机场,FSCLOUD 之类的,很便宜,就是跑路了,有 v 友推荐一下吗?就月付 1-3 元的,凑合用就行

15. 油车自驾车队里的纯电车
长途自驾游,其中有一对准备开纯油车一起去,因为每天的行进距离大概都已经定好了,高速上面的起步阶段,一天可能就要跑 700km 左右,目的地后每天都接近 3-4 百 km ,在高速休息站放水休息的 10 来分钟,电车能搞定补能吗?哎…