服务发现是指使用一个注册中心来记录分布式系统中的全部服务的信息,以便其他服务能够快速的找到这些已注册的服务.服务发现是支撑大规模 SOA 和微服务架构的核心模块,它应该尽量做到高可用.
目的
让消费者查找服务(定位服务),进而访问服务(使用服务).
实现
硬编码和配置文件 -> DNS -> 注册中心
高可用
分布式架构来保证高可用性
分布式数据一致性
CAP 定理
BASE 理论
一致性模型
服务注册中心
功能
- 服务注册, 生产者注册服务名称/IP地址/端口号/元数据到注册中心
- 服务查找, 消费者根据服务名称在注册中心查找服务地址和状态
- 服务健康检查, 注册中心通过心跳探测提供者的健康,把不健康的剔除
- 服务变更通知, 消费者通过推/拉的方式,从注册中心获得生产者的消息
解决方案
解决方案 | CAP | 协议 |
---|---|---|
ZooKeeper | CP | Zab |
Eureka | AP | 未公布 |
etcd | CP | Raft |
Consul | AP | Raft |
例子
微服务架构 go-micro 的注册中心组件
接口
haha@st /mnt/i/github.com/ms/go-micro (mymc1) $ go doc registry.Registry
type Registry interface {
Init(...Option) error
Options() Options
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}
The registry provides an interface for service discovery and an abstraction
over varying implementations {consul, etcd, zookeeper, ...}
func NewRegistry(opts ...Option) Registry
- 服务注册, Register()
- 服务查找, GetService()
- 服务健康检查,ListServices()
- 服务变更通知, Watch()
consul 是默认实现
haha@st /mnt/i/github.com/ms/go-micro (mymc1) $ go doc -u consul.consulRegistry
type consulRegistry struct {
Address string
Client *consul.Client
opts registry.Options
// connect enabled
connect bool
queryOptions *consul.QueryOptions
sync.Mutex
register map[string]uint64
// lastChecked tracks when a node was last checked as existing in Consul
lastChecked map[string]time.Time
}
func (c *consulRegistry) Deregister(s *registry.Service) error
func (c *consulRegistry) GetService(name string) ([]*registry.Service, error)
func (c *consulRegistry) Init(opts ...registry.Option) error
func (c *consulRegistry) ListServices() ([]*registry.Service, error)
func (c *consulRegistry) Options() registry.Options
func (c *consulRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error
func (c *consulRegistry) String() string
func (c *consulRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error)
etcdv3 以插件方式提供
haha@st /mnt/i/github.com/ms/go-plugins (mymp1) $ go doc -u etcdv3.etcdv3Registry
type etcdv3Registry struct {
client *clientv3.Client
options registry.Options
sync.Mutex
register map[string]uint64
leases map[string]clientv3.LeaseID
}
func (e *etcdv3Registry) Deregister(s *registry.Service) error
func (e *etcdv3Registry) GetService(name string) ([]*registry.Service, error)
func (e *etcdv3Registry) Init(opts ...registry.Option) error
func (e *etcdv3Registry) ListServices() ([]*registry.Service, error)
func (e *etcdv3Registry) Options() registry.Options
func (e *etcdv3Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error
func (e *etcdv3Registry) String() string
func (e *etcdv3Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error)