分布式Horde下GenServer创建注册与API调用的延迟问题咨询
Horde 0.8.3分布式Elixir应用的实际部署问题
部署场景与现象
采用0.8.3版本的Horde为Elixir应用构建分布式注册表与分布式监督树体系,核心实现逻辑如下:
- 以GenServer为基础实现
UserAgent(简称UA)模块,每个UA实例代表一个接入应用的用户 - 通过
Horde.DynamicSupervisor.start_child(MyApi.DSup, {MyApi.UserAgent, user})启动UA实例 - 在创建UA的同一函数逻辑中,调用UA的客户端接口
UserAgent.ping(ua_id);该ping方法会通过via_tuple从注册表中查找对应UA的pid,再向其发送:ping消息
应用部署在N1、N2两个节点上后出现如下异常:
当start_child(...)与ping(...)的执行逻辑均在N1运行、而目标UA实际被调度创建在N2上时,绝大多数场景下调用ping(...)都无法在Horde注册表中找到该UA。经实测,新建的UA需要约150ms到350ms(平均250ms)才能在Horde注册表中达到全集群可见状态,该延迟来自Horde基于deltaCRDT实现的后台异步数据同步机制。
待确认的核心问题
- 应用运行在单台物理服务器上(无跨节点网络延迟),配备12核CPU且注册表为空时,平均250ms的同步延迟是否属于正常水平?还是需要进一步排查是否存在配置或使用层面的问题?
- 我原本认为
Horde.DynamicSupervisor.start_child(...)是同步调用——即待全集群的注册表数据同步完成后才会返回,因为Horde官方声称其行为与标准库的DynamicSupervisor保持一致。这一认知是否正确?有没有办法实现跨节点注册的同步确认? - 我目前实现了如下带等待重试逻辑的
get_pid(id, ...)方法来获取UA的pid,这种方案是否合理?
def get_pid(_id, _wait, waited, max_wait) when waited > max_wait, do: :error def get_pid(id, wait, waited, max_wait) do Logger.debug("get_pid(#{id}, wait=#{wait}, waited=#{waited}, max_wait=#{max_wait})") case Horde.Registry.lookup(via_tuple(id)) do {pid, _} -> Logger.debug("\t-> got pid=#{inspect(pid)}") pid [] -> Logger.debug("\t-> got []. Going for a nap for #{wait}ms") Process.sleep(wait) get_pid(id, wait * 2, waited + wait, max_wait) end end
内容的提问来源于stack exchange,提问作者mszmurlo
相关产品推荐
相关产品推荐

