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

6.9 KiB
Raw Permalink Blame History

背景

目前灾备方案使用客户端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版本协议进行发送