Mock实现
Service Discovery的Mock实现,代码在:
istio/pilot/pkg/serviceregistry/memory/discovery.go
NewDiscovery()
NewDiscovery()方法构建一个基于内存的ServiceDiscovery
func NewDiscovery(services map[model.Hostname]*model.Service, versions int) *ServiceDiscovery {
return &ServiceDiscovery{
services: services,
versions: versions,
}
}
ServiceDiscovery接口
ServiceDiscovery 是一个基于内存的discovery interface,实现了 model.ServiceDiscovery:
type ServiceDiscovery struct {
// 保存用于测试的服务信息
services map[model.Hostname]*model.Service
versions int
// 保存期望获得的代理服务实例
WantGetProxyServiceInstances []*model.ServiceInstance
// 各种预设的error,用于模拟出错的情况
ServicesError error
GetServiceError error
InstancesError error
GetProxyServiceInstancesError error
}
这个mock registry是用于测试目的。
先看看和服务发现直接相关的几个方法的实现:
// AddService 用来添加服务到registry
func (sd *ServiceDiscovery) AddService(name model.Hostname, svc *model.Service) {
// 保存在 services 字段中
sd.services[name] = svc
}
// Services 方法实现 discovery 接口,返回所有服务
func (sd *ServiceDiscovery) Services() ([]*model.Service, error) {
// 看看是否有预设的 ServicesError 错误
if sd.ServicesError != nil {
return nil, sd.ServicesError
}
out := make([]*model.Service, 0, len(sd.services))
// 简单的将 services 字段的内容返回
for _, service := range sd.services {
out = append(out, service)
}
return out, sd.ServicesError
}
// GetService 方法实现 discovery 接口,返回单个服务
func (sd *ServiceDiscovery) GetService(hostname model.Hostname) (*model.Service, error) {
// 看看是否有预设的 ServicesError 错误
if sd.GetServiceError != nil {
return nil, sd.GetServiceError
}
// 以hostname为key简单查询,返回值有可能为nil
val := sd.services[hostname]
return val, sd.GetServiceError
}
// InstancesByPort 方法实现 discovery 接口,返回服务实例
func (sd *ServiceDiscovery) InstancesByPort(hostname model.Hostname, num int,
labels model.LabelsCollection) ([]*model.ServiceInstance, error) {
// 看看是否有预设的 InstancesError 错误
if sd.InstancesError != nil {
return nil, sd.InstancesError
}
// 先检查有没有服务
service, ok := sd.services[hostname]
if !ok {
return nil, sd.InstancesError
}
out := make([]*model.ServiceInstance, 0)
// 如果服务类型是 external,则返回空列表
if service.External() {
return out, sd.InstancesError
}
// 按给定的端口在服务的 ServicePort 列表中查询
if port, ok := service.Ports.GetByPort(num); ok {
// 构建多个不同版本的的实例,版本数量有字段 versions 决定
for v := 0; v < sd.versions; v++ {
if labels.HasSubsetOf(map[string]string{"version": fmt.Sprintf("v%d", v)}) {
out = append(out, MakeInstance(service, port, v, "zone/region"))
}
}
}
return out, sd.InstancesError
}
和 Proxy 相关的方法实现:
// GetProxyServiceInstances 实现 discovery interface
func (sd *ServiceDiscovery) GetProxyServiceInstances(node *model.Proxy) ([]*model.ServiceInstance, error) {
// 看看是否有预设的错误
if sd.GetProxyServiceInstancesError != nil {
return nil, sd.GetProxyServiceInstancesError
}
if sd.WantGetProxyServiceInstances != nil {
return sd.WantGetProxyServiceInstances, nil
}
out := make([]*model.ServiceInstance, 0)
// 游历所有保存的服务
for _, service := range sd.services {
if !service.External() {
for v := 0; v < sd.versions; v++ {
// Only one IP for memory discovery?
// makeIP方法返回的IP地址要和node的IP匹配
if node.IPAddresses[0] == MakeIP(service, v) {
for _, port := range service.Ports {
out = append(out, MakeInstance(service, port, v, "zone/region"))
}
}
}
}
}
return out, sd.GetProxyServiceInstancesError
}
func (sd *ServiceDiscovery) GetProxyLocality(node *model.Proxy) string {
// not implemented
return ""
}