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



    4.0.0

    net.zhi365
    nacosdiscover
    pom
    1.0

    
        service-provider
    

    
        UTF-8
        UTF-8
        1.8
    

    
        
            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                2.1.2.RELEASE
                pom
                import
            

            
                org.springframework.cloud
                spring-cloud-dependencies
                Greenwich.RELEASE
                pom
                import
            

            
                org.springframework.boot
                spring-boot-dependencies
                2.1.6.RELEASE
                pom
                import
            
        
    

    
        
            
                org.springframework.boot
                
                
                spring-boot-maven-plugin
            
        
    

(2) ServiceProvider(服务生产者)

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

pom.xml



    
        nacosdiscover
        net.zhi365
        1.0
    
    4.0.0

    service-provider

    
        
            org.springframework.boot
            spring-boot-starter-web
        
    

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



    
        nacosdiscover
        net.zhi365
        1.0
    
    4.0.0

    spring-rest-consumer-bootstrap

    
        
            org.springframework.boot
            spring-boot-starter-web
        
    

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服务发现快速入门

你可能感兴趣的:(Nacos服务发现-一、概览)