在一个分布式微服务系统里面,服务之间的调用会非常频繁和复杂,大规模集群服务会经常发生故障,应用的上下线也是常态。这时需要一个调度的"大脑"来给微服务指挥服务之间应该要如何做调用的。
EasyOps 名字服务(以下简称 ens)扮演了 EasyOps 平台中这个指挥的角色。本文会从系统架构、用户使用的角度介绍 EasyOps 的名字服务。
功能
ens 实现了以下功能:
- 服务注册
服务提供方需要向外提供服务的时候,会对外宣称自己提供的服务名和端口有哪些,启动的时候会自动把这个信息注册到名字服务里面,便于调用方能够发现这个服务。
在 EasyOps 平台里面,每个程序包里面的 package.conf.yaml 的描述文件里面会记录了这个程序包提供的服务
# 名字服务列表
service_list:
- name: logic.dc_console
port: 8087
- 服务路由
调用方需要知道被调方的地址时,通过 ens 提供的不同语言 sdk(c++, go, rust, py, java 等)获取被调服务的地址(ip+端口)。
- 负载均衡
当有多台主机提供相同的服务时,ens 会通过每台机器设置的权重来随机分配一个地址给到调用方。
- 自动容灾
当服务或者主机发生故障时,ens 会自动踢掉有问题主机提供的服务,实现自动容灾的功能。
系统架构
总体架构
总体的系统架构图如下:

- mongodb
mongodb 集群作为名字服务的中心存储,用于记录服务名与主机地址的对应关系。
- ens_root
缓存名字信息,分担 mongodb 压力。
- ens_client
在每台 EasyOps 服务端的主机都会装上 ens_client。
ens_client 会定时从 ens_root 同步名字信息下来。ens_client 提供缓存名字信息、服务节点发现功能。
此外, ens_client 还会定时上报主机心跳信息, 当心跳过期时,心跳过期的主机会被自动剔除。
- ens_sdk
缓存名字信息,提供不同语言的 sdk 给服务调用方使用。
高可用
ens_root, ens_client, ens_sdk 都会有自己的缓存。任何一点故障,不会影响服务的正常调用。
ens 管理
日常维护 EasyOps 平台时,我们经常需要管理名字服务。ens 提供了两个方法来对名字服务做读写管理。
控制台查看服务
访问页面 http://\${EasyOps 平台 IP}/admin/ens 我们会看到所有的服务所在的地址

命令行工具查看、新增、删除服务
查询名字下的 IP 端口 /usr/local/easyops/ens_client/tools/get_all_service.py 要查的名字
往名字里面注册 IP 端口 /usr/local/easyops/ens_client/tools/register_service.py 要注册的名字 要注册的端口 要注册的 IP(可选,默认本机 IP)
从名字里面删除 IP 端口 /usr/local/easyops/ens_client/tools/unregister_service.py 要注销的名字 要注销的端口 要注销的 IP(可选,默认本机 IP)
未来展望
名字服务过去在 EasyOps 平台中扮演了核心的角色,未来 ens2.0 将会在多方面做优化。
结合契约中心做更多优化,比如支持按契约名及契约版本路由,支持路由的优先级。
除了 ip, port 以外,支持记录服务/契约相关的更多字段,如 host,契约版本号等。
更灵敏的自动容灾。
结合 CMDB 做功能更强大的控制台管理功能。