其他分享
首页 > 其他分享> > nacos实现服务注册中心与配置中心

nacos实现服务注册中心与配置中心

作者:互联网

一、nacos简介

Nacos(DynamicNaming and Configuration Service)是一个应用于服务注册与发现、配置管理的平台,代替了原来SpringCloud系列中的Eureka+Config+Bus。它孵化于阿里巴巴,成长于十年双十一的洪峰考验,沉淀了简单易用、稳定可靠、性能卓越的核心竞争力。
官网地址: https://nacos.io/zh-cn/docs/quick-start.html
常见注册中心:Zookeeper(雅虎Apache),Eureka(Netfix),Nacos(Alibaba),Consul(Google)

二、nacos服务搭建

1 下载与安装

浏览器输入网址 https://github.com/alibaba/nacos/releases 选择对应版本下载,我使用的版本是1.4.1,然后解压
在这里插入图片描述

2 初始化配置

解压后的文件找到/conf/nacos-mysql.sql文件,创建nacos_config数据库(数据库名可自己指定,编码方式utf8mb4),把nacos-mysql.sql脚本导入该库中,脚本执行成功后会创建如下表
在这里插入图片描述
说明:在执行此文件时,要求mysql的版本大于5.7版本(MariaDB最好10.5.11),否则会出现如下错误:
在这里插入图片描述
打开/conf/application.properties文件,配置你导入nacos-mysql.sql数据库的配置信息

### 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=1234

3 服务启动与访问

进入解压文件的bin目录,windows环境下执行命令 startup.cmd -m standalone 其中-m代表启动模式,standalone代表着单机模式运行,非集群模式
在这里插入图片描述
启动成功后,访问Nacos服务,浏览器输入 http://localhost:8848/nacos 默认账号密码为nacos/nacos 登录

三、服务注册与发现入门

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

1 创建Maven父工程

创建maven module父工程,命名为00-review-msa,该工程的作用就是来管理子模块中所需要的共性核心依赖
在这里插入图片描述

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>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zhanlijuan</groupId>
    <artifactId>00-review-msa</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spring.cloud-version>Hoxton.SR8</spring.cloud-version>
        <spring.cloud.alibaba-version>2.2.5.RELEASE</spring.cloud.alibaba-version>
    </properties>

    <!--依赖版本管理-->
    <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>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

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

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

说明:父工程资源初始化完成以后,将src目录删除,因为父工程只负责依赖管理.

2 生产者服务创建及注册

在00-review-msa父工程下创建子工程msa-provider,添加项目依赖

    <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>

修改配置文件application.yml 实现服务注册

server:
  port: 8081
spring:
  application:
    #服务名,后续会在注册中心里呈现这个名字 服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则
    name: msa-provider
  cloud:
    nacos: #服务的注册与发现
      server-addr: localhost:8848

定义处理请求的控制层对象和方法

@RestController
public class TestController {

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

    @GetMapping(value = "/provider/test/{msg}")
    public String doEcho(@PathVariable String msg) {
        return port + "say:Hello Nacos Discovery " + msg;
    }
}

启动启动类,然后刷新nacos服务,检测是否服务注册成功
在这里插入图片描述
打开浏览器,输入 http://localhost:8081/provider/test/msa ,然后进行访问。

3 消费者服务发现及调用

在00-review-msa父工程下创建子工程msa-consumer,添加项目依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--服务注册和发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

修改配置文件application.yml

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

构建远程过程调用对象,基于此对象访问远程服务,服务消费方通过RestTemplate 调用服务提供方的服务的

@Configuration
public class RestTemplateConfig {

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

编写测试类,测试服务消费

@RestController
public class TestController {

    @Value("${spring.application.name}")
    private String appName;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/test")
    public String test() {
        String url = "http://localhost:8081/provider/echo/" + appName;
        System.out.println("request url:" + url);
        return restTemplate.getForObject(url, String.class);
    }

}

启动消费者服务,在nacos中注册成功
在这里插入图片描述
浏览器输入 http://localhost:8090/consumer/test 出现如下效果
在这里插入图片描述

四、nacos实现负载均衡

1 @LoadBalancerClient

修改TestController类,注入LoadBalancerClient对象,添加testLoadBalancerClient方法

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

    /**
     * 基于RestTemplate进行远程服务调用,但是在调用之前基于loadBalancerClient对象去从nacos注册中心基于服务名查找服务实例(可能有多个)
     * 此时会在本地按照一定算法去选择服务实例,然后进行服务调用
     */
    @GetMapping("/consumer/testLoadBalancerClient")
    public String doRestEcho02() {
        //基于服务名(nacos中服务列表中的名字)查找服务实例
        ServiceInstance serviceInstance = loadBalancerClient.choose("msa-provider");
        //构建远程调用的url
        String url = String.format("http://%s:%s/provider/echo/%s", serviceInstance.getHost(), serviceInstance.getPort(), appName);
        System.out.println("request url:" + url);
        return restTemplate.getForObject(url, String.class);
    }

msa-provider 服务启动两个,端口分别为8081,8082,启动msa-consumer服务,检查服务是否注册成功
在这里插入图片描述
浏览器访问 http://localhost:8090/consumer/testLoadBalancerClient 反复刷新,你会发现msa-provider的两个服务都可以处理msa-consumer的请求
在这里插入图片描述
总结:这里多个实例并发提供服务的方式为负载均衡,这里的负载均衡实现默认是因为Nacos集成了Ribbon来实现的,Ribbon配合RestTemplate,可以非常容易的实现服务之间的访问。Ribbon是Spring Cloud核心组件之一,它提供的最重要的功能就是客户端的负载均衡(客户端可以采用一定算法,例如轮询访问,访问服务端实例信息),这个功能可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡方式的服务调用。

2 @LoadBalanced

描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器LoadBalancerInterceptor进行拦截LoadBalancerInterceptor将负载均衡的核心逻辑交给了loadBalancer,然后在拦截器内部,启动RestTemplate的负载均衡。

RestTemplateConfig类添加代码

    @Bean
    @LoadBalanced
    public RestTemplate loadBalancedRestTemplate() {
        return new RestTemplate();
    }

修改TestController类

    @Autowired
    private RestTemplate loadBalancedRestTemplate;
    /**
     * 基于具备了负载均衡特性的RestTemplate进行远程服务调用,实现的功能与方式 loadBalancerClient 相同,只是代码编写上做了简化,
     * 此效率会稍微弱于方式loadBalancerClient,因为底层会对请求进行拦截,拦截到以后基于loadBalancerClient获取服务实例,然后进行调用
     */
    @GetMapping("/consumer/loadBalancedRestTemplate")
    public String doRestEcho04() {
        String url=String.format("http://%s/provider/echo/%s","msa-provider",appName);
        System.out.println("request url:" + url);
        return loadBalancedRestTemplate.getForObject(url, String.class);
    }

五、基于Feign的远程服务调用

1 Feign简介

Feign 是一种声明式Web服务客户端,底层封装了对Rest技术(拼接url,拼接参数)的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现,最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由社区进行维护,更名为 OpenFeign。

2 Feign入门案例

在服务消费方,添加项目依赖(SpringCloud团队基于OpenFeign研发了starter)

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

启动类上添加@EnableFeignClients注解
在这里插入图片描述
定义Http请求API,基于此API借助OpenFeign访问远端服务

/**
 * 基于@FeignClient定义远程服务调用接口,这个接口不需要我们自己写实现类,底层会在服务启动时会帮我们创建实现(代理对象),在实现类内部进行远程服务调用
 * 其中:
 * name 属性的值为nacos中的服务名,
 * contextId 为一个上下文id,作为远程调用服务的唯一标识,一般就写当前接口名,用于区分服务调用,
 * 因为将来一个服务提供方会提供很多资源调用,假如服务消费方,基于同一个服务提供方,写了很多接口此时假如没有指定contextId,服务启动就会失败
 */
@FeignClient(name = "msa-provider", contextId = "remoteProviderService")//msa-provider为nacos中的服务名
public interface RemoteProviderService {

    @RequestMapping("/provider/echo/{msg}")//前提是远端服务msa-provider有这个请求地址
    String echoMsg(@PathVariable String msg);
}

创建FeignConsumerController中并添加feign访问

@RestController
@RequestMapping("consumer")
public class FeignConsumerController {

    @Autowired
    private RemoteProviderService remoteProviderService;

    /**
     * 基于feign方式的服务调用
     */
    @GetMapping("feign/echo/{msg}")
    public String doFeignEcho(@PathVariable String msg) {
        //基于feign方式进行远端服务调用(前提是服务必须存在)
        return remoteProviderService.echoMsg(msg);
    }
}

重启服务,浏览器访问 http://localhost:8090/consumer/feign/echo/hello测试
在这里插入图片描述

3 远程服务异常处理

定义FallbackFactory接口的实现

/**
 * 基于此对象处理RemoteProviderService接口调用出现的异常问题
 */
@Component
public class ProviderFallbackFactory implements FallbackFactory<RemoteProviderService> {
    /**
     * 此方法会在RemoteProviderService接口服务调用时,出现了异常后执行
     */
    @Override
    public RemoteProviderService create(Throwable throwable) {
        return (msg) -> "服务维护中,请稍后重试";
    }
}

在Feign访问接口中应用FallbackFactory对象
在这里插入图片描述
在application.yml中添加配置,启动feign方式调用时的服务中断处理机制.

#启用feign方式服务调用的异常处理机制
feign:
  hystrix:
    enabled: true

重启msa-comsumer服务,停止msa-provider服务,浏览器输入 http://localhost:8090/consumer/feign/echo/dddd 测试
在这里插入图片描述

4 Feign调用过程分析

Feign应用过程分析(底层逻辑先了解):
1)通过 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件。
2) Feign Starter 在项目启动过程中注册全局配置,扫描包下所有@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),并构建类的对象,然后交给spring管理(注册 IOC 容器)。
3) 接口被调用时被动态代理类逻辑拦截,将 @FeignClient 请求信息通过编码器生成 Request对象,基于此对象进行远程过程调用。
4) 请求对象经Ribbon进行负载均衡,挑选出一个健康的 Server 实例(instance)。
5) 通过 Client 携带 Request 调用远端服务返回请求响应。
6) 通过解码器生成 Response 返回客户端,将信息流解析成为接口返回数据。

六、nacos实现配置中心

市场上主流配置中心有Apollo(携程开源),nacos(阿里开源),Spring Cloud Config(Spring Cloud 全家桶成员)这里选择nacos,此组件不仅提供了注册中心,还具备配置中心的功能,动态管理发布配置,无需重启服务,更好保证服务的可用。

1 nacos配置快速入门

在msa-provider服务的pom文件添加依赖

        <!--添加nacos配置中心依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

将项目中的application.yml的名字修改为bootstrap.yml配置文件(启动优先级最高)

spring:
  application:
    #服务名,后续会在注册中心里呈现这个名字 服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则
    name: msa-provider
  cloud:
    nacos:
      discovery: #服务的注册与发现
        server-addr: localhost:8848
      config: #服务的配置
        server-addr: localhost:8848
        group: DEFAULT_GROUP
        file-extension: yml

打开nacos配置中心,新建配置
在这里插入图片描述
其中Data ID的值要与bootstrap.yml中定义的spring.application.name的值相同(服务名-假如有多个服务一般会创建多个配置实例,不同服务对应不同的配置实例)。
在TestController中添加注解**@RefreshScope**实现动态发布,添加一个获取日志级别的方法

/**
 * @RefreshScope的作用是在配置中心的相关配置发生变化以后,能够及时看到更新(底层是通过重新创建Controller对象的方式,对属性进行了重新初始化)
 */
@RefreshScope //动态刷新配置
@RestController
@Slf4j
public class TestController {

    @Value("${logging.level.com.zhanlijuan:error}")
    private String logLevel;

    @GetMapping("/provider/doGetLogLevel")
    public String doGetLogLevel() {
        log.trace("==log.trace==");//跟踪
        log.debug("==log.debug==");//调试
        log.info("==log.info==");//常规信息
        log.warn("==log.warn==");//警告
        log.error("==log.error==");//错误信息
        return "log level is " + logLevel;
    }
 }

浏览器输入 http://localhost:8082/provider/doGetLogLevel
在这里插入图片描述
然后nacos修改日志级别在继续测试,验证是否动态更新

2 nacos配置管理模型

Nacos 配置管理模型由三部分构成,如图所示:
在这里插入图片描述

2.1 命名空间设计

Nacos中的命名空间一般用于配置隔离,这种命名空间的定义一般会按照环境(开发,生产等环境)进行设计和实现.我们默认创建的配置都存储到了public命名空间
在这里插入图片描述
需求:自定义命令空间,测试环境,从配置中读取信息
创建命名空间beta
在这里插入图片描述
命名空间成功创建以后,会在如下列表进行呈现。
在这里插入图片描述
在指定命名空间下添加配置,也可以直接取配置列表中克隆,例如:
在这里插入图片描述
克隆成功以后,我们会发现在指定的命名空间中有了我们克隆的配置
在这里插入图片描述
修改beta命名空间中Data Id的msa-provider的配置
在这里插入图片描述
在bootstrap.yml文件中增加命名空间namespace的配置
在这里插入图片描述
重启服务,测试能否获取到beta里面的配置的日志级别

2.2 分组设计及实现

当我们在指定命名空间下,按环境或服务做好了配置以后,有时还需要基于服务做分组配置,例如,一个服务在不同时间节点(节假日,活动等)切换不同的配置,可以在新建配置时指定分组名称
在这里插入图片描述
修改boostrap.yml配置类,在其内部指定我们刚刚创建的分组
在这里插入图片描述
在NacosConfigController类中添加属性和方法用于获取和输出DEV_GROUP_51配置中设置的线程数

    @Value("${server.tomcat.threads.max:200}")
    private Integer maxThread;

    @RequestMapping("/provider/doGetMaxThread")
    public String doGetMaxThread(){
        return "server.threads.max is  "+maxThread;
    }

重启服务测试
在这里插入图片描述

2.3 共享配置设计及读取

当同一个namespace的多个配置文件中都有相同配置时,可以对这些配置进行提取,然后存储到nacos配置中心的一个或多个指定配置文件,哪个微服务需要,就在服务的配置中设置读取即可。
在nacos中创建一个共享配置文件
在这里插入图片描述
在指定的微服务配置文件(bootstrap.yml)中设置对共享配置文件的读取

spring:
  application:
    #服务名,后续会在注册中心里呈现这个名字 服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则
    name: msa-provider
  cloud:
    nacos:
      discovery: #服务的注册与发现
        server-addr: localhost:8848
      config: #服务的配置
        server-addr: localhost:8848
        #group: DEFAULT_GROUP 默认的分组
        file-extension: yml
        #namespace: cad30c4b-105c-4f0b-9ec1-a63a9e9a9837 #命名空间namespace不写默认是public 用于环境的隔离
        group: DEFAULT_GROUP_11
        shared-configs[0]: #共享配置
          data-id: app-public-beta.yml
          group: DEFAULT_GROUP
          refresh: true #默认false

NacosConfigController 类添加业务逻辑代码验证

    @Value("${page.pageSize:10}")
    private Integer pageSize;
    
    @GetMapping("/provider/doGetPageSize")
    public String doGetPageSize() {
        //return String.format()
        return "page size is " + pageSize;
    }

启动服务进行访问测试
在这里插入图片描述

标签:调用,服务,String,中心,nacos,注册,provider,msa
来源: https://blog.csdn.net/zhanlijuan2015/article/details/119273050