一、Window下单机搭建.
1、Nacos官方文档:Nacos 快速开始
2、Nacos基于Java开发,部署一个Java应用,版本2.1.0,实际开发使用企业版,有完整权限和运维.
3、Nacos存储配置在数据库中,简历对应的数据库和表结构,对应SQL如下,这里使用mysql存储.
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info */
/******************************************/
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_aggr */
/******************************************/
CREATE TABLE `config_info_aggr` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`content` longtext NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_beta */
/******************************************/
CREATE TABLE `config_info_beta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_tag */
/******************************************/
CREATE TABLE `config_info_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_tags_relation */
/******************************************/
CREATE TABLE `config_tags_relation` (
`id` bigint(20) NOT NULL COMMENT 'id',
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`nid` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`nid`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = group_capacity */
/******************************************/
CREATE TABLE `group_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = his_config_info */
/******************************************/
CREATE TABLE `his_config_info` (
`id` bigint(64) unsigned NOT NULL,
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`data_id` varchar(255) NOT NULL,
`group_id` varchar(128) NOT NULL,
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL,
`md5` varchar(32) DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src_user` text,
`src_ip` varchar(50) DEFAULT NULL,
`op_type` char(10) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`nid`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = tenant_capacity */
/******************************************/
CREATE TABLE `tenant_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`kp` varchar(128) NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE `users` (
`username` varchar(50) NOT NULL PRIMARY KEY,
`password` varchar(500) NOT NULL,
`enabled` boolean NOT NULL
);
CREATE TABLE `roles` (
`username` varchar(50) NOT NULL,
`role` varchar(50) NOT NULL,
UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL,
`resource` varchar(255) NOT NULL,
`action` varchar(8) NOT NULL,
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
4、配置文件修改
默认端口:8848.
### Default web context path:
server.servlet.contextPath=/nacos
### Default web server port:
server.port=7088
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=10000&socketTimeout=30000&autoReconnect=true&useUnicode=true&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
db.user.0=数据库账号
db.password.0=数据库密码
### Connection pool configuration: hikariCP
db.pool.config.connectionTimeout=30000
db.pool.config.validationTimeout=10000
db.pool.config.maximumPoolSize=20
db.pool.config.minimumIdle=2
5、单机启动命令
①、 startup.cmd -m standalone
②、直接启动命令修改.
修改startup.cmd,修改为standalone,默认是以集群启动的.
6、配置
①、默认账号/密码:nacos/nacos
②、新增配置
③、修改配置、灰度发布.
支持TEXT、JSON、XML、YAML、HTML、Properties类型的配置文件,文件枚举信息如下:
package com.alibaba.nacos.api.config;
import com.alibaba.nacos.api.utils.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* Config data type.
*
* @author liaochuntao
**/
public enum ConfigType {
/**
* config type is "properties".
*/
PROPERTIES("properties"),
/**
* config type is "xml".
*/
XML("xml"),
/**
* config type is "json".
*/
JSON("json"),
/**
* config type is "text".
*/
TEXT("text"),
/**
* config type is "html".
*/
HTML("html"),
/**
* config type is "yaml".
*/
YAML("yaml"),
/**
* not a real type.
*/
UNSET("unset");
private final String type;
private static final Map<String, ConfigType> LOCAL_MAP = new HashMap<String, ConfigType>();
static {
for (ConfigType configType : values()) {
LOCAL_MAP.put(configType.getType(), configType);
}
}
ConfigType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public static ConfigType getDefaultType() {
return TEXT;
}
/**
* check input type is valid.
*
* @param type config type
* @return it the type valid
*/
public static Boolean isValidType(String type) {
if (StringUtils.isBlank(type)) {
return false;
}
return null != LOCAL_MAP.get(type);
}
}
文件修改类型枚举.
package com.alibaba.nacos.api.config;
/**
* Property Change Type.
*
* @author rushsky518
*/
public enum PropertyChangeType {
/**
* add.
*/
ADDED,
/**
* modified.
*/
MODIFIED,
/**
* deleted.
*/
DELETED
}
在配置项中设置.
package com.alibaba.nacos.api.config;
/**
* ConfigChangeItem.
*
* @author rushsky518
*/
public class ConfigChangeItem {
private String key;
private String oldValue;
private String newValue;
private PropertyChangeType type;
public ConfigChangeItem(String key, String oldValue, String newValue) {
this.key = key;
this.oldValue = oldValue;
this.newValue = newValue;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getOldValue() {
return oldValue;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
public PropertyChangeType getType() {
return type;
}
public void setType(PropertyChangeType type) {
this.type = type;
}
@Override
public String toString() {
return "ConfigChangeItem{" + "key='" + key + '\'' + ", oldValue='" + oldValue + '\'' + ", newValue='" + newValue
+ '\'' + ", type=" + type + '}';
}
}
④、配置项查询,content为longtext类型存储.
⑤、配置项修改
启动失败时候查看日志解决具体报错,使用logback日志组件.
二、Windows下集群搭建
1、目录规划以及端口安排,三个节点集群搭建.
Nacos1:8848
Nacos2:8850
Nacos3:8852
注意:单个Nacos节点分布式搭建集群需要四个端口.
raft port: ${server.port} - 1000
grpc port: ${server.port} + 1000
grpc port for server: ${server.port} + 1001
例如:假设对外端口为8848,即总共会有4个端口被占用,分别为7848、8848、9848、9849
集群搭建要避免端口占用,否则集群启动节点失败.
netstat -ano |findstr "8848"
8848、7848、9848、9849
netstat -ano |findstr "8850"
8850、7850、9850、9851
netstat -ano |findstr "8852"
8852、7852、9852、9853
2、集群配置文件
8848节点,配置各个节点的集群ServerIP
192.168.1.6:8848
192.168.1.6:8850
192.168.1.6:8852
3、启动集群节点
8848节点
8850节点
8852节点
4、集群访问页面
http://192.168.1.6:8848/nacos/index.html#/clusterManagement?dataId=&group=&appName=&namespace=
账号:nacos/nacos
节点元数据.
5、新增配置
查看其他两个节点.
说明:会在文件中做个缓存,本地文件中没有在GET服务端,都是这样设计的,Apollo的也是这样缓存的.
三、高可用集群
图片来自网络架构图
说明:Nginx集群可以用云服务SLB来搭建负载均衡监听,MySQL保证高可用,常见基本如单Region单AZ的主备,以及跨AZ容灾的主备浮动VIP确保.
①、Nginx的反向代理配置如下:
http {
server {
listen 80;
server_name 127.0.0.1;
location /nacos {
proxy_pass http://nacoscluster/nacos;
}
}
upstream nacoscluster {
server 192.168.1.6:8848;
server 192.168.1.6:8850;
server 192.168.1.6:8852;
}
}
这里Nginx配置就略过了,网上资料比较多,配置反向代理即可.
②、有条件可以使用云服务+单独域名来负载均衡,搭建高可用的配置服务.
四、Prometheus监控
1、本质Nacos是使用SpringBoot开发,自带监控端点actuator,并且集成了prometheus监控.
2、开启监控项
management.endpoints.web.exposure.include=*
3、配置Prometheus监控任务.
# Nacos集群
- job_name: "NacosClusterMonitor"
metrics_path: '/nacos/actuator/prometheus'
static_configs:
- targets: ['192.168.1.6:8848','192.168.1.6:8850','192.168.1.6:8852']
4、启动Promethesu监控
http://192.168.1.6:9090/targets#pool-NacosClusterMonitor
5、Grafana展示
13221
Nacos的监控实现:使用promethesu+Http方式
package com.alibaba.nacos.client.monitor;
import io.prometheus.client.Gauge;
import io.prometheus.client.Histogram;
/**
* Metrics Monitor.
*
* @author Nacos
*/
public class MetricsMonitor {
private static final Gauge NACOS_MONITOR = Gauge.build().name("nacos_monitor").labelNames("module", "name")
.help("nacos_monitor").register();
private static final Histogram NACOS_CLIENT_REQUEST_HISTOGRAM = Histogram.build()
.labelNames("module", "method", "url", "code").name("nacos_client_request").help("nacos_client_request")
.register();
public static Gauge.Child getServiceInfoMapSizeMonitor() {
return NACOS_MONITOR.labels("naming", "serviceInfoMapSize");
}
public static Gauge.Child getDom2BeatSizeMonitor() {
return NACOS_MONITOR.labels("naming", "dom2BeatSize");
}
public static Gauge.Child getListenConfigCountMonitor() {
return NACOS_MONITOR.labels("naming", "listenConfigCount");
}
public static Histogram.Timer getConfigRequestMonitor(String method, String url, String code) {
return NACOS_CLIENT_REQUEST_HISTOGRAM.labels("config", method, url, code).startTimer();
}
public static Histogram.Child getNamingRequestMonitor(String method, String url, String code) {
return NACOS_CLIENT_REQUEST_HISTOGRAM.labels("naming", method, url, code);
}
}
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.common.http.HttpRestResult;
import io.prometheus.client.Histogram;
import java.util.Map;
/**
* MetricsHttpAgent.
*
* @author Nacos
*/
public class MetricsHttpAgent implements HttpAgent {
private static final String GET = "GET";
private static final String POST = "POST";
private static final String DELETE = "DELETE";
private static final String DEFAULT_CODE = "NA";
private final HttpAgent httpAgent;
public MetricsHttpAgent(HttpAgent httpAgent) {
this.httpAgent = httpAgent;
}
@Override
public void start() throws NacosException {
httpAgent.start();
}
@Override
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);
HttpRestResult<String> result;
try {
result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);
} finally {
timer.observeDuration();
}
return result;
}
@Override
public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor(POST, path, DEFAULT_CODE);
HttpRestResult<String> result;
try {
result = httpAgent.httpPost(path, headers, paramValues, encode, readTimeoutMs);
} finally {
timer.observeDuration();
}
return result;
}
@Override
public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor(DELETE, path, DEFAULT_CODE);
HttpRestResult<String> result;
try {
result = httpAgent.httpDelete(path, headers, paramValues, encode, readTimeoutMs);
} finally {
timer.observeDuration();
}
return result;
}
@Override
public String getName() {
return httpAgent.getName();
}
@Override
public String getNamespace() {
return httpAgent.getNamespace();
}
@Override
public String getTenant() {
return httpAgent.getTenant();
}
@Override
public String getEncode() {
return httpAgent.getEncode();
}
@Override
public void shutdown() throws NacosException {
httpAgent.shutdown();
}
}
仅仅搭建,后面分析分布式算法和一些源码等.