Spring Cloud Alibaba之服务发现组件 - Nacos

[TOC]


服务发现

为了实现多个微服务之间的调用,我们除了需要Feign这种调用组件外还得依赖服务发现组件。主要的原因是每个微服务所在的机器ip并非总是固定的,并且每个微服务都可能部署多个实例在不同的机器上,所以我们不能把依赖的微服务ip地址写在代码或配置文件里,我们需要有个组件去动态的管理,这就是为什么微服务架构里服务发现功能是必须的。

那么服务发现组件是怎么实现服务发现的呢?我们以大家比较熟悉的MySQL来做类比,通过MySQL简单说明一下服务发现机制的实现。如下图:


image.png

简单说明一下什么是服务提供者与服务消费者:

  • 服务提供者:服务的被调用方(即:为其他微服务提供接口的微服务)
  • 服务消费者:服务的调用方(即:调用其他微服务接口的微服务)
  • 例如:订单服务需要调用用户服务的接口,那么订单服务就是服务消费者,而用户服务则是服务提供者
  • 服务提供者与服务消费者实际描述的是微服务之间的调用关系,一般都是成对出现的

当微服务启动的时候会向服务发现组件注册自身信息,在上图中就类似于向MySQL发送一条insert语句,将服务的元数据如服务名称、ip地址及服务状态等信息插入到MySQL中,如上图的registry表数据所示,这个过程称之为服务注册,所以服务发现组件内部会都维护类似于这样的一张注册表。

微服务在注册完成后,会读取服务发现组件中保存的其他微服务的元数据并缓存一份到本地,就类似于向MySQL发送一条select all语句。这样在调用其他服务的时候,就不需要每次都去服务发现组件上查询,而是从本地缓存去查找调用地址,这样可以减轻服务发现组件的压力。所以上图中的调用箭头并没有指向服务发现组件,而是直接指向服务提供者。这样的好处是哪怕是服务发现组件挂掉了,还能从本地缓存中获取其他微服务的调用地址。到这一步微服务之间就可以互相发现了,即完成基本的服务发现

但微服务有可能会挂掉或下线,此时其他服务不应该去发现一个不存在的服务。所以每个服务启动且向服务发现组件注册完成之后,都会通过心跳机制告知存活状态。上图中用last_heartbeat字段表示,若某个服务在超过一定的时间都没有发送心跳包的话,就会被服务发现组件检测到,此时就会删除注册表里该服务的注册信息,并通知其他服务更新本地缓存(若有新注册的服务也会通知其他服务更新本地缓存)。


搭建Nacos Server

关于什么是Nacos,官方文档已经描述得很详细了,Nacos官方文档地址如下:

https://nacos.io/zh-cn/docs/what-is-nacos.html

所以这里只是简单概述一下,Nacos与Eureka一样,是服务发现组件,同时也是配置中心。Nacos解决了两个问题,一是服务A如何找到服务B;二是管理微服务的配置,让一个微服务的所有实例的配置都统一,并且可以实现配置修改后自动刷新等。

理论介绍也说得差不多了,本小节我们来动手搭建一个Nacos Server。过程很简单首先需要下载一个Nacos,下载地址如下:

https://github.com/alibaba/nacos/releases

然后我们需要选择一个合适的版本下载,即Nacos Server版本应尽量与Client端的版本对应。至于Client的版本我们可以到工程的pom.xml文件中找到Spring Cloud Alibaba的依赖管理项点击进去即可查看到:


image.png

如下可以看到Nacos Client的版本为1.0.0,所以与之对应选择1.0.0版本的Nacos Server进行下载:


image.png

注:我这里使用的Spring Cloud版本是Greenwich.SR1,Spring Cloud Alibaba的版本是0.9.0.RELEASE

由于不是生产环境所用,无需严格选择对应的版本,所以我这里选择下载最新的1.1.0版本:


image.png

下载并解压后进入bin目录,双击startup.cmd,或在命令行中输入cmd startup.cmd即可运行Nacos Server:


image.png

启动成功:


image.png

使用浏览器访问localhost:8848进入Nacos Server的管理页面,此时需要输入账户密码,默认的账户密码都是nacos:

image.png

登录成功后,页面如下:


image.png

该管理页面支持中英文,可在右上角点击切换:


image.png

官方文档如下:

https://nacos.io/zh-cn/docs/quick-start.html


将微服务注册到Nacos

在上一小节中,我们已经完成了Nacos Server的搭建,而这一小节将演示如何将微服务注册到Nacos。我现在有一个用户中心微服务,其pom.xml文件如下,包含了Spring Cloud Alibaba及Nacos Client依赖,Spring Boot版本为2.1.6.RELEASE:

<dependencies>
    ...
    
    <!-- Nacos Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <!--整合Spring Cloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--整合Spring Cloud Alibaba-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.9.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

在配置文件中配置一下nacos server的地址及端口:

spring:
  cloud:
    nacos:
      discovery:
        # 指定nacos server的地址
        server-addr: 127.0.0.1:8848
  application:
    # 服务名称
    name: user-center
  
  ...  

配置完成后启动项目,然后到nacos server的管理页面的服务列表上查看是否注册成功,注册成功的话会显示在服务列表里,如下:


image.png

点击详情可以看到详细信息:


image.png

经过以上这几个步骤,就可以非常简单地整合Nacos Client,并将微服务注册到Nacos Server上。通过同样的步骤,我将另一个内容中心微服务也注册到Nacos Server上。我们来写一个简单的测试用例,看看在内容中心上是否能发现用户中心,代码如下:

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class DiscoveryClientTests {

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 测试服务发现,证明内容中心能找到用户中心
     */
    @Test
    public void getServiceInstancesTest(){
        // 获取用户中心微服务的所有实例信息
        List<ServiceInstance> instances = discoveryClient.getInstances("user-center");
        // 以json格式打印出来
        log.info(JsonUtil.obj2JsonPretty(instances));
    }
}

控制台输出的json信息如下,证明通过服务发现组件能让内容中心总是能找到用户中心:

[ {
  "serviceId" : "user-center",
  "host" : "192.168.190.1",
  "port" : 8080,
  "secure" : false,
  "metadata" : {
    "nacos.instanceId" : "192.168.190.1#8080#DEFAULT#DEFAULT_GROUP@@user-center",
    "nacos.weight" : "1.0",
    "nacos.cluster" : "DEFAULT",
    "nacos.healthy" : "true",
    "preserved.register.source" : "SPRING_CLOUD"
  },
  "uri" : "http://192.168.190.1:8080",
  "scheme" : null,
  "instanceId" : null
} ]

Nacos服务发现的领域模型

下图整理了Nacos服务发现的领域模型,我们将围绕该图进行介绍:


image.png

1、上图最外层的是Namespace,对应管理界面的命名空间,如下:

image.png

Namespace主要用作隔离,默认为public,例如我们有三个环境:开发、测试及生产环境,那么就可以创建三个Namespace,不同的Namespace之间是互相隔离的。

举个例子,我们可以来创建一个开发环境专用的命名空间:


image.png

创建完成后可以看到每个命名空间都会有自己的唯一命名空间id:


image.png

那么微服务要如何注册到指定的命名空间呢?很简单,在配置文件中通过namespace配置项指定即可:

spring:
  cloud:
    nacos:
      discovery:
        # 指定nacos server的地址
        server-addr: 127.0.0.1:8848
        # 配置命名空间
        namespace: 4a557407-c2c8-4524-97a0-17aa3c836407
        
  ...      

配置完成后重启项目,此时该服务不再是注册到之前的public命名空间,而是注册到我们刚刚创建的dev命名空间,此时在dev下的微服务是看不到public下的微服务的,即实现了环境隔离了:


image.png

2、在Namespace之下是Group服务分组,默认的Group是DEFAULT_GROUP。我们可以在服务列表中看到:

image.png

Group可以将不同的微服务划分到同一个分组里,Group可以让我们方便去分组管理微服务。但需要注意的是,在目前的Spring Cloud Alibaba版本,并没有用上这个Group,应该会在未来的版本上支持。


3、而Group下面是Service,Service既是微服务,例如用户微服务、订单微服务等。每个Service可以包含多个Cluster(集群),Cluster是对指定微服务的一个虚拟划分,默认为DEFAULT。比方说公司内有北京机房、上海机房的服务器,那么为了异地容灾,用户中心微服务就可能会被同时部署在北京机房和上海机房。这时候我们就可以为北京机房的用户中心微服务实例划分到一个集群里并且起一个集群名称,而上海机房的用户中心微服务实例同理。将微服务实例划分到一个集群后,我们还可以实现类似于让上海机房里的微服务尽量调用同机房内的其他微服务,这样在容灾的同时还可以提升性能。

关于集群我们可以直接在配置文件中配置,而不用像命名空间那样需要提前创建,如下:

spring:
  cloud:
    nacos:
      discovery:
        # 指定nacos server的地址
        server-addr: 127.0.0.1:8848
        # 配置集群名称,名称可以任意
        cluster-name: BJ
        
  ...      

配置完成后重启项目,此时可以看到该微服务实例处于BJ集群下,而不是处于之前默认的DEFAULT集群下:


image.png

4、Cluster里是Instance,即上面所提到的微服务实例

关于这些概念的官方文档地址如下:

https://nacos.io/zh-cn/docs/concepts.html


Nacos元数据

什么是Nacos元数据,官方文档描述如下:

Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。

  • 服务级别的元信息在服务详情中展示
  • 集群的元信息在集群配置中展示
  • 实例的元信息在集群实例表内展示

元数据作用:

  • 提供描述信息
  • 让微服务调用更灵活
    • 例如实现微服务的版本控制;当有多个版本的微服务共存时就可以通过元数据进行版本控制

配置元数据的两种方式:

  1. 在Nacos Server的管理页面设置;以服务的元数据示例,在服务详情页面点击编辑服务后,在元数据这栏输入json格式的元数据即可:


    image.png
  1. 通过配置文件指定;如下示例:
spring:
  cloud:
    nacos:
      discovery:
        # 指定nacos server的地址
        server-addr: 127.0.0.1:8848
        # 这种方式配置的是实例级别的元数据
        metadata:
          # k-v形式,k和v都可以自定义
          instance: c
          test: a
          version: v1

配置完成后重启项目,可以看到配置文件中所配置的实例级别的元数据:


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容