Nacos服务发现-一、概览

上一篇 Nacos服务发现-零、导学

1.1 从单体架构到微服务

1.1.1 单体架构

Web应用程序发展的早期,大部分web工程师将所有的功能模块打包到一起并放在一个Web容器中运行,所有功能模块使用同一个数据库,同时,它还提供API或者UI访问的Web模块等。

3201048542,3330451989.jpg

尽管也是模块化逻辑,但是最终还是会打包并部署为单体式应用,这种将所有功能部署在一个Web容器中运行的系统就叫做单体架构(也称:巨石型应用)

优点:

  • 开发效率高:模块之间交互采用本地方法调用,并节省微服务之间的交互讨论时间与开发成本。
  • 容易测试:IDE都是为开发单个应用设计的、容易测试---在本地就可以启动完整的系统。
  • 容易部署:运维成本小,直接打包为一个完整的包,拷贝到Web容器的某个目录下即可运行。

但是,上述的好处是有条件的,它适用于小型简单应用,对于大规模的复杂应用,就会展现出来以下的不足:

缺点:

  • 复杂性逐渐变高,可维护性逐渐变差 :所有业务模块部署在一起,复杂度越来越高,修改时牵一发动全身。
  • 版本迭代速度逐渐变慢:修改一个地方就要将整个应用全部编译、部署、启动时间过长、回归测试周期过长。
  • 阻碍技术创新:若更新技术框架,除非你愿意将系统全部重写,无法实现部分技术更新。
  • 无法按需伸缩:通过冗余部署完整应用的方式来实现水平扩展,无法针对某业务按需伸缩。

1.1.2 微服务

许多大型公司,通过采用微服务架构解决了上述问题。其思路不是开发一个巨大的单体式的应用,而是将应用分解为小的、互相连接的微服务。

一个微服务一般完成某个特定的功能,比如订单服务、用户服务等等。每一个微服务都是完整应用,都有自己的业务逻辑和数据库。一些微服务还会发布API给其它微服务和应用客户端使用。

比如,根据前面描述系统可能的分解如下:

image-20210109180611020.png

每一个业务模块都使用独立的服务完成,这种微服务架构模式也影响了应用和数据库之间的关系,不像传统多个业务模块共享一个数据库,微服务架构每个服务都有自己的数据库。

优点:

  • 分而治之,职责单一;易于开发、理解和维护、方便团队的拆分和管理
  • 可伸缩;能够单独的对指定的服务进行伸缩
  • 局部容易修改,容易替换,容易部署,有利于持续集成和快速迭代
  • 不会受限于任何技术栈

1.2 什么是服务发现

在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标。这样在我们的代码中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为了完成一次请求,消费方需要知道服务生产方的网络位置(IP地址和端口号)。

我们的代码可以通过读取配置文件的方式读取服务生产方网络位置,如下:

image-20210114224629773.png

我们通过Spring Boot技术很容易实现:

(1) 新建Maven项目

父工程pom.xml

<?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>net.zhi365</groupId>
    <artifactId>nacosdiscover</artifactId>
    <packaging>pom</packaging>
    <version>1.0</version>

    <modules>
        <module>service-provider</module>
    </modules>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.2.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.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <!--    这个问题太坑了,是boot-maven中间那个【-】的问题,重新输入就好用了 -->
                <!--<artifactId>spring-boot‐maven-plugin</artifactId>-->
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

(2) ServiceProvider(服务生产者)

ServiceProvider是服务的生产方,暴露/service服务地址,实现代码如下:

pom.xml

<?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">
    <parent>
        <artifactId>nacosdiscover</artifactId>
        <groupId>net.zhi365</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>service-provider</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

ServiceProviderApplication.java

/**
 * @author Xin.li
 * @date 2021-01-14 23:38
 */
@SpringBootApplication
public class ServiceProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
}

ServiceController.java

package net.zhi365.serviceprovider.web;

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

/**
 * @author Xin.li
 * @date 2021-01-14 23:44
 */
@RestController
public class ServiceController {

    @GetMapping( value = "/service")
    public String service() {
        return "provider invoke";
    }
}

application.yml

server:
  port: 56010

(3) Service A(服务消费者)

实现代码:

pom.xml

<?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">
    <parent>
        <artifactId>nacosdiscover</artifactId>
        <groupId>net.zhi365</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-rest-consumer-bootstrap</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

SpringRestConsumerBootStrapApplication.java

package net.zhi365.springrestconsumerbootstrap;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author Xin.li
 * @date 2021-01-15 0:03
 */
@SpringBootApplication
public class SpringRestConsumerBootStrapApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringRestConsumerBootStrapApplication.class, args);
    }
}

ConsumerController.java

package net.zhi365.springrestconsumerbootstrap.web;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author Xin.li
 * @date 2021-01-15 0:08
 */
@RestController
public class ConsumerController {

    @Value("${provider.address}")
    private String providerAddress;

    @GetMapping(value = "/service")
    public String service(){
        RestTemplate restTemplate = new RestTemplate();
        //  调用服务
        String providerResult = restTemplate.getForObject("http://" + providerAddress +"/service", String.class );

        return "consumer invoke | " + providerResult;
    }
}

application.yml

server:
  port: 56020
  # 服务生产方地址
provider:
  address: 127.0.0.1:56010

看上去很完美,但是,仔细考虑以下,此方案对于微服务应用而言行不通。

首先,微服务可能是部署在云环境的,服务实例的网络位置或许是动态分配的。另外,每一个服务一般会有多个实例来做负载均衡,由于宕机或升级,服务实例网络地址会经常动态改变。再者,每一个服务也可能应对临时访问压力增加新的服务节点。

如下图所示:

image-20210115001646505.png

基于以上的问题,服务之间如何相互感知?服务如何管理?这就是服务发现的问题了。如下图:

image-20210114233006747.png

上图中服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端。

(1)在每个服务启动时会向服务发现中心上报自己的网络位置。这样,在服务发现中心内部会形成一个服务注册表,服务注册表是服务发现的核心部分,是包含所有服务实例的网络地址的数据库。

(2)服务发现客户端会定期从服务发现中心同步服务注册表 ,并缓存在客户端。

(3)当需要对某服务进行请求时,服务实例通过该注册表,定位目标服务网络地址。若目标服务存在多个网络地址,则使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。

总结一下,在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中心来获取访问目标服务的网络地址,从而实现服务发现的机制。

下一篇 Nacos服务发现-二、Nacos服务发现快速入门

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

推荐阅读更多精彩内容