Nacos服务调用图解

本文详细介绍了Nacos服务的搭建,包括环境配置、下载安装、初始化配置和启动访问。讨论了Nacos作为服务注册与发现平台的角色,以及服务调用的案例,包括生产者和消费者的创建、注册与调用。此外,文章还涵盖了服务负载均衡的设计与实现,以及面试中可能涉及的Nacos相关问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 Nacos

nacos概述

 构建Nacos服务

下载与安装 

初始化配置

服务启动与访问

 常见报错

        MySQL的版本问题

        Nacos服务启动问题

服务注册与调用入门

生产者服务创建及注册

 消费者服务发现及调用

 服务负载均衡设计及实现

面试分析

微服务项目结构分析​

服务调用案例分析​

服务调用方案图解​



  •  Nacos

  • nacos概述

        Nacos(DynamicNaming and Configuration Service)是一个应用于服务注册与发现、配置管理的平台。它孵化于阿里巴巴,成长于十年双十一的洪峰考验,沉淀了简单易用、稳定可靠、性能卓越的核心竞争力.官网地址:https://nacos.io/zh-cn/docs/quick-start.html

  •  构建Nacos服务

  1. 检查环境变量(JAVA_HOME)
  2. 确保Mysql版本为5.7以上(MariaDB 10.5以上)
  • 下载与安装 

  1. Nacos下载

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

2. 解压Nacos(注意:不要出现中文目录)

  • 初始化配置

  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&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
    db.user.0=root
    db.password.0=root
  2. 登录mysql,执行:source d:/nacos-mysql.sql

  • 服务启动与访问

  1. 启动Nacos服务

  • Linux/Unix/Mac启动命令(standalone代表着单机模式运行,非集群模式):

        ./startup.sh -m standalone

  • Windows启动命令(standalone代表着单机模式运行,非集群模式):

        startup.cmd -m standalone

说明:

1)执行执行令时要么配置环境变量,要么直接在nacos/bin目录下去执行.
2)nacos启动时需要本地环境变量中配置了JAVA_HOME(对应jdk的安装目录),
3)一定要确保你连接的数据库(nacos_config)是存在的.
4)假如所有的配置都正确,还连不上,检查一下你有几个数据库(mysql,…)

2.访问Nacos服务

打开浏览器,输入http://localhost:8848/nacos地址,出现如下登陆页面:

其中,默认账号密码为nacos/nacos.

  •  常见报错

        MySQL的版本问题

当我们在执行一些SQL脚本时(例如 nacos-mysql.sql文件),假如出现如下错误,请升级你的mysql(建议mysql5.7以上或MariaDB 10.5.11)

        Nacos服务启动问题

问题1:

问题2:

  • 服务注册与调用入门

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

  • 生产者服务创建及注册

  1. 创建服务提供者工程(module名为sca-provider),继承parent工程(01-sca),其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>01-sca</artifactId>
            <groupId>com.jt</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>sca-provider</artifactId>
        <dependencies>
            <!--Web服务-->
            <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>

    2.创建并修改配置文件application.yml(或者application.properties),实现服务注册,关键代码如下:

    server:
       port: 8081
    spring:
      application:
        name: sca-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848

    注意:服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则。

3.创建启动类,并定义处理请求的控制层对象和方法,关键代码如下:

package com.cy;

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScaProviderApplication.class, args);
    }

    /**定义Controller对象(这个对象在spring mvc中给他的定义是handler),
     * 基于此对象处理客户端的请求*/
    @RestController
    public class ProviderController{
        //@Value默认读取项目配置文件中配置的内容
        //8080为没有读到server.port的值时,给定的默认值
        @Value("${server.port:8080}")
        private String server;
        //http://localhost:8081/provider/echo/tedu
        @GetMapping("/provider/echo/{msg}")
        public String doRestEcho1(@PathVariable String msg){
            return server+" say hello "+msg;
        }
    }
  }

 4.启动启动类,然后刷先nacos服务,检测是否服务注册成功,如图所示:

5.打开浏览器,输入http://localhost:8081/provider/echo/msa,然后进行访问。 

  •  消费者服务发现及调用

1.创建服务消费者(module名为sca-consumer),继承parent工程(01-sca),其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>01-sca</artifactId>
        <groupId>com.jt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>sca-consumer</artifactId>
    
   <dependencies>
    <!--Web服务-->
    <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>

2.修改配置文件application.yml,关键代码如下:

server:
  port: 8090
spring:
  application:
    name: sca-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #从哪里去查找服务

 3.创建启动类并实现服务消费,关键代码如下:

package com.cy;
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    @RestController
    public class ConsumerController{

        @Value("${spring.application.name}")
        private String appName;
        @Autowired
        private RestTemplate restTemplate;
        @GetMapping("/consumer/doRestEcho1")
        public String doRestEcho01(){
            String url = "http://localhost:8081/provider/echo/"+appName;
            System.out.println("request url:"+url);
           return restTemplate.getForObject(url, String.class);
        }
    }
}

 4.动消费者服务,并在浏览器输入http://localhost:8090/consumer/doRestEcho1地址进行访问,假如访问成功会出现,如图所示效果:

  •  服务负载均衡设计及实现

 1.手动写负载均衡

        配置启动多个启动类,修改并发运行选项:

 

修改sca-provider的配置文件端口,分别以8081,8082端口方式进行启动。

server:
  port: 8081
spring:
  application:
    name: sca-provider
  cloud:
    nacos:
      server-addr: localhost:8848
 @GetMapping("/consumer/echo/{msg}")
        public String doRestEcho1(@PathVariable String msg) {
            //手动自己写负载均衡(随机调用服务列表中的服务对象)
            //调用谁? sca-provider中的一个url
            String url1 = "http://localhost:8081/provider/echo/"+msg;
            String url2 = "http://localhost:8080/provider/echo/"+msg;
            String url3 = "http://localhost:8082/provider/echo/"+msg;
            String urls[] = new String[]{url1,url2,url3};
            //随机获取一个小于urls数组长度的整数
            int n = new Random().nextInt(urls.length);//手动式的负载均衡
            //如何调用?
            return restTemplate.getForObject(urls[n],String.class);
//            return server + "Say hello" + msg;
        }

 启动sca-consumer项目模块,打开浏览器,输入如下网址进行反复服务访问:

http://localhost:8090/consumer/echo/tedu

然后会发现sca-provider的两个服务都可以处理sca-consumer的请求.

2.基于loadBalancerClient方式获取服务实例

    @Bean
    @LoadBalanced//这个注解在描述RestTemplate对象时,系统底层会对RestTemplate对象的请求进行拦截
    public RestTemplate loadBalanceRestTemplate(){
        return new RestTemplate();
    }

 @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    @LoadBalanced//这个注解在描述RestTemplate对象时,系统底层会对RestTemplate对象的请求进行拦截
    public RestTemplate loadBalanceRestTemplate(){
        return new RestTemplate();
    }

    @RestController
    public class ConsumerController{

        @Autowired
        private RestTemplate restTemplate;

        /**
         * @Autowired注解描述属性时,会告诉spring框架,要优先按照属性类型进行对象的查找和注入,假如
         * 此类型的对象存在多个,此时还会按照属性名进行查找和对比,有相同的直接注入(DI),没有相同则报错
         * 也可以在属性山添加@Qualifier("bean的名字")注解,指定要注入的具体对象
         * */

        @Autowired
        private RestTemplate loadBalanceRestTemplate;

        //负载均衡客服端对象(基于此对象可以从nacos中获取服务列表,并且可以基于一定的算法从列表获取一个服务实例)
        @Autowired
        private LoadBalancerClient loadBalancerClient;

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




            //负载均衡方式调用
            @GetMapping("/consumer/echo2/{msg}")
            public String doRestEcho2(@PathVariable String msg){
            //基于loadBalancerClient方式获取服务实例
            String serviceId = "sca-provider";//这个名字要在nacos的服务列表中
            ServiceInstance choose = loadBalancerClient.choose(serviceId);
            String ip = choose.getHost();
            int port = choose.getPort();
//            String url = "http://" + ip + ":" + port + "/provider/echo/"+msg;
            String url = String.format("http://%s:%s/provider/echo/%s",ip,port,msg);
            return restTemplate.getForObject(url,String.class);
        }

3. 使用拦截器的方式

    @Bean
    @LoadBalanced//这个注解在描述RestTemplate对象时,系统底层会对RestTemplate对象的请求进行拦截
    public RestTemplate loadBalanceRestTemplate(){
        return new RestTemplate();
    }



        @GetMapping("/consumer/echo3/{msg}")
        public String doRestEcho3(@PathVariable String msg) {
            String url = String.format("http://sca-provider/provider/echo/%s",msg);
            return loadBalanceRestTemplate.getForObject(url,String.class );
        }
    }
}

面试分析

  • 为什么要将服务注册到nacos?(为了更好的查找这些服务)
  • 在Nacos中服务提供者是如何向Nacos注册中心(Registry)续约的?(5秒心跳)
  • 对于Nacos服务来讲它是如何判定服务实例的状态?(检测心跳包,15,30)
  • 服务启动时如何找到服务启动注册配置类?(NacosNamingService)
  • 服务消费方是如何调用服务提供方的服务的?(RestTemplate)

       

  • @Bean注解的作用?(一般用于配置类内部,描述相关方法,用于告诉spring此方法的返回值要交给spring管理,bean的名字默认为方法名,假如需要指定名字可以@Bean(“bean的名字”),最多的应用场景是整合第三方的资源-对象)
  • @Autowired注解的作用?(此注解用于描述属性,构造方法,set方法等,用于告诉spring框架,按找一定的规则为属性进行DI操作,默认按属性,方法参数类型查找对应的对象,假如只找到一个,则直接注入,类型多个时还会按照属性名或方法参数名进行值的注入,假如名字也不同,就出报错.)
  • Nacos中的负责均衡底层是如何实现的?(通过Ribbon实现,Ribbon中定义了一些负载均衡算法,然后基于这些算法从服务实例中获取一个实例为消费方法提供服务)
  • Ribbon 是什么?(Netflix公司提供的负载均衡客户端,一般应用于服务的消费方法)
  • Ribbon 可以解决什么问题? (基于负载均衡策略进行服务调用, 所有策略都会实现IRule接口)
  • Ribbon 内置的负载策略都有哪些?(8种,可以通过查看IRule接口的实现类进行分析)
  • @LoadBalanced的作用是什么?(描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器进行拦截,然后在拦截器内部,启动负载均衡策略。)
  • 我们可以自己定义负载均衡策略吗?(可以,基于IRule接口进行策略定义,也可以参考NacosRule进行实现)

微服务项目结构分析

服务调用案例分析

服务调用方案图解

 这张图描述了远程服务调用的几中方式:
第一种:服务比较少,例如就两个服务,一个服务消费,一个服务提供,就不需要注册中心,不需要负载均衡.
第二种:并发比较大,服务服务比较多,我们需要管理服务,就需要注册中心,我们还需要服务间的负载均衡.但代码编写的复杂多相对高一些,我们需要自己获取ip,获取端口,拼接字符串等.
第三种:我们要基于第二种进行代码简化,底层提供了一种拦截器,把基于服务名获取服务实例的过程在拦截器中做了封装,简化了代码的开发.但是加了拦截器多少会在性能少有一点损耗.
第四种方式主要是从代码结构上做一个挑战,我们前面三种基于RestTemplate进行服务调用,本身属于一种远程服务调用业务,能够将这种业务写到一个业务对象中,Feign方式就诞生了,它主要对代码结构的一种优化.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值