Consul实现
pilot discovery 的 Consul 实现。
Controller的定义
Consul实现非常简单,一个 consul 的 client,一个monitor用来监听。
type Controller struct {
client *api.Client
monitor Monitor
}
Discovery的实现
Services() 很简单,用 consul 的 client 获取所有服务,然后做一次格式转换即可:
func (c *Controller) Services() ([]*model.Service, error) {
data, err := c.getServices()
services := make([]*model.Service, 0, len(data))
for name := range data {
endpoints, err := c.getCatalogService(name, nil)
services = append(services, convertService(endpoints))
}
return services, nil
}
convertService()方法的细节,可以稍后研究一下,主要是对照一下 consul 的服务模型和 Pilot 的服务模型。
GetService()方法也是如此,调用 consul client 的 getCatalogService()方法获取数据,然后转一下格式:
func (c *Controller) GetService(hostname model.Hostname) (*model.Service, error) {
name, err := parseHostname(hostname)
endpoints, err := c.getCatalogService(name, nil)
return convertService(endpoints), nil
}
InstancesByPort() 方法,也是类似:
func (c *Controller) InstancesByPort(hostname model.Hostname, port int,
labels model.LabelsCollection) ([]*model.ServiceInstance, error) {
name, err := parseHostname(hostname)
endpoints, err := c.getCatalogService(name, nil)
instances := []*model.ServiceInstance{}
for _, endpoint := range endpoints {
instance := convertInstance(endpoint)
if labels.HasSubsetOf(instance.Labels) && portMatch(instance, port) {
instances = append(instances, instance)
}
}
return instances, nil
}
GetProxyServiceInstances()方法就有点惨,consul client 没有提供现成的方法,因此不得不先获取全量的service,然后逐个比对IP地址:
func (c *Controller) GetProxyServiceInstances(node *model.Proxy) ([]*model.ServiceInstance, error) {
// 获取全量的service
data, err := c.getServices()
out := make([]*model.ServiceInstance, 0)
// 对每个service
for svcName := range data {
// 都获取该服务的服务实例信息
endpoints, err := c.getCatalogService(svcName, nil)
// 然后对每一个服务实例
for _, endpoint := range endpoints {
addr := endpoint.ServiceAddress
if len(node.IPAddresses) > 0 {
// 都比对一下IP地址
for _, ipAddress := range node.IPAddresses {
if ipAddress == addr {
out = append(out, convertInstance(endpoint))
break
}
}
}
}
}
return out, nil
}