在微服务架构中,服务注册中心是一个举足轻重的组件。它实现的目标是便捷于多服务之间的通信,服务的横向扩展等。它能提供的服务有服务的注册与发现、中心化配置、健康检查和服务移除。市面上存在很多组件,包括Consul 、Zookeeper 、Nacos 、Eureka 等等。这些组件具体的差异内容比较丰富,我们单独开一篇文章讲。这篇文章我们讲一下在国内比较火的Nacos 的快速入门,文章内容会涉及到Nacos 的基础知识、环境搭建、基于Springboot2 工程实践。
一、Nacos核心概念
Nacos技术团队在在线文档上已经介绍的很详细的啦,见Nacos文档,核心的要义如下。
Nacos (official site: nacos.io) is an easy-to-use platform designed for dynamic service discovery and configuration and service management. It helps you to build cloud native applications and microservices platform easily.
--来自Github官方文档介绍
简单地说,它自诩为一个易于使用的平台。核心功能为用于动态服务发现、配置和服务管理。目标是帮助开发者轻松地构建云本地应用程序和微服务平台。
还是不够明白,再明白的讲,Nacos 是阿里开源的注册中心,其完美支持基于 DNS 和基于 RPC 的服务发现。在Spring Cloud 中使用Nacos,只需要预先安装配置好Nacos server ,然后只需要对原有服务进行简单的配置就可以完成服务的注册发现。
其核心功能包括:
- 服务发现和服务健康监测
- 动态配置服务
- 动态 DNS 服务
- 服务及其元数据管理
服务的注册和发现是作为一个服务注册中心的基本素养,Nacos还支持动态配置服务,动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。
作为一个开发者,对于Nacos的细节我们可能关注的重要点包含:
- 在一致性协议(CAP)上支持CP/AP
- 支持负载均衡策略
- 有雪崩保护
- 支持自动注销示例
- 支持监听、多数据中心、跨注册中心同步
- 支持
Spring Cloud 、Dubbo 、K8s 集成
二、基于docker环境环境
众所周知,Nacos 在运行过程中需要存储数据到Mysql ,所以我们必须选择安装Mysql 。因为博主的云主机很low,1核2G,所以我们选择安装Mysql5.7,集成的docker-compose.yml 内容如下,NACOS_VERSION 变量在env 文件中控制。
version: "2"
services:
nacos:
image: nacos/nacos-server:${NACOS_VERSION}
container_name: nacos-standalone-mysql
env_file:
- ./env/nacos-standlone-mysql.env
volumes:
- ./standalone-logs/:/home/nacos/logs
- ./init.d/custom.properties:/home/nacos/init.d/custom.properties
ports:
- "8848:8848"
- "9848:9848"
- "9555:9555"
depends_on:
- mysql
restart: on-failure
environment:
- JVM_XMS=64m
- JVM_XMX=64m
- JVM_XMN=16m
- JVM_MS=8m
- JVM_MMS=8m
- NACOS_DEBUG=n
- TOMCAT_ACCESSLOG_ENABLED=false
mysql:
container_name: mysql
image: nacos/nacos-mysql:5.7
env_file:
- ./env/mysql.env
volumes:
- ./mysql:/var/lib/mysql
ports:
- "3306:3306"
因为我的服务器很low,nacos默认对JVM 的堆参数的配置相当高。所以我进行了简单优化。
- JVM_XMS=64m
- JVM_XMX=64m
- JVM_XMN=16m
- JVM_MS=8m
- JVM_MMS=8m
我都这样去抠内存了,那我更不可能去配置集群模式了,我们先以单机模式上手。
另外docker-compose.yml 文件中用到了两个文件,分别是nacos-standlone-mysql.env 和mysql.env ,内容如下。
mysql.env
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=nacos_devtest
MYSQL_USER=nacos
MYSQL_PASSWORD=nacos
nacos-standlone-mysql.env
PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=mysql
MYSQL_SERVICE_DB_NAME=nacos_devtest
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=nacos
MYSQL_SERVICE_PASSWORD=nacos
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
具体填写的参数可以根据实际开发情况进行更改。启动起来,配置云服务器的安全组。访问{ip}:{port}/nacos ,网页出现nacos的登录页面,默认账号和密码都是nacos ,登录后会出现以下的页面,即Nacos-Console 至此环境安装成功。
三、实践-获取中心配置
在使用Spring Cloud 集成Nacos 之前,我们先使用Spring Boot 。对于Nacos的版本,我使用的是0.2.4 ,是一个比较新的版本。
3.1 设置配置
设置配置我们可以使用Nacos 的管理控制台,如下图所示,我们预先添加一个useLocalCache 的配置参数。
配置填写完成后,保存,添加配置完成。
3.2 开发实践
动态获取配置,需要先通过maven 引入项目依赖。
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
因为我这个项目部署的时候要成为一个Web-server,所以引入web依赖。对于我这样一个Demo项目,用不上Tomcat 这样比较重的Web服务容器,我采用的是更加轻量一些的Jetty ,先排除Tomcat 依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
再引入Jetty 的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<version>${spring-boot.version}</version>
</dependency>
基本的依赖设置完成。
然后添加项目的配置文件application.properties ,关键是配置Nacos Server 的服务地址。
nacos:
config:
server-addr: {nacos-server-ip}:{nacos-server-port}
spring:
application:
name: springboot2-nacos-config
然后写一个Controller 端口,通过调用端口/config/get 服务,获取useLocalCache 在Nacos 服务上最新的值。并且设置autoRefreshed (自动刷新)为true 。
@Controller
@RequestMapping("config")
public class ConfigController {
@NacosValue(value = "${useLocalCache:true}", autoRefreshed = true)
private boolean useLocalCache;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public boolean get() {
return useLocalCache;
}
}
启动Web应用,然后调用 Get http://{ip}:45452/config/get ,返回的值是false ,与预期一致。通过配置管理中心设置值为true ,刷新调用接口,返回的值为true ,至此简单的获取配置完成。
四、实践-服务注册发现
注册和发现是作为一个服务注册中心最核心的功能。注册是服务的Provider,发现是服务的Consumer。我们通过一个示例来使用。
4.1 服务注册
为了使用注册中心的功能,我们必须引入相关依赖nacos-discovery-spring-boot-starter 。
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
接下来,我们要注册自身服务到服务中心,然后暴露接口以供外部查询。
@RestController
@RequestMapping("/discovery")
@Slf4j
public class NacosDiscoveryController {
@NacosInjected
private NamingService namingService;
@Value("${spring.application.name}")
private String applicationName;
@Value("${server.port}")
private Integer serverPort;
@PostConstruct
public void registerInstance() throws NacosException {
log.debug("serverPort:{}",serverPort);
#填写的ip和port很关键,用于服务中心进行健康检查。
namingService.registerInstance(applicationName,"127.0.0.1",serverPort);
}
@SneakyThrows
@GetMapping(value = "/get")
public List<Instance> get(@RequestParam String serviceName){
log.debug("Nacos Discovery into get method...{}",serviceName);
return namingService.getAllInstances(serviceName);
}
}
方法registerInstance() 在spring容器初始化时执行,向注册中心注册本服务,因为服务非集群模式,所以不用填集群服务名。方法get() 暴露HTTP Get 接口,提供查询指定服务名的所有实例。
配置文件application.properties 的内容如下,关键是配置Nacos Server 的服务地址。
nacos:
config:
server-addr: {nacos-server-ip}:{nacos-server-port}
spring:
application:
name: nacos.discovery.client
启动项目,我们可以观察Nacos管理控制台,有服务注册成功。
访问http://{ip}:{port}/discovery/get?serviceName=nacos.discovery.client ,成功获取到注册服务的信息,如下所示,展示了运行的健康状态,实例信息等。
{
"instanceId": "221.19.226.48#8080#DEFAULT#DEFAULT_GROUP@@nacos.discovery.client",
"ip": "221.19.226.48",
"port": 8080,
"weight": 1,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"serviceName": "DEFAULT_GROUP@@nacos.discovery.client",
"metadata": { },
"instanceHeartBeatInterval": 5000,
"instanceIdGenerator": "simple",
"ipDeleteTimeout": 30000,
"instanceHeartBeatTimeOut": 15000
}
]
4.2 服务发现
服务发现也是相当的简单,依赖同注册的服务保持一致,配置信息只需改变spring.application.name ,然后调用服务。
?
@SneakyThrows
@PostConstruct
public void doConsume(){
namingService.selectOneHealthyInstance("nacos.discovery.client");
final RestTemplate restTemplate = new RestTemplate();
String url = String.format("http://221.19.226.48:45451/discovery/get?serviceName=nacos.discovery.client", "221.19.226.48", 45451);
String result = restTemplate.getForObject(url, String.class);
System.out.println(String.format("请求URL:%s,响应结果:%s", url, result));
}
|