首批通过分布式安全可靠测评,为关键业务系统打造
连接管理
更新时间:2025-08-07 18:01:40
针对一个客户端的物理连接,ODP 维持自身到后端多个 OBServer 节点的连接,采用基于版本号的增量同步方案维持每个 OBServer 节点的连接在同一状态,保证了客户端高效访问各个 OBServer 节点。连接管理的另外一个功能是连接保持,在 OBServer 节点宕机/升级/重启时,客户端与 ODP 的连接不会断开,ODP 可以迅速切换到健康的 OBServer 节点上,对应用透明。
创建连接
ODP 的 Session 分为两类:Client Session 和 Server Session。Client Session 指的是客户端与 ODP 之间建立的连接;Server Session 指的是 ODP 与 OBServer 节点之间创建的连接。当 ODP 向 OBServer 节点转发客户端请求时,如果与 OBServer 节点之间没有创建连接,则需要初始化一个 Session 实例。
创建 Session 时需要做认证操作,ODP 无法决定该 Session 将来要访问哪些 OBServer,所以认证过程中,ODP 只能任意选择一个 OBServer 节点进行认证,将客户端发送的认证数据包转发给 OBServer 节点,并将 OBServer 节点返回的结果转发给客户端,同时将客户端认证的数据包都缓存在 Client Session 内部,以便 ODP 与其它 OBServer 节点建立该 Client Session 关联的 Server Session 时,将这些认证数据包发送给 OBServer 节点,便于与 OBServer 节点顺利进行认证。
存储连接
每当客户端向 ODP 发送请求,需要根据客户端连接信息查询获取 Client Session。在非连接池模式下,Server Session 不能脱离 Client Session 独立存在,只有根据 Client Session 来查询其关联的 Server Session,或者查询某个 Server Session 是否是与某个 Client Session 关联。
ODP 接收到客户端 SQL 请求时,会通过查询 partition table cache 来获取到 OBServer 节点的地址,然后查询 Client Session 保存的 Server Session 有没有与该 OBServer 节点关联的 Server Session 存在,如果存在则使用该 Server Session,如果不存在,则与该 OBServer 节点创建连接,并将 Server Session 加入 Client Session 关联的 Server Session 存储结构中。
事务状态维护
在默认配置或非分布式事务模式下,ODP 以事务绑定 Client Session 与 Server Session。事务的第一条语句到达 ODP 时,ODP 选择一个 Server Session 并绑定到 Client Session 上,后续该事务中的所有请求均通过此 Server Session 转发至 OBServer,禁止切换 Server Session。因此,ODP 需在 Client Session 中记录事务状态以维持绑定关系。
在非分布式事务模式下,维护事务状态的主要目的是保证事务中不切换 Server Session。 具体来说:
如果在事务中,OBServer 宕机,ODP 需要感知节点状态并将未完结的事务结束掉。因为 MySQL 协议没有超时机制,ODP 必须主动通知客户端事务终止。
OBServer 节点未实现事务同步,暂不支持事务迁移功能。事务只能由初始 OBServer 处理,换节点会导致失败。因此,在 ODP 做主备切换时,必须确保进行中的事务完成,或返回特殊错误以通知客户端终止事务。
另一个目的是在 ODP 升级时,通过 Kill 旧 ODP 停止服务前,需等待所有事务完结,以最小化用户影响。
若开启分布式事务路由(配置项 enable_ob_protocol_v2=true 且 enable_transaction_internal_routing=true),则事务内允许切换 Server Session。 此模式下,ODP 会根据 SQL 涉及的分区位置动态选择最优 OBServer 节点,实现事务内跨节点路由。此时,事务状态维护的目的转向确保路由一致性和故障恢复:ODP 仍需记录事务状态以处理节点宕机或主备切换,但由于支持跨节点路由,事务迁移限制部分缓解,ODP 可通过内部机制协调多节点事务。
在事务开启时,记录事务开启状态到 Client Session,事务结束时将该事务状态重置。判断事务结束的依据是:
如果使用 Autocommit,每个请求需解析 OBServer 返回包,数据转发完成后立即重置事务状态。
如果是长事务,仅在 Commit/Rollback 请求后解析返回包来判断事务结束。
连接变量管理
Client Session 需要记录客户端在该 Session 上所有设置过的变量,每次修改一个变量,在 Client Session 中记下修改时间。当 ODP 选择一个 Server Session 转发请求时,首先检查该 Server Session 上 Session 变量的修改时间是否大于 Client Session 中记录的修改时间。若小于,则意味着该 Session 没有使用最新的 Session 变量。ODP 会先重置该 Server Session 上的所有 Session 变量,批量将当前 Client Session 中保存的 Session 变量设置到该 Server Session 上后,再通过该 Server Session 转发请求;反之,则直接通过 Server Session 转发。
对于一些常见的 Session 变量,如:autocommit 等,客户端可能频繁设置,所以不能使用根据 modify time 来决定是否批量重置,而是每个 Server Session 存储这些常见 Session 变量的值,每次请求都对比 Client Session 中的变量值与 Server Session 中的变量值是否一致,不一致则重新设置这些变量值。
闪断避免
闪断避免指的是 ODP 与 OBServer 节点的 Server Session 异常不会被客户端感知,客户端与 ODP 之间的 Client Session 正常,客户端能够正常的读写数据。需要处理 Server Session 异常的情况如下:
OBServer 节点发生 Leader 切换,ODP 还没有获取到新的 Leader。这种情况主要由 OBServer 节点来处理,Leader 切换一定要保证将正在处理的事务都完成,ODP 只是尽力保证将请求发送给数据所在的 OBServer 节点,OBServer 节点发生了 Leader 切换,那么即使数据不在该 OBServer 节点上,该节点也需要负责处理该请求,并把结果返回给 ODP。
OBServer 节点发生宕机,那么 ODP 与该 OBServer 节点的连接就会断开。如果该 Server Session 正在处理事务中,那么 ODP 需要发送一个错误响应给客户端;如果该 Server Session 处于空闲状态,只需将该 Server Session 从其对应的 Client Session 中标记删除即可。新的请求将不再使用该 Server Session 转发请求。
ODP 与 OBServer 节点通信超时,MySQL 协议本没有超时机制,但 OBServer 节点有超时机制,所以 OBserver 节点超时会通知 ODP,ODP 将错误通知给客户端。如果 OBServer 节点发现 Server Session 长时间不活动,也会 Kill 该 Session,这种情况的处理参考第 2 项的处理方式。
ODP 与 OBServer 节点之间的网络连接断开或发生网络分区,这种情况处理参考第 2 项,即使发生网络分区,如果 Server Session 上有事务正在执行,OBServer 在一段时间后终止该 Session,所以 ODP 在 Server Session 断开一段时间后,给客户端报错,结束未完成的事务,避免 Session 长时间被挂住。
ODP 升级,新启动的 ODP 将负责客户端发起的新 Session,旧 ODP 上的 Session 数量会越来越少,当旧 ODP 上的 Session 数量低于某个阈值时,需要将旧 ODP 上的 Session 全部都终止掉(当然要保证正在处理的事务完成,长事务需要等一段时间,超时仍然没有完成也只能强制 Kill 掉),然后停止旧 ODP。这个过程无法完全避免客户端连接闪断。
ODP 宕机,这种情况下,ODP 上的连接都会断掉,可能很快 ODP 被重新启动,或者该 ODP 负责的连接被其它的 ODP 处理,闪断无法避免。
使用 ODP 能够避免大部分异常情况下的连接闪断,特别是在 OBServer 节点发生 Leader 切换、主备集群切换、ODP 升级等后端维护的情况下,能保持客户端连接正常,对客户端的影响比较小。
Kill Session 处理
MySQL 协议没有超时机制,但 MySQL 会 Kill 长时间不活跃的 Session,如果客户端一直等不到服务端的响应,会一直等待,遇到这种挂住的情况,一般 DBA 会介入,调用 MySQL 的 Kill Session 命令将 Session 关闭。
OBServer 节点有超时机制,一般情况下,无论是服务端宕机,还是网络分区,或者 obproxy 与服务端的连接断开,obproxy 都能够通知 Client Session 事务处理失败。但如果超时时间设置得过长,或者 obproxy 处理有遗漏,Client Session 确实挂住了,那么应用就会要求做 Kill Session 操作。obproxy 需要能够对 Kill Session 做特殊处理,不仅要处理 obproxy 上记录的 Client Session 状态,还需要通知 OBServer关闭 Server Session。