3. nacos服务发现

本文讲解以下几个方面的内容:

1. nacos服务发现原理

2. spring cloud服务协作流程

3.搭建nacos服务端

4. 搭建nacos服务发现客户端

5. nacos服务发现的数据模型


一. nacos服务发现的原理

image

有两个微服务A和B, A调用B, 那么A是如何调用B的呢?我们可以通过http请求,进行调用. 也可以使用rpc进行调用.

不管使用什么方式, A需要知道B的地址和端口号. 那么A是如何知道B的地址和端口好的呢? 如上图:

1. B服务启动的时候, 会注册到服务发现中心, 告诉他,我的ip和端口号是什么?这里应该也是接口调用,通知服务发现中心的.

2. A服务启动的时候, 也会注册的服务发现中心, 告诉他, 我的ip和端口号是什么? 同时, 服务发现中心会告诉我, 当前已注册的服务的ip和端口号. 这里通过一个接口请求和参数返回就可以实现.

3. 拿到了B服务的ip和port, 接下来就可以调用服务B了.

二. spring cloud服务协作流程

我们要基于spring cloud生态环境进行开发. 所以,先来了解spring cloud的服务写作流程

image

前面注册和发现就都不说了, 上面说过了, 这里多了两个东西, 一个是Ribbon, 另一个是feign.

Ribbon是负载均衡器, Feign是远程调用, 自动进行http请求.

2.1 服务负载均衡 -- Ribbon

客户端Service A 要调用ServiceB的实例1和实例2. 那么到底调用ServiceB的哪个实例呢? 使用Ribbon负载均衡, 要看使用什么样的算法了, 可以使用轮询算法, 或者其他算法, 如加权算法

负载均衡有两种: 服务端负载均衡, 客户端负载均衡

  • 服务端负载均衡

在负载均衡中维护一个可用的服务实例清单, 当客户端请求来临时, 负载均衡服务器按照某种配置好的规则(负载均衡算法), 从可用服务实例清单中, 选取其一去处理客户端请求, 这就是服务端负载均衡, 例如Nginx. 通过nginx进行负载均衡, 客户端发送请求值Nginx, nginx通过负载均衡算法, 在多个服务器之间选择一个进行访问.

image
  • 客户端负载均衡

接下来, 我们要讲的ribbon, 就属于客户端负载均衡, 在ribbon客户端会有一个服务实例地址列表, 在发送请求前, 通过负载均衡算法, 选择一个服务实例, 然后进行访问, 这是客户端负载均衡. 即在客户端进行负载均衡算法分配.

image

服务的调用方, 我们就可以理解为是一个客户端.

负载均衡算法:

image

可通过下面的方式, 在spring boot配置中修改默认的负载均衡的策略

<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">account-service.ribbon.NFLoadBalanceRuleClassName=com.netflix.loadBalancer.RandomRule</pre>

其中: account-service: 是调用的服务的名称. 后面的组成部分是固定的.

2.2 服务间接口的调用---Feign

feign是服务端http接口的调用.

feign可以帮助我们更快捷, 优雅的调用httpApi. 原来我们在调用http请求的时候, 需要使用的是RestTemplate, 传输域名和端口号, 进行http调用. 使用feign后, 不用再使用RestTemplate模拟请求了, feign能够通过服务名, 找到对应的接口. 不需要我们在拼接地址+端口了, 提供了简单方便的操作.

使用方法:

  1\. 在Service B定义一个接口
image

2. 声明feign客户端

image

新建一个类, 声明为FeignClient类型的接口. 指定调用的服务名. 然后将指定接口. 这样在调用的时候, 就可以通过服务名, + 接口, 自动找到对应的项目接口了.

三. 搭建nacos服务端

这里上一节已经搭建过了(地址: https://www.cnblogs.com/ITPower/articles/12630193.html), 在服务的最后, 我们搭建了nacos的集群

四. 搭建nacos服务发现客户端

因为对于服务发现来说, 有很多配置都是公用的, 因此, 我们搭建一个父工程, 将通用的配置都添加到里面取.

4.1 搭建父工程.

创建一个maven工厂, 引入jar包即可. pom文件如下

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;"><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lxl.www</groupId>
    <artifactId>parent-discovery</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 这是一个父类工程, 所以, 需要设置打包类型为pom -->
    <packaging>pom</packaging>

    <properties>
        <project.build.sourceEncodding>UTF-8</project.build.sourceEncodding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- 这里我们使用的是alibaba的spring cloud -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>

</project></pre>

4.2 创建一个服务提供者, 也就是生产者.

在父工程下创建一个子工程. 我们要做一下三件事

1. 修改pom文件, 引入服务发现, feign, 和spring boot web

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;"><dependencies>
        <!-- 引入服务发现的包 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- 定义接口访问, 引入spring boot web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 服务之间http调用, 引入feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies></pre>

2. 添加application.yml配置文件

指定服务端口号, nacos服务的地址

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">server:
  port: 56010 spring:
  application:** name: productor
 cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848** **#nacos的服务器地址**
logging:
  level:
    root: info
    org.springframework: info</pre>

3. 定义一个启动类, 用来启动spring boot新项目

需要增加两个引入. 一个启用服务发现, 另一个是启用feign

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">package com.lxl.www.nacos;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

import javax.swing.*;

**@SpringBootApplication** **// 引入服务发现
@EnableDiscoveryClient
// 使用feign接口调用
@EnableFeignClients** public class ProductorApplication { public static void main(String[] args) {
        SpringApplication.run(ProductorApplication.class, args);
    }
}</pre>

4. 定义一个controller, 写一个接口

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">package com.lxl.www.nacos.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/productor") public class ProductorController {

    @GetMapping("/service") public String service() {
        System.out.println("provider invoke"); return "provider invoke";
    }

}</pre>

5. 启动程序, 在nacos中查看服务注册列表

image

最终项目结构如下:

4.3 创建一个服务消费者.

其中前3步骤和创建服务生产者是一样的

在父工程下创建一个子工程. 我们要做一下三件事

1. 修改pom文件, 引入服务发现, feign, 和spring boot web

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;"><dependencies>
        <!-- 引入服务发现的包 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- 定义接口访问, 引入spring boot web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 服务之间http调用, 引入feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies></pre>

2. 添加application.yml配置文件

指定服务端口号, nacos服务的地址

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">server:
  port: 56010 spring:
 application: 
    **name: consumer**

  cloud:
   ** nacos:
      discovery:
        server****-addr: 127.0.0.1:8848** **#nacos的服务器地址**
logging:
  level:
    root: info
    org.springframework: info</pre>

3. 定义一个启动类, 用来启动spring boot新项目

需要增加两个引入. 1个启用服务发现, 另一个是启用feign

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">package com.lxl.www.nacos;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients; **@SpringBootApplication** **// 引入服务发现
@EnableDiscoveryClient
// 使用feign接口调用
@EnableFeignClients** public class CustomerApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomerApplication.class, args); } }</pre>

4. productor生产者远程代理定义

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">package com.lxl.www.nacos.feign.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "productor") public interface ProductorFeign {

    @GetMapping("/productor/service")
    String service();

}</pre>

5. 通过feign调用productor的的接口

<pre style="color: rgb(0, 0, 0); font-family: &quot;Courier New&quot;; font-size: 12px; margin: 5px 8px; padding: 5px;">package com.lxl.www.nacos.controller;

import com.lxl.www.nacos.feign.client.ProductorFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/") public class ConsumerController {
    @Autowired private ProductorFeign productorFeign;

    @GetMapping("consumer") public String cunsumer() {
        String service = productorFeign.service();
        System.out.println(service); return service;
    }

}</pre>

6. 启动服务, 查看nacos客户端, 并调用接口测试

image

nacos生产上已经注册发现了两题服务

同时调用接口, 可以获取到productor返回的内容.

4.4 spring cloud的默认负载均衡方式--轮询

我们可以通过启动多个服务的方式, 来测试服务的负载均衡策略.

1. 修改productor的启动端口号为动态端口号. 目的是方便启动的时候动态配置端口号, 启动集群

image

** 2. 修改配置, 添加动态端口号**

image
image

vm options配置中设置动态端口号为-Dport=56010, 56011. 点击复制按钮, 可以增加一个应用, 然后配置参数后, 启动两个应用.

3. 在nacos控制台查看启动效果

image

我们看到, nacos的productor 有两台服务实例. 点击详情可查看具体的服务实例信息:

image

4. 调用consumer的接口, 访问productor, 默认采用轮询的负载均衡算法

  http://localhost:56020/consumer

五. nacos服务发现的数据模型

nacos的注册发现是一种三层模型: 即 服务--集群--实例.如下图:

image

nacos最外层是服务. 最里层是多台实例. 多个实例之间组成一个服务集群.

5.1 命名空间

命名空间不仅适用于配置管理, 同样适用于服务发现. namespace的常用场景之一是不同环境的配置隔离.如: 开发, 生成, 测试环境资源的隔离.

productor启动了两个实例, 点击详情进去可以看到他是一个集群. 集群里有两台实例.

5.2 服务.

  在命名空间下, 有各个服务.比如我们上面定义的是在public命名空间下, 定义了两个服务. 一个是productor, 一个是consumer.

服务有服务名实例. ****远程调用的时候, 需要指定服务名.

5.3 实例

实例是基于网络协议通讯, 所以必须要有一个ip:端口号

5.4 元信息

在及群里点击某一个实例-->编辑, 可以看到如下页面, 可以设置元信息

image

那么元信息是什么呢? 每台服务器都可能会设置自己的个性化的信息. 这就是每台服务器的元数据信息

5.5 实操---指定集群的命名空间为dev

image

只需要在配置中增加命名空间就可以了.

我们也可以修改集群的名字, 集群的默认名字是DEFAULT. 我们这里将其修改为default. 在控制台dev命名空间下, 可以看到启动了服务customer.

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

推荐阅读更多精彩内容