Files
KnowStreaming/docs/plus/04.灾备共享用户兼容设计.md
2023-02-14 16:27:47 +08:00

227 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 背景
目前灾备方案使用客户端User唯一标识做灾备切换能有效保障整个客户端元数据统一切换。目前用户存量场景存在Kafka User共享使用情况但是各个客户端对Topic的访问是互相独立的为了兼容这种场景实现客户端能独立进行灾备切换而不影响其他客户端连带切换。
## 方案
### Client端兼容方案二
**client.id 格式:** ~~HA#AppId#TopicName~~ InstanceID
一个InstanceID可以对应多个Topic
**约束:** AppID下每个客户端实例使用相同的InstanceID并且不同客户端实例的InstanceID不能重复
> 客户端实例定义最好是每个生产者、消费者实例使用一套InstanceID次之是应用粒度一个应用使用一套InstanceID但是存在访问多个Topic会存在一些关联切换情况
>
> 注意客户端每次启动都使用相同的InstanceID不能每次启动都生成新的InstanceID
**InstanceID生成方式**
1. 由平台申请生成InstanceID可以在Topic申请时为每一个Topic产生一个InstanceID或者多个Topic申请一个InstanceID
2. 由用户自己控制直接在客户端设置一个ID
**InstanceID和Topic对应关系**
1. 声明式由平台申请InstanceID与Topic绑定关系
2. 自动化:从引擎侧上报的连接信息中自动获取(客户端未启动过这种场景获取不到)
引擎侧上报用户访问信息已有TopicName、AppID、访问类型生产、消费、ClientID
**平台切换:**
用户选择切换方式:用户维度、用户+InstanceID维度
用户维度跟现有逻辑保持一致用户下所有Topic同时切换
用户+InstanceID维度切换Topic时如果用户下InstanceID绑定了Topic则只切换这个InstanceID否则整个用户进行切换
**Gateway、引擎处理**
如果AppID+InstanceID绑定了集群则按这个集群进行转发否则按AppID粒度进行转发
### Server端兼容方案
#### 现状
灾备Gateway、Broker会根据客户端标识转发以下请求
- API_VERSIONS
- METADATAnull、empty、some topics
- FIND_COORDINATOR
- INIT_PRODUCER_ID // 无事务、幂等场景可忽略
Broker会根据客户端标识阻断以下请求
- PRODUCE
- FETCH
- OFFSET_COMMIT
- OFFSET_FETCH
- JOIN_GROUP
- HEARTBEAT
- OFFSET_FOR_LEADER_EPOCH
#### 流程
每个节点建立连接后会发送API_VERSIONS请求获取节点协议版本信息
**生产者:**
1. 生产者启动后会先向引导地址发送METADATAtopics=empty请求只请求集群地址的元数据并更新缓存中metadata的nodes信息
2. 当发送一条消息后生产者刷新元数据发送METADATAtopics=some topics请求
**消费者:**
1. 消费者启动后会向引导地址发送METADATAtopics=empty请求只请求集群地址的元数据并更新缓存中metadata的nodes信息
2. 消费者启动后会向引导地址发送FIND_COORDINATOR请求获取Coordinator地址
3. 客户端向Coordinator发起连接后续发送JOIN_GROUP、SYNC_GROUP
4. 随后会更新客户端元数据,发送元数据请求
如果订阅类型为AUTO_TOPICS会向引导地址发送METADATAtopics=some topics请求
如果订阅类型为AUTO_PATTERN则会向引导地址发送**METADATAtopics=null**请求null为all topics元数据请求
**请求归类:**
- **无信息**
- API_VERSIONS
- METADATAnull、empty
- **含Topic信息**(多个)
- METADATAsome topics
- PRODUCE
- FETCH
- OFFSET_FOR_LEADER_EPOCH
- **含Group信息**
- FIND_COORDINATOR
- OFFSET_COMMIT
- OFFSET_FETCH
- JOIN_GROUP
- HEARTBEAT
#### 改造
根据更细粒度客户端标识进行转发和阻断对于生产者使用AppID#TopicName消费者使用AppID#TopicName或AppID##GroupName作为客户端标识
> 限制1要求AppID#TopicName或AppID##GroupName全局唯一
>
> 限制2要求客户端只访问一个Topic待定
1. **客户端标识获取**
通过解析请求协议内容获取对应的标识符
Topic AppID#TopicName
GroupAppID##GroupName
2. **请求协议处理**
根据优先级AppID##GroupName、AppID#TopicName、AppID获取客户端标识是否绑定集群如果绑定集群进行响应转发或者阻断
3. **无标识请求处理**
- API_VERSIONS
客户端发送API_VERSIONS到Gateway由Gateway直接响应给客户端GW的APIs信息不进行转发由于GW是基于2.5版本的灾备也是基于2.5版本),这里需要判断是不是灾备场景,非灾备场景继续按原有逻辑进行处理
- METADATA
empty情况这种情况是客户端第一次启动时发出的请求nodes信息由Gateway直接响应给客户端GW地址不进行转发
null情况这种情况时消费者采用正则的方式进行订阅需要返回用户有权限的所有Topic列表Gateway无法处理这种场景
4. **多Topic处理**
方案1只处理单一Topic情况如果出现多个Topic按AppID粒度进行转发或阻断
方案2平台维护AppID#TopicList与集群绑定关系当请求的Topic集合为维护的子集时按照细粒度转发否则使用AppID粒度进行转发或阻断
5. **平台改造**
维护平台增加AppID#TopicName和AppID##GroupName与集群绑定关系
切换如果AppID下Topic维护了细粒度绑定关系切换时则不关联其他Topic未维护细粒度绑定关系的Topic切换时不关联出其他已经维护了细粒度绑定关系的Topic
#### 总结
**前提假设:** 1. Gateway版本与Broker版本一致 2. 明确了解用户客户端访问Topic范围
**局限性:** 不支持消费者采用正则模式的订阅方式
只有在平台管理员能够明确了解共享用户的使用情况下才可以使用这种兼容方案否则可能会导致客户端访问集群元数据混乱部分Topic访问失败的情况。平台做大之后平台管理员很难了解每一个用户的使用情况也许当下是规范的后续可能会产生使用交叉情况所以这个兼容方案制作临时使用长期优先在平台侧进行细粒度管控。
### Client端兼容方案一
通过在客户端增加client.id配置生成更细粒度的标识由服务器端进行识别转发
client.id 格式: HA#AppId#TopicName
1. 在Gateway和Broker的ZK中维护AppId#TopicName与集群的绑定关系
2. Gateway和Broker识别客户端ClientID以HA开头则此ClientID是一个细粒度灾备标识根据AppId#TopicName获取集群绑定关系,将请求转发到实际集群
---
**0.10.0.0 Protocol version**
METADATA V1满足正常使用
GROUP_COORDINATOR_REQUEST V0 10 FindCoordinatorRequest V1+增加key_type默认为0group
API_VERSIONS V0
Gateway为2.5版本如果客户端是2.5服务端是0.10客户端将以2.5版本协议进行发送