Sofa Consul Registry 的实现,介绍 consul 服务注册发现 API、数据模型、健康检查等设计。
/v1/agent/service/register
官方推荐使用 agent api 而不是 catalog api,保证应用直连 consul agent,不会经过负载均衡,确保 register 和 deregister 为同个 agent。
参数见数据结构定义。
/v1/agent/service/deregister/:service_id
service_id
见数据结构定义中的 Id
。
/v1/catalog/services
返回所有服务名和 metadata 信息,SOFA 不需要使用这个 API。
/v1/health/service/:service
因为 Consul 可以通过 agent 进行 health check 并标识服务的健康状态,所以这个 API 只会返回健康的实例(符合预期)。
service
见数据结构定义中的 Name
。
/v1/health/service/:service?index=:index&wait=300s&passing
Consul 通过 Blocking Queries 实现基于长轮训的 Watch 功能。在每次请求时都会返回 X-Consul-Index
标识当前资源的版本状态,之后的请求携带上对应值将会阻塞该请求。直到数据发生变更时(即 Index 发生变化时)或是超过了设置的最长阻塞时间,请求才会返回。
service
见数据结构定义中的 Name
。
Consul 注册一个服务的定义主要分为四部分:
- 服务的基本信息(name/id/host/port)
- 服务的元信息(meta/tags)
- 服务的健康检查信息(ttl/tcp/http)
- 一些配置信息
在此我们只关注前三者
Consul 中的字段 | 描述 | 在 SOFA 中的字段 | 默认值 | 是否允许用户配置 | 在其他注册中心的实现 |
---|---|---|---|---|---|
Id | 服务实例的唯一标识 | interfaceId + uniqueId + host + port | interfaceId + uniqueId + host + port | 否 | etcd: serviceName:protocol:uniqueId:uuid zk: bolt://192.168.1.100:22000?xxx=yyy nacos: 推测是通过 interfaceId + host + port + clusterName |
Name | 服务名 | interfaceId | interfaceId | 否 | 均为 interfaceId |
Address | 服务地址 | host | host | 否 | 均为 host |
Port | 服务端口 | port | port | 否 | 均为 port |
在 SOFA 中,interface id 是一个 java interface 的完整类名(例如 com.alipay.sofa.rpc.HelloService
),但是 Consul 不推荐 service name 中包含 .
,虽然 HTTP API 的服务注册发现能够使用,但是会造成 DNS 功能失效(因为 DNS 功能同样使用了 .
区分 tags),需要考虑几种场景:
- 用户的 Consul 只为 SOFA RPC 使用,且只使用 sofa-registry-consul,则 service name 可以使用类名,因为 HTTP API 不会受到影响
- 用户的 Consul 会注册其他服务,并使用一些其他组件(例如 Consul Template + Nginx),考虑
.
是否会破坏其他组件的功能,需要提供配置将.
转义成-
,或是只使用最后一截类名(例如HelloService
)作为 service name - 用户同时使用 Consul DNS 暴露 SOFA 服务,则同样不能出现
.
,方案同上。
Consul 的服务实例元信息提供了两个字段:Meta 和 Tags,前者为 KV 形式,后者为 List 形式(但是也可以通过 key=val
的方式拼接)。
目前看区别主要在于 Tags 可以用于在 Consul 侧进行过滤,而 Meta 只提供存储功能。
所以 unionId
字段可以注册到 tags 中,直接在 Consul 侧过滤所有符合实例,但是这不是必须的,拉取所有实例并通过 RegistryUtils#matchProviderInfos
可能更容易保证逻辑统一。
Meta 可以直接通过 RegistryUtils#convertProviderToMap
生成,和 nacos 实现保持统一。
Consul 主要提供了三种健康检查方式,TTL 心跳、服务端主动 TCP 探活和服务端主动 HTTP 探活。
- TTL 心跳是目前提供的方式,实现简单,但是心跳可能未必准确反映服务健康状态
- TCP 探活能至少保证服务暴露的端口可用,但是也无法反映出服务详细健康状态
- HTTP 心跳在使用 Web 应用(尤其是 Spring Boot Actuator 或是 SOFA Boot)时,可以实现类似 Readiness 功能,在这些场景下是首选。
个人倾向为三种方式均可通过配置项配置,默认采用第一种或是第二种方式。
TBD...