你如果想和你所有的朋友失去联系, 最简单的办法就是换个电话号码, 然后不通知任何人.
在微服务架构中也一样, 如果一方换了 IP 地址, 其他 service 就找不到它了.
Service discovery 的作用, 就是帮忙在网络中寻找 service .
为什么需要 service discovery
如果网站的架构都是在物理主机的基础上搭建的, 那么配置, IP 地址, 在多数时候都是相对稳定不变的.
但如果 app 在云端, 因为 service 会经历重启, 崩溃, 伸缩, 所以很多 service 都是使用动态的 IP. 那么手动再来配置每台服务器就不方便了.
Service discovery 的组成
它由 3 部分组成:
service registry, 维护一个列表, 存储各个 service 的位置信息
service provider 提供服务. 服务开始时把自己 register 到 registry 上. 服务断线时 de-register .
service consumer 使用其他服务. 它需要从 registry 获取其他服务的位置
Service discovery 的设计
其实我们需要做的就是维护一个 service name -> [server IPs] 的 hash table. 注意这里使用的是 server IPs 集合, 因为一个 service 可能由很多太 server 提供.
当需要获取一个 service IP 时, 直接从数组中随机选择一个即可.
这样的话, 用一个 redis 都可以实现一个简单的 service discovery.
但这里有以下一些复杂的情况要考虑:
service 掉线时, 多半不能 de-register . 那么 service discovery 如何知道它掉线了? 现在的解决方案是, service discovery 会时不时对 service 做 health check , 比如每 5 秒一次. 如果 service 无法连接, 那么就 de-register
consumer 是不是每次查询其他 service 都要向询问 register? 为了减小 register 的压力, consumer 可以维护一份本地的 provider 位置信息
在 2) 的基础上, 如果 provider 信息变了, 如何通知 consumer? 其实实现方法挺多的. 1) 如果 consumer 主动更新自己, 那么 consumer 可以时不时和 registry 同步信息, 比如每 1 分钟一个. 这样 registry 压力还是挺大. 也可以是只有当 consumer 发现, 使用本地提供的信息仍然无法连接 provider 时才向 registry 同步信息. 这更像是一个 cache 的设计. 2) 如果 provider 主动更新 consumer, 那么可以使用 pub-sub 模式. 设计一个 message queue, 所有 consumer 监听这个 queue.provider 位置信息变化时发一个 message,consumer 收到后更新自己. 不过这样, 每个 consumer 需要多一个 thread 来 listen to queue
如何避免 registry 的 single point of failure? 使用分布式系统来实现 registry , 比如 zookeeper / etcd / consul
另一种实现方法, 是使用 client-side discovery , 从客户端的角度实现 discovery. 每一个客户端都有一份 provider 的位置信息, 由客户端来实现 load balance .Airbnb 的 SmartStack 和 Netflix 的 Eureka 就类似这个思路. 这个方法有利有弊吧.
来源: http://www.tuicool.com/articles/rYzqiqM