Spring Cloud(二):Spring Cloud Alibaba Nacos

Spring Cloud(二):Spring Cloud Alibaba Nacos_第1张图片

Nacos注册中心

Nacos注册中心(Nacos Server)核心功能

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

Nacos注册中心(Nacos Server)环境搭建

官方文档: https://nacos.io/zh-cn/docs/deployment.html

下载安装包:https://github.com/alibaba/nacos/releases/

解压,进入nacos目录

Spring Cloud(二):Spring Cloud Alibaba Nacos_第2张图片

配置数据库

单机下:不配置Naocs默认使用内存数据库
Mysql数据库:使用conf/nacos-mysql.sql初始化表
application.properties Mysql配置: conf/application.properties
Spring Cloud(二):Spring Cloud Alibaba Nacos_第3张图片

启动Nacos

单机模式:

./bin/startup.sh -m standalone

集群模式:

./bin/startup.sh or ./bin/startup.sh -m cluster

conf/cluster.conf.example

#example
192.168.16.101:8848
192.168.16.102:8848
192.168.16.103:8848

如果是一台集群需要区分nacos.home目录配置 nacos.home=/nacos-cluster/nacos-8847 需要创建目录并在目录下新建/nacos-cluster/nacos-8847/conf/cluster.conf

Nacos2.x版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口
新增端口是在配置的主端口(server.port 8848)基础上,进行一定偏移量自动生成

端口 与主端口的偏移量 描述
9848 1000 客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求
9849 1001 服务端gRPC请求服务端端口,用于服务间同步等

如果碰到mysql-connector-java不兼容添加
对应jar包到nacos下plugins/mysql文件夹里面

Spring Cloud Alibaba Nacos快速开始

1. 依赖

pom.xml


<dependency>
	<groupId>com.alibaba.cloudgroupId>
	<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>

application.yml

spring:
  application:
    name: open-api-global-quartz
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: 2cd251e2-5fb4-491a-955e-67c43be601f4
        group: open-api
      config:
        server-addr: localhost:8848
        file-extension: yaml
        group: open-api

更多配置:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery

Spring Cloud(二):Spring Cloud Alibaba Nacos_第4张图片

2. 启动服务,nacos管理端界面查看是否成功注册

Spring Cloud(二):Spring Cloud Alibaba Nacos_第5张图片

测试,通过Open API查询实例列表

open-api 目前还是1.x.x

Spring Cloud(二):Spring Cloud Alibaba Nacos_第6张图片

http://localhost:8848/nacos/v1/ns/instance/list?serviceName=open-api-service-product&groupName=open-api&namespaceId=2cd251e2-5fb4-491a-955e-67c43be601f4

Spring Cloud(二):Spring Cloud Alibaba Nacos_第7张图片

注册示例代码

/* Refer to document: https://github.com/alibaba/nacos/blob/master/example/src/main/java/com/alibaba/nacos/example
*  pom.xml
    
        com.alibaba.nacos
        nacos-client
        ${latest.version}
    
*/
package com.alibaba.nacos.example;

import java.util.Properties;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;

/**
 * @author nkorange
 */
public class NamingExample {

    public static void main(String[] args) throws NacosException {

        Properties properties = new Properties();
        properties.setProperty("serverAddr", System.getProperty("serverAddr"));
        properties.setProperty("namespace", System.getProperty("namespace"));

        NamingService naming = NamingFactory.createNamingService(properties);

        naming.registerInstance("open-api-service-product", "11.11.11.11", 8888, "TEST1");

        naming.registerInstance("open-api-service-product", "2.2.2.2", 9999, "DEFAULT");

        System.out.println(naming.getAllInstances("open-api-service-product"));

        naming.deregisterInstance("open-api-service-product", "2.2.2.2", 9999, "DEFAULT");

        System.out.println(naming.getAllInstances("open-api-service-product"));

        naming.subscribe("open-api-service-product", new EventListener() {
            @Override
            public void onEvent(Event event) {
                System.out.println(((NamingEvent)event).getServiceName());
                System.out.println(((NamingEvent)event).getInstances());
            }
        });
    }
}

Spring Cloud(二):Spring Cloud Alibaba Nacos_第8张图片

Ribbon 提供的LoadBalanced

Spring Cloud(二):Spring Cloud Alibaba Nacos_第9张图片

@Configuration
public class RestConfig {

    @Bean
    @LoadBalanced //open-api-service-product => ip:port
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
@Slf4j
@RestController
@RequestMapping("/demo")
public class RestTemplateController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/product")
    public String productIndex() {
        log.info("demo product start");
        String url = "http://open-api-service-product/check";
        String result = restTemplate.getForObject(url, String.class);
        log.info("demo product result = " + result);
        return result;
    }
}

Nacos注册中心常见配置

服务分级存储模型

服务-集群-实例 三层模型
Spring Cloud(二):Spring Cloud Alibaba Nacos_第10张图片

服务逻辑隔离

Spring Cloud(二):Spring Cloud Alibaba Nacos_第11张图片

  • Namespace 隔离设计: 命名空间(Namespace)用于进行租户(用户)粒度的隔离,Namespace 的常用场景之一是不同环境的隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
  • group服务分组:不同的服务可以归类到同一分组,group也可以起到服务隔离的作用

临时实例和持久化实例

在定义上区分临时实例和持久化实例的关键是健康检查的方式

  • 临时实例使用客户端上报模式:临时实例需要能够自动摘除不健康实例,而且无需持久化存储实例
  • 持久化实例使用服务端反向探测模式:持久化实例使用服务端探测的健康检查方式,因为客户端不会上报心跳, 所以不能自动摘除下线的实例

在大中型的公司里往往:

  • 持久化实例注册—基础组件: 例如数据库、缓存等,这些往往不能上报心跳
  • 动态服务的注册—上层业务: 例如微服务或者 Dubbo 服务,服务的 Provider 端支持添加汇报心跳的逻辑

Nacos 1.x 中持久化及非持久化的属性是作为实例的⼀个元数据进行存储和识别。
Nacos 2.x 中继续沿用了持久化及非持久化的设定,但是有了⼀些调整。在 Nacos2.0 中将是否持久化的数据抽象至服务级别, 且不再允许⼀个服务同时存在持久化实例和非持久化实例,实例的持久化属性继承自服务的持久化属性。

# 持久化实例
spring.cloud.nacos.discovery.ephemeral: false

临时实例变更为持久实例:删除 nacos/data/protocol/raft/naming_persistent_service_v2

NacosServiceRegistry implements ServiceRegistry 源码入口

org.springframework.cloud.client.serviceregistry.ServiceRegistry

com.alibaba.cloud.nacos.registry.NacosServiceRegistry implements ServiceRegistry

public abstract class AbstractAutoServiceRegistration<R extends Registration>
		implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {
	...
	public void onApplicationEvent(WebServerInitializedEvent event) {
		bind(event);
	}
	...
}		
public class NacosServiceRegistry implements ServiceRegistry<Registration> {
	...
	@Override
	public void register(Registration registration) {

		if (StringUtils.isEmpty(registration.getServiceId())) {
			log.warn("No service to register for nacos client...");
			return;
		}

		String serviceId = registration.getServiceId();
		String group = nacosDiscoveryProperties.getGroup();

		Instance instance = getNacosInstanceFromRegistration(registration);

		try {
			// Nacos namingService 注册
			namingService.registerInstance(serviceId, group, instance);
			log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
					instance.getIp(), instance.getPort());
		}
		catch (Exception e) {
			log.error("nacos registry, {} register failed...{},", serviceId,
					registration.toString(), e);
			// rethrow a RuntimeException if the registration is failed.
			// issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132
			rethrowRuntimeException(e);
		}
	}
	...
}

Nacos 配置中心

demo

  1. pom.xml
<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
  1. bootstrap.yml
spring:
  application:
    name: stock-service
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        cluster-name: Beijing
        namespace: dev
        file-extension: yaml
        shared-configs[0]:
          dataId: nacos-share.yaml
          refresh: true
        extension-configs[0]:
          dataId: nacos-ext.yaml
          refresh: true
  1. 优先级从高到低:
  1. nacos-config-product.yaml 精准配置
  2. nacos-config.yaml 同工程不同环境的通用配置
  3. ext-config: 不同工程 扩展配置
  4. shared-dataids 不同工程通用配置
  1. @Value注解可以获取到配置中心的值,但是无法动态感知修改后的值,需要利用@RefreshScope注解
@RestController
@RequestMapping("/nacos")
@RefreshScope
public class NacosConfigController {

    @Value("${mxnacos.nacos-ext.name}")
    private String nacosExtName;

    @Value("${mxnacos.nacos-share.name}")
    private String nacosShareName;

    @Value("${mxnacos.stock-service.name}")
    private String stockServiceName;

    @GetMapping("/config")
    public String deductStock() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("nacosShareName: " + nacosShareName);
        stringBuilder.append(" < ");
        stringBuilder.append("nacosExtName: " + nacosExtName);
        stringBuilder.append(" < ");
        stringBuilder.append("stockServiceName: " + stockServiceName);
        return stringBuilder.toString();
    }
}

在这里插入图片描述

Nacos nacos-examples

https://github.com/nacos-group/nacos-examples

你可能感兴趣的:(Spring,Cloud,Spring,Cloud,Nacos)