服务发现是微服务架构中关键的组成部分,服务发现说白了就是客户端怎么找到服务端的地址(ip和端口),这个问题可以很简单也可以很复杂,这里主要介绍服务发现的大致原理。
下面通过大家接触最多的场景:访问网页的过程讲解服务发现。
网络通讯的前提条件
所有的网络应用,客户端和服务端通讯的前提条件就是客户端得知道服务端的ip地址和端口号,例如:你要访问一个网页,浏览器得知道网页服务器的ip和端口号是多少,才可以向网页服务器发送请求,最终取回网页内容进行展示。
dns服务发现
我们平时打开网页的时候,记住的是域名,不知道服务器ip和端口,但是浏览器通讯必须要服务器的ip地址和端口,这个时候浏览器会借助dns服务器,用域名作为请求参数,去dns服务器查询域名对应的ip地址,过程如下图。
通过域名去dns服务器查询服务器ip地址的过程就叫dns服务发现,就是通过dns服务器,发现了web服务的地址。
说明:通过dns服务器只能查询域名对应的ip地址,没有端口号,不过对于http协议默认端口就是80,https对应的是443,所以浏览器可以确定网页服务器的端口号。
dns服务注册
前面提到,我们可以使用域名作为参数去dns服务器,查询服务的地址,那么dns服务器怎么知道一个域名对应的ip地址是什么?
这里就需要我们事先向dns服务器注册域名和ip地址的对应关系;例如,我们配置dns的A记录,将www.tizi365.com 和 112.10.21.230 的对应关系,添加到dns服务器中。
向dns服务器配置域名和ip地址的过程,就是服务注册,就是注册了某种服务的意思(因为我们服务端的地址,往往代表某种服务)。
服务反注册,就是删除之前注册的服务信息。
前面通过dns介绍服务发现和服务注册,大家如果做过web开发配置过dns,都不会陌生;既然dns可以实现服务发现,直接使用传统的dns服务器就行,为什么还需要其他方案?
传统dns服务发现的缺陷:
-
延时,dns缓存导致服务地址变更,客户端没法及时拿到最新的地址。
-
不支持服务存活检查
-
不支持一对多的服务和地址映射关系,就是一个域名对应多个ip地址
-
不支持配置服务地址的端口配置
提示:传统的dns服务器,实现服务发现有缺陷,专门定制的dns服务器是可以解决上面提出的问题的。
基于配置文件的服务发现
既然服务发现的目的就是为了让客户端知道服务端的地址,前面的例子是因为人记不住ip地址,需要域名方便记忆,我们服务端内部的接口互相调用,不存在不好记忆的问题。
直接在配置文件中记录服务端的地址,客户端不就知道服务端地址了。 例子:
// 伪代码
// 用户服务,因为启动了3个用户服务实例,所以配置了3个服务地址
userservice=["192.168.101.1:3211","192.168.101.2:3121","192.168.101.3:3782"]
// 订单服务,启动了两个服务实例,因此有两个服务地址
orderservice = ["172.10.0.21:9810","172.10.0.22:9810"]
通过例子,我们知道集群规模较小而且服务实例比较稳定的时候,直接基于配置文件实现服务发现,简单有效,通过配置文件,我们可以直接读取服务的地址。
但是对于集群规模较大或者基于容器化部署以后,服务重启、新建、销毁是很频繁的,意味着,经常会出现服务地址失效、或者新增服务地址的情况,单纯靠手工维护ip列表是不现实的。
代理
基于代理的服务发现,例如:nginx,大家应该不陌生,我们只要记住nginx的地址,不需要知道nginx后面代理了多少个服务地址,也就是通过类似nginx的代理技术,可以间接的和服务通信。
基于代理技术的服务发现,对客户端来说很简单,只要记录一个统一的代理地址就行了,服务地址的变化,只要更新代理服务器的配置信息即可,但是服务地址变化,一般的代理工具都得人工维护配置信息,也无法做到自动更新位置信息,也得需要自己定制工具。
注册中心
基于注册中心的服务发现,就好比如存在一个地方,集中登记所有的服务地址信息,需要的时候去注册中心查询服务地址即可,注册中心提供了服务健康检查,发现服务异常了,就自动剔除掉对应的服务地址。
流程说明:
-
首先服务启动的时候,主动往注册中心,注册自己的服务名和地址信息。
-
客户端通过服务名,到注册中心查询服务的地址。
-
客户端通过地址连接服务,进行通信。
当然注册中心也支持,主动将变化的服务地址信息推送到客户端,客户端在本地就可以查询服务地址。
注册中心通常也支持服务健康检查,如果注册中心发现某个服务地址异常了,就会剔除无效的地址。