Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Proposal: 对接 Nacos 配置中心 | Nacos As Config Center #975

Closed
felix021 opened this issue Jun 13, 2023 · 17 comments
Closed

Proposal: 对接 Nacos 配置中心 | Nacos As Config Center #975

felix021 opened this issue Jun 13, 2023 · 17 comments
Assignees
Labels
proposal A proposal need to discuss and will do implementation.

Comments

@felix021
Copy link
Contributor

felix021 commented Jun 13, 2023

This module is implemented in: https://github.com/kitex-contrib/config-nacos/

背景

Support integration with well-known config centers

目标

基于本文描述的配置存储参考规范:

  • 按 Kitex 的 Suite 扩展规范,实现 NacosClientSuite、NacosServerSuite;
  • 基于上面实现的方案,写一个简单的例子(Kitex Client & Server),用于展示实际用法;

配置存储参考规范

根据 Nacos OpenAPI,每一份配置由 (namespaceId, group, dataId) 三元组唯一标识。

字段 取值 说明
namespaceId 固定值,如 "KitexConfig" 建议新建命名空间,独立管理RPC配置,避免与非 Kitex 配置冲突、误操作
group 默认值 DEFAULT_GROUP,也可以由用户自定义 (方案详情: TODO @whalecold)
dataId 格式为 ${ClientServiceName}.${ServerServiceName}.${Category};也可以由用户自定义 其中 Category 为枚举值:"rpc_timeout", "retry", "circuit_break", "limit",用于指定配置类型,超时、重试、熔断、限流

客户端配置

超时:Category=rpc_timeout

配置信息格式为 JSON,其 Schema 为

map[string]*rpctimeout.RPCTimeout // 分method指定超时配置

说明:

例如:Echo 方法链接超时 50ms、请求超时 1s,其他方法连接超时 100ms、请求超时 2s

{
  "*": {
    "conn_timeout_ms": 100,
    "rpc_timeout_ms": 2000
  },
  "Echo": {
    "conn_timeout_ms": 50,
    "rpc_timeout_ms": 1000
  }
}

注:Kitex 只区分连接超时和读写超时,因此只需要指定两个字段即可。

重试:Category=retry

配置信息格式为 JSON,其 Schema 为

map[string]*retry.Policy

说明:

例如:Echo 方法启用备用请求(200ms后未返回则发出),其他请求都默认失败重试3次

{
    "*": {
        "enable": true,
        "type": 0,                 // 失败重试(type=0)
        "failure_policy": {
            "stop_policy": {
                "max_retry_times": 3,
                "max_duration_ms": 2000,
                "cb_policy": {
                    "error_rate": 0.1
                }
            },
            "backoff_policy": {
                "backoff_type": "fixed",
                "cfg_items": {
                    "fix_ms": 50
                }
            }
        }
    },
    "Echo": {
        "enable": true,
        "type": 1,                // 备用请求(type=1)
        "backup_policy": {
            "retry_delay_ms": 200,
            "stop_policy": {
                "max_retry_times": 2,
                "max_duration_ms": 1000,
                "cb_policy": {
                    "error_rate": 0.3
                }
            }
        }
    }
}

注:retry.Container 内置支持用 * 通配符指定默认配置(详见 getRetryer 方法)

熔断:Category=circuit_break

配置信息格式为 JSON,其 Schema 为

map[string]*circuitbreak.CBConfigItem

注:

例如:Echo 方法使用下面的配置(0.3、100),其他方法使用全局默认配置(0.5、200)

{
  "Echo": {
    "enable": true,
    "err_rate": 0.3,
    "min_sample": 100
  }
}

注:kitex 的熔断实现目前不支持修改全局默认配置(详见 initServiceCB

服务端

限流:Category=limit

Group 里 CallerName 的值留空,表示是服务端配置,与客户端无关

配置信息格式为 JSON,其 Schema 为 limiter.LimiterConfig

type LimiterConfig struct {
	ConnectionLimit int64 `json:"connection_limit"`
	QPSLimit        int64 `json:"qps_limit"`
}

例如:最大100并发 && 每 100ms 内最大 2000QPS

{
  "connection_limit": 100,
  "qps_limit": 200
}

注:

  1. 限流配置的粒度是 Server 全局,不分 client、method
  2. 「未配置」或「取值为 0」表示不开启
  3. connection_limit 和 qps_limit 可以独立配置,例如 connection_limit = 100, qps_limit = 0

参考

@felix021
Copy link
Contributor Author

感兴趣的同学可以认领这个任务,如有疑问可以留言

@whalecold
Copy link
Member

感兴趣的同学可以认领这个任务,如有疑问可以留言

可以分给我

@YangruiEmma YangruiEmma added the proposal A proposal need to discuss and will do implementation. label Jun 13, 2023
@whalecold
Copy link
Member

whalecold commented Jun 15, 2023

简单用了下 nacos 的配置,有几个问题:

  • 使用 $ClientServiceName/$ServerServiceName/$Extra 的格式作为 Group 好像不太合适,因为服务也有 Group 属性,我理解某个配置只会对相同 Group 的服务生效
  • dataId 作为枚举值的话同一个 group 下的配置很快就用完了

是不是这样改比较好一点:

  • Group 保持和注册中心的一致
  • dataId 用户自己定义和服务以及治理类型无关
  • 使用归属应用作为配置的服务归属,添加 kitex_config_type: rpc_timeout 的标签来标识治理类型; 或者按照 AllInOne 的方式配置,这样可以减少使用者的配置数量。 例如
{
    "rpc_timeout":{

    },
    "retry_config":{

    }
}

还有我们需要用标签显式的指定规则是生效在 client 侧还是 server 侧吗
image

@felix021
Copy link
Contributor Author

  1. 「服务也有 Group 属性」是指什么?按我的理解, Nacos 只是用 (namespaceId, group, dataId) 来唯一标识一个配置,和服务似乎没关系,决于调用 api 时给了什么值;
  2. 「同一个 group 下的配置很快就用完了」,这是 nacos 的什么限制?
  3. 关于配置的粒度,在做这个方案的时候我们考虑过,两个极端分别是 (1) 所有配置放在同一个 group + dataId 下, (2) group中包含方法名称。在和两个企业用户沟通过后,暂定用当前这个折中方案:(1) 单条配置不会太大(特别是 nacos 的 API 不支持乐观锁更新,单条配置越大越容易出现两个不同用户同时修改导致配置被覆盖的问题),(2) 配置的数量不会太多,(3) 单条配置的含义比较明确。。如果用户确实希望调整这个粒度,可以 fork 后自行修改实现。

@whalecold
Copy link
Member

  1. Nacos 也是一个服务注册中心,页面可以参考下图哈。不知道这里 Nacos 作为配置中心是否要配合 Nacos 的注册中心一起使用,如果是的话配置只会对同 Group 的服务生效的,在不同 Group 下是允许同名服务的。同时我在页面上尝试手动创建带 / 的 Group 也会报错。
  2. 是在 1 的前提下,Group 限定死了,dataId 又是枚举的,感觉有问题。

image

@CoderPoet
Copy link
Member

个人感觉 Kitex 动态配置模型是不是不应该强依赖 nacos 的概念来做?

主要有几点考虑:

  1. nacos 提供的 namespace 和 group 概念,其他配置中心不一定会有等价的概念,切换其他配置中心的时候,用户使用习惯可能得发生变化

  2. nacos 提供这些概念更多是让用户去灵活根据自己的场景去进行配置隔离和管理,我们这边占用掉了,是否会影响用户使用的灵活性呢?
    比如:通常我们会用 namespace 来做环境隔离,使用 group 来做业务隔离,这边如果占用了 namespace 和 group,是不是用户就没办法进行环境、业务隔离了?

  3. 如果是为了考虑开箱即用,只依靠 dataid 的命名约定方式是不是也足够了?
    比如参考 spring cloud 的做法:${prefix}-${spring.profiles.active}.${file-extension},kitex 是不是也可以设计一个命名约定?

/cc @felix021 @whalecold

@felix021
Copy link
Contributor Author

个人感觉 Kitex 动态配置模型是不是不应该强依赖 nacos 的概念来做?

主要有几点考虑:

  1. nacos 提供的 namespace 和 group 概念,其他配置中心不一定会有等价的概念,切换其他配置中心的时候,用户使用习惯可能得发生变化
  2. nacos 提供这些概念更多是让用户去灵活根据自己的场景去进行配置隔离和管理,我们这边占用掉了,是否会影响用户使用的灵活性呢?
    比如:通常我们会用 namespace 来做环境隔离,使用 group 来做业务隔离,这边如果占用了 namespace 和 group,是不是用户就没办法进行环境、业务隔离了?
  3. 如果是为了考虑开箱即用,只依靠 dataid 的命名约定方式是不是也足够了?
    比如参考 spring cloud 的做法:${prefix}-${spring.profiles.active}.${file-extension},kitex 是不是也可以设计一个命名约定?

/cc @felix021 @whalecold

是的,我们讨论了这个问题,初步结论如下:

  1. namespace 应该是用于环境隔离的,应该类似于 kitex-config-production, kitex-config-test 这样的方式。不过也取决于用户的实际部署环境,如果用户的 nacos 在 production、test 环境是隔离部署的,那么不一定需要体现在 namespace 的取值里

  2. group 和 dataId 的设定需要更灵活一点,考虑是我们提供一个默认方案(命名约定),但允许用户注入自己的方案。具体方案待 @whalecold 再细化一下

@whalecold
Copy link
Member

whalecold commented Jun 26, 2023

支持自定义 group 和 dataid,自定义格式之间用 . 号作为分割符,服务本身不应该额外使用该字符。
如果不需要的配置,例如配置 client 的策略,ServerServiceName 使用空格代替,ClientServiceName 同理。

默认值

group: DEFAULT_GROUP
dataId:{{.ClientServiceName}}.{{.ServerServiceName}}.{{.PolicyName}}

用户也可以灵活配置,例如:

group: {{.ClientServiceName}}
dataId:{{.ServerServiceName}}.{{.PolicyName}}

cc @CoderPoet @felix021

@CoderPoet
Copy link
Member

用户的服务名里出现 . 是不是比较常见? 比如 psm 都是有 . 的

@whalecold
Copy link
Member

whalecold commented Jun 28, 2023

用户的服务名里出现 . 是不是比较常见? 比如 psm 都是有 . 的

nacos 本身有一些限制,分隔符选择的不多,还有下划线和中划线,有什么推荐的吗 @CoderPoet

@CoderPoet
Copy link
Member

用户的服务名里出现 . 是不是比较常见? 比如 psm 都是有 . 的

nacos 本身有一些限制,分隔符选择的不多,还有下划线和中划线,有什么推荐的吗 @CoderPoet

如果只有这几个选择,确实比较尴尬,个人感觉这几个里面,可能服务名里用下划线的会相对少一点

@whalecold
Copy link
Member

whalecold commented Jun 28, 2023

用户的服务名里出现 . 是不是比较常见? 比如 psm 都是有 . 的

nacos 本身有一些限制,分隔符选择的不多,还有下划线和中划线,有什么推荐的吗 @CoderPoet

如果只有这几个选择,确实比较尴尬,个人感觉这几个里面,可能服务名里用下划线的会相对少一点

现在用户可以自定义的,只是默认用了 ., 实现上是用 go 的 template 渲染了 ClientServiceName、PolicyName、ClientServiceName 这三个值,所以还是挺灵活的。

@CoderPoet
Copy link
Member

用户的服务名里出现 . 是不是比较常见? 比如 psm 都是有 . 的

nacos 本身有一些限制,分隔符选择的不多,还有下划线和中划线,有什么推荐的吗 @CoderPoet

如果只有这几个选择,确实比较尴尬,个人感觉这几个里面,可能服务名里用下划线的会相对少一点

现在用户可以自定义的,只是默认用了 ., 实现上是用 go 的 template 渲染了 ClientServiceName、PolicyName、ClientServiceName 这三个值,所以还是挺灵活的。

动态配置逻辑里并不需要从 dataid 里取这些值是么?

@whalecold
Copy link
Member

动态配置逻辑里并不需要从 dataid 里取这些值是么?

每个规则的配置名称都是确定的,比如说有个 bookinfo 的 client 要去开启 retry 的规则,那么 dataid 肯定就是 bookinfo..retry,这时候去订阅制定的配置就好了~ nacos clinet 提供了 ListenConfig 的接口

@CoderPoet
Copy link
Member

动态配置逻辑里并不需要从 dataid 里取这些值是么?

每个规则的配置名称都是确定的,比如说有个 bookinfo 的 client 要去开启 retry 的规则,那么 dataid 肯定就是 bookinfo..retry,这时候去订阅制定的配置就好了~ nacos clinet 提供了 ListenConfig 的接口

OK,那感觉用 . 没啥问题

@whalecold
Copy link
Member

whalecold commented Jul 25, 2023

字段:group
取值:默认值 DEFAULT_GROUP,也可以由用户自定义
说明:自定义格式参考 go template 的语法,可以根据 ClientServiceName、ServerServiceName、Category 三个元数据自由定义,自定义环境环境变量为 configGroup


字段:dataId
取值:默认格式为 ${ClientServiceName}.${ServerServiceName}.${Category};也可以由用户自定义
说明:自定义语法参考 group,环境变量 Key 为 configDataId。 其中 Category 为枚举值:"rpc_timeout", "retry_config", "cb_config", "limiter_config",用于指定配置类型,超时、重试、熔断、限流

补充了下 Proposal, @felix021 你更新下哈

@felix021 felix021 changed the title Proposal: 对接 Nacos 配置中心 Proposal: 对接 Nacos 配置中心 | Nacos As Config Center Sep 18, 2023
@felix021
Copy link
Contributor Author

This module is implemented in https://github.com/kitex-contrib/config-nacos/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal A proposal need to discuss and will do implementation.
Development

No branches or pull requests

4 participants