目录

二、Nacos 简介

三、Nacos注册中心演变及其设计思想

四、Nacos核心功能

五、Nacos的下载与安装

1.各种注册中心比较:

2.Nacos服务端部署

2.Nacos客户端服务环境搭建

2.1 创建基于Nacos的服务提供者

 创建基于Nacos的服务消费者

5、服务注册中心对比

SpringCloudAlibaba学习文档

  • 官网文档:
  • 英文文档:
  • https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html
  • 中文文档:

二、Nacos 简介

       Nacos是Naming Service(服务注册中心) 和 Configuration Service(配置中心)的 缩写。

       官方:一个更易于构建云原生应用的动态服务发现(Nacos DKcovery )、服务配置(Nacos Contig)和服务管理平台。

      服务发现是微服务架构体系中最关键的组件之一。如果尝试着用手动的方式来给每一个客户端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于服务的动态扩缩容。Nacos Discovery Starter可以松助您将服务自动注册到Nacos服务端,并且能够动态感知和刚新某个服务实例的服务列表。除此之外,Nacos Discovery Starter 也将服务实例自身的一些元数据信息-例如host,port,健康检查URL,主页等-注册到Nacos 。Nacos的获取和启动方式可以参考Nacos官网。    
       简单来说:就是 集注册中心+配置中心+服务管理平台 的组合 即 Nacos = Eureka+Config+Bus
       Nacos的关键特性包括:

  • 服务发现和服务健康监测
  • 动态配置服务
  • 动态 DNS服务
  • 服务及其元数据管理 。


三、Nacos注册中心演变及其设计思想

分布式架构的远程服务式调用

String url = "http://localhost:8010/order/findOrderByuserId/"+id;
ResponseEntity<List> responseEntity m restTemplate.getForEntity(url,List.class);
List<order> orderList = responseEntity.getBody();

 问题发现: 

       分布式架构的 远程服务式调用 的弊端,当发生服务的迁移或者是服务的扩容, 此时需要手动修改远程服务地址。并进行代码的重新编译和部署。

解决方案:

       使用注册表,将所有的远程服务地址全部放到注册表中。每个远程服务地址存一个对应的服务名称,会员服务则会通过订单服务名称 ,查出订单服务的地址进行调用。

 问题发现: 

       如果订单服务进行水平扩展进行扩容,则需要对其服务进行维护管理,将扩容的服务IP:PORT也存入到列表中,但存在问题是困难,需要手动将扩容的进行维护。

解决方案:

       使用负载均衡器 Ngnix ,将所有的远程服务地址全部放到Ngnix中。

 问题发现: 

       如果使用 Ngnix ,如果某个服务挂掉,则Ngix没有进行服务实时监控和检查的功能,因此无法发现挂掉的服务,且成百上千个的服务地址都配置在这个Nginx中,需要频繁的修改和配置远程服务地址,手动配置容易出错,因此对于运维人员服务是灾难性的。

解决方案:

       使用服务注册中心,在会员启动时候调用注册接口执行 insert ,注册到 mysql 中,每次会员调用订单服务前都会去获取订单服务列表,就是去 mysql 中执行 select。而订单服务启动的时候也会调用注册接口执行 insert ,注册到 mysql 中。

 问题发现: 

       如果订单服务进行水平扩展,如果其中某台服务挂掉, 则此注册中心不会通知,会员服务仍然会调用此服务。

解决方案:

       改善服务注册中心,引入心跳机制,服务会在本地维护一个定时任务,每隔5秒发送一次心跳,如果超过5秒没有收到心跳,则认为当前服务已经是挂掉,将状态修改为 stop 状态。如果超过30秒没有收到服务心跳,则会将服务从注册表中清除。

       订单服务维护一个定时任务,会定时调用心跳接口发送心跳,进行和注册中心保持联系,如果服务停止了,则会调用注销接口,将服务停掉。

       在会员服务也维护一个定时任务,会定时调用心跳接口发送心跳,进行和注册中心保持联系,如果服务停止了,则会调用注销接口,将服务停掉。

       但会员服务同时也维护另一个定时任务,会定时拉取订单服务列表,然后缓存到客户端,然后通过负载均衡器进行远程调用。

四、Nacos核心功能

  • 服务注册:Nacos Client 会通过发送 REST 请求的方式向 Nacos Server 注册自己的服务,提供自身的元数据,比如 Ip 址、端口等信息。Nacos Server 接收到注册请求后,就会把这些元数据信息存在一个双层的内存 Map 中。
  • 服务心跳:Nacos Client 在服务注册后,会维护一个定时心跳来持续通知 Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。
  • 服务同步:Nacos Server 集群之间会互相同步服务实例,用来保证服务信息的一致性。leader  raft 
  • 服务发现:服务消费者(Nacos Client )在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面主册的服务清单,并且缓存在  Nacos Client  本地,同时会在 Nacos Client  本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存
  • 服务健康检查:Nacos Server 会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户心跳的的实例会将它的 healthy属性设置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册)

五、Nacos的下载与安装

1.各种注册中心比较:

   CAP:C  一致性      A  可用性      P 分区容错性

     Nacos注册中心的使用需要用到注册中心服务端客户端。

2.Nacos服务端部署

  • 第一步:下载安装包

        SpringCloud Alibaba Nacos下载地址:https://github.com/alibaba/nacos/releases
        官网文档:https://nacos.io/zh-cn/index.html

        进入官网,选择合适版本,此处选用最新版本的前一个版本1.4.3稳定版本

  • 第二步:进行安装修改启动脚本

        下载后安装到哪里解压到哪里,解压nacos后,进入bin目录修改startup.cmd。新版本的nacos默认是以cluster集群方式启动,此时会报错,需要修改startup.cmd的启动方式,修改如下地方。 

       如需修改各种nacos的各种配置,则进入application.properties修改。如果是单机模式下,则直接默认使用的是内存,如果是集群模式,则可以使用数据源。一般windows中默认使用单机模式。

  • 第三步:启动Nacos服务端

       双击运行startup.cmd启动nacos服务端。

  • 第四步:访问管理平台

       nacos注册服务中心管理可以通过管理平台查看和配置。启动后访问如下:

      管理平台:http://192.168.56.21:8848/nacos/index.html#/login

      用户名:nacos

      密    码:nacos

2.Nacos客户端服务环境搭建

2.1 创建基于Nacos的服务提供者

  •  新建两个服务提供者和一个服务消费者模块,分别为:    

       cloudalibaba-product-server9001

       cloudalibaba-product-server9002

       cloudalibaba-order-server9000

  • 引入服务提供者和服务消费者依赖

服务提供者依赖

服务消费者依赖

<dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
</dependencies>

编写配置文件

server:
  port: 9999
 
spring:
  application:
    #应用名称(nacos会将该名称当做服务名称)
    name: nacos-payment-provider
  cloud:
    #将来要将服务注册到哪个服务中心
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址
 
# springboot actuator 监控
management:
  endpoints:
    web:
      exposure:
        include: '*'
server:
  port: 9998
 
spring:
  application:
    #应用名称(nacos会将该名称当做服务名称)
    name: nacos-payment-provider
  cloud:
    #将来要将服务注册到哪个服务中心
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址
 
# springboot actuator 监控
management:
  endpoints:
    web:
      exposure:
        include: '*'
  •  生产者主启动类 

@SpringBootApplication
@EnableDiscoveryClient //服务注册与发现
public class PaymentMain9999 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9999.class,args);
    }
}



@SpringBootApplication
@EnableDiscoveryClient //服务注册与发现
public class PaymentMain9998 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9998.class,args);
    }
}
  • 编写业务类

@RestController
public class PaymentController {
 
    @Value("${server.port}")
    private String serverPort;
 
    @GetMapping("/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Integer id){
 
        return "nacos registry,serverPort:"+serverPort+"\t"+id;
    }
 
}

 创建基于Nacos的服务消费者

  • 新建服务消费者模块

       cloudalibaba-consumer-nacos-order83      

  • 引入依赖

       这里消费者远程调用提供者运用OpenFegin进行远程调用,所以引入了OpenFegin的依赖。

<dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
</dependencies>
  • 消费者启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderNacosMain83 {
    public static void main(String[] args) {
        SpringApplication.run(OrderNacosMain83.class,args);
    }

}
  • 编写消费者配置文件
server:
  port: 83
 
 
spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  • 编写消费者远程调用接口
@Component
@FeignClient(value = "nacos-payment-provider")
public interface PaymentOpenService {
 
    @GetMapping("/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Integer id);
}
  • 编写消费者业务类
@RestController
public class PayMentController {
    @Autowired
    private PaymentOpenService paymentOpenService;
 
    @GetMapping("/consumer/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Integer id){
        return paymentOpenService.getPayment(id);
    }
}

启动两个提供者和消费者,查看都已注册进nacos 

 发现调用成功,因为openfegin默认支持ribbon 所以发现进行了轮询。

到此服务注册和发现成功!!!

5、服务注册中心对比

nacos全景图

 nacos和cap

      Nacos 支持AP和CP模式的切换
 
     C是所有节点在同一时间看到的数据是一致的;而A的定义是所有的请求都会收到响应。
 
      何时选择使用何种模式?
      一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如 Spring cloud 和 Dubbo 服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。
 
      如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须,K8S服务和DNS服务则适用于CP模式。
      CP模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
 

第十六章:Spring Cloud Alibaba 基础环境搭建

第十八章:Nacos注册中心详解-入门案例及服务通信

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐