【02】Nacos-服务注册中心

1. Nacos注册中心简介

1.1 背景分析

  • 在微服务中,首先需要面对的问题就是如何查找服务(软件即服务),其次,就是如何在不同的服务之间进行通信。如何更好更方便的管理应用中的每一个服务,如何建立各个服务之间联系的纽带,由此注册中心诞生(例如淘宝网卖家提供服务,买家调用服务)。
  • 市面上常用的注册中心有Zookeeper(雅虎Apache)、Eureka(Netfix)、Nacos(Alibaba)、Consul(Google)。
  • 下面我们选择Nacos进行学习,Nacos它很好的支持了阿里的双11活动,不仅可以做注册中心,还可以作为配置中心,稳定性和性能都很好。

1.2 Nacos概述

  • Nacos (DynamicNaming and Configuration Service)是一个应用于服务注册与发现、配置管理的平台。它孵化与阿里巴巴,成长于十年双十一的洪峰考研,沉淀了简单易用,稳定可靠,性能卓越的核心竞争力。这里是它的官网地址
  • 一个更易构建云原生应用的服务发现(Nacos Discovery)、服务配置(Nacos Config)和服务管理的平台;
  • Nacos的关键特性:
    • 服务发现和服务健康检测;
    • 动态配置服务;
    • 动态DNS服务;
    • 服务及其元数据管理;

1.3 Nacos注册中心

  • 管理所有微服务,解决微服务之间调用关系的错综复杂、难以维护的问题。
    注册中心的演变

1.4 核心功能

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

1.5 主流的注册中心

  • C:一致性、A:可用性、P:分区容错性
    注册中心比对

2. 构建Nacos服务

2.1 下载与安装

第一步:Nacos下载,可在浏览器直接输入如下地址:

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

单机模式官方文档

第二步:选择对应的版本,直接下载,如图所示:
1
第三步:解压Nacos(不要解压到中文目录下),其目录结构如下:
1

2.2 初始化配置

第一步:找到conf/nacos-mysql.sql文件里的sql脚本,然后登录mysql,然后基于脚本文件中的描述,创建数据库(名字nacos_config,编码方式utf8mb4),并执行脚本文件,脚本执行成功之后会创建一些表,如图所示。
1
说明:在执行此文件时,要求mysql的版本大于5.7版本以上(MariaDB最好是10.5.11),否则会出现如下错误。
1
第二步:打开conf/application.properties的这个文件,并基于当前环境配置要连接的数据库。(假如前面有#,要将其去掉)

### If use MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&serverTimezone=UTC&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user.0=root
db.password.0=root

2.3 服务启动与访问

第一步:启动Nacos服务。
Windows启动命令(standalone代表着单机模式运行,非集群模式):

startup.cmd -m standalone

1
说明:
1)执行命令时,要么配置环境变量,要么直接在nacos/bin目录下通过cmd命令窗口执行。
2)nacos启动时需要本地环境变量中配置JAVA_HOME(对应jdk的安装目录)。
第二步:访问Nacos服务。
打开浏览器,输入http://localhost:8848/nacos地址,出现如下登录页面:
1
其中,默认账号:nacos,默认密码:nacos。

3. 服务注册与调用入门

3.1 业务描述

创建两个项目Module分别为服务提供者和服务消费者,两者都要注册到NacosServer中(这个本质上就是一个web服务,默认端口为8848),然后服务提供者可以为服务消费者提供远端调用服务(例如,支付服务是服务提供方,订单服务为服务消费方),如图所示。
1

3.2 创建项目父工程

  • 第一步:创建父工程 springcloud-demo,此工程为我们后续项目模块的父工程,这个工程的作用就是来管理子模块中所需要的共性依赖。
  • 第二步:导入需要的核心依赖,其pom文件的内容如下:
<?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>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>springcloud-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-demo</name>
    <description>父工程</description>
    <packaging>pom</packaging>
    
    <!--声明集成的子模块-->
   <modules>
        <module>StockService</module>
        <module>OrderService</module>
    </modules>

	<!--全局版本管理-->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring.cloud-version>Hoxton.SR8</spring.cloud-version>
        <spring.cloud.alibaba-version>2.2.5.RELEASE</spring.cloud.alibaba-version>
    </properties>

	 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <!--依赖管理-->
    <dependencyManagement>
        <dependencies>
       		 <!--spring cloud依赖,此依赖需要springboot的支持,依赖中定义了spring cloud微服务规范-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud-version}</version>
                <!--import表示此工程下的子工程可以直接引用这个依赖中的版本-->
                 <scope>import</scope>
                 <!--当scope为import时,这里的类型必须为pom类型-->
                <type>pom</type>
            </dependency>
            
            <!--spring cloud alibaba依赖,此依赖基于spring cloud,当前依赖中使基于微服务规范做了具体的实现-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
	<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

  • 其中的版本可以参考如下网址(涉及到一个兼容性问题,不能随意指定其版本)。

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

  • 最后,父工程资源初始化完成之后,将src目录删除,因为父工程只负责依赖管理。

3.3 服务提供者创建及注册

  • 第一步:创建服务提供者继承父工程,其module名为StockService。
  • 第二步:添加项目依赖。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>springcloud-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/>
    </parent>

    <artifactId>StockService</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>StockService</name>
    <description>StockService</description>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Nacos-服务注册与发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>
  • 第三步:创建并修改配置文件application.yml,实现服务注册。
server:
  port: 8082
  servlet:
    context-path: /stock
    
spring:
  application:
    name: StockService #服务名称
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        username: nacos
        password: nacos

  • 第四步:定义处理请求的控制层方法
@RestController
@RequestMapping("/stockapi")
public class StockController {

    @Value("${server.port}")
    private String port;

    @RequestMapping("/handle")
    public String getStock() {
        System.out.println("删减库存");
        return "端口:"+port+"-->库存减一";
    }
}

服务提供者

3.4 服务消费者的发现及调用

  • 第一步:创建服务消费者继承父工程,module名为OrderService。
  • 第二步:添加项目依赖。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>springcloud-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/>
    </parent>

    <artifactId>OrderService</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>OrderService</name>
    <description>OrderService</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Nacos-服务注册与发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>
  • 第三步:修改配置文件application.yml。
server:
  port: 8081
  servlet:
    context-path: /order

spring:
  application:
    name: OrderService
  cloud:
    loadbalancer: #开启ribbon的负载均衡
      ribbon:
        enabled: true
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        username: nacos
        password: naocs
  • 第四步:创建启动类并实现服务消费。
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    //构建RestTemplate对象,基于此对象访问远程服务
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder){
        builder.setConnectTimeout(Duration.ofSeconds(100));
        builder.setReadTimeout(Duration.ofSeconds(100));
        return builder.build();
    }

    //构建负载均衡的RestTemplate对象
    @Bean
    @LoadBalanced
    public RestTemplate loadBalancedRestTemplate(){
        return new RestTemplate();
    }
  }
 	@RestController
 	@RequestMapping("/consumer")
    public class ConsumerController{

        @Autowired
        private RestTemplate restTemplate;

		//具有负载均衡功能的RestTemplate对象
        @Autowired
        private RestTemplate loadBalancedRestTemplate;

        /**
         负载均衡客户端对象:
         基于此对象可以从注册中心获取服务实例
         */
        @Autowired
        private LoadBalancerClient loadBalancerClient;

        @GetMapping("/doRestEcho1")
        public String doRestEcho1(){
            /**
             * 说明:
               基于RestTemplate进行远程服务调用,但是不具备负载均衡特性,这种方式不需要nacos,
               是直接通过固定的ip和端口进行服务调用的,此方式不适合多服务实例调用。
             */
            String url ="http://localhost:8082/stock/stockapi/handle";
            //远程调用
            //String.class是调用服务响应数据类型
            return restTemplate.getForObject(url, String.class);
        }

        @GetMapping("/doRestEcho2")
        public String doRestEcho2(){
            /**
             * 说明:
               基于负载均衡的RestTemplate进行远程服务调用,但是在调用之前基于loadBalancedClient对象去从nacos注册中心基于服务名查找
               服务实例(可能有多个),此时会在本地按照一定算法去选择服务实例,然后进行服务调用。
             */

            //基于服务名(nacos中服务表中的名字)查找服务实例
            ServiceInstance choose = loadBalancerClient.choose("StockService");
            String ip = choose.getHost();//获取ip地址
            int port = choose.getPort();//获取端口号
            //构建远程调用的url
            String url = "http://"+ip+":"+port+"/stock/stockapi/handle";
            //远程调用-RPC
            return loadBalancedRestTemplate.getForObject(url, String.class);
        }

        @GetMapping("/doRestEcho3")
        public String doRestEcho3(){
        	//可以直接使用提供服务的服务名称来直接请求
            String url = "http://StockService/stock/stockapi/handle";
            return loadBalancedRestTemplate.getForObject(url , String.class);
        }
    }
}

消费者

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值