SpringCLoud——Nacos配置中心
Nacos实现配置管理
统一配置管理
然后我们就看到了配置管理界面,但是此时这里是空的,我们可以创建一些配置文件:
其中比较重要的就是配置的名称和配置内容。Data ID就是配置文件的名称,配置文件的名称的命名规范是:【服务名-环境名.后缀名】,比如我要创建一个userserver在dev环境下的统一配置管理,那么我的配置文件名就可以叫做:【userserver-dev.yaml】。描述指的就是你的配置文件的描述信息,也就是介绍一下你的配置文件是干什么用的。配置格式我们一般选择YAML,剩下的就是最重要的配置内容部分。
配置内容并不是将我们之前写的所有的内容直接粘贴进去,在这里面写的,主要是一些经常变动的部分,以及一些true和false产生不同效果的部分,比如我们的数据库的内容,我们并不需要变更他们,写一次就可以了,这种的我们就不会写在这里。我们以时间的格式化模板作为案例:
微服务配置拉取
项目启动之后,要优先读取nacos中的配置文件,然后再次读取本地的配置文件,但是要读取nacos的配置文件之前,要先知道nacos的地址,而nacos的地址存在于本地的application.yml文件中,所以,这里要使用另一个配置文件叫做:bootstrap.yml文件,这个文件的优先级要比application.yml文件的优先级要高很多,所以我们要把关于nacos的配置都写在这个里面。
<!-- Nacos的配置管理客户端依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
spring:
application:
name: userserver # 服务的名称
profiles:
active: dev # 环境
cloud:
nacos:
server-addr: localhost:8848 # 服务器的地址
config:
在这个文件中配置的东西,其中【服务名称】,【环境】,【文件的后缀名】这三个设置,就决定了在Nacos中配置的Data ID的内容,也是根据这三个内容能找到在Nacos中的对应的配置。
然后将之前在application.yml中的相同的配置注释掉。
之后就可以测试一下我们是否拉取到了在微服务中的配置,我们直接使用变量去注入我们在微服务中配置的配置项的内容,然后在Controller中创建一个方法,输出这个变量就知道我们是否拉取到了配置:
@Value("${pattern.dateformat}")
private String dataformat;
@GetMapping("data")
public String getDataformat(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dataformat));
其实我们并没有必要去访问方法,如果你的配置错误,那么在重启服务的时候你就已经无法重启了,会报出一个错误:
意思就是说,无法读取到你想要注入到变量中的配置项,所以说如果你的项目能启动起来,那么就说明你的配置是正确的。
我们也可以执行一下方法,也就是我们访问一下刚才在Controller中写入的方法对应的地址:
之前我们在微服务中配置的是一个日期格式化形式的参数,现在输入的跟我们在微服务中配置的形式一样。
将配置交给Nacos管理的步骤:
- 在Nacos中添加配置文件
- 在微服务中引入nacos的config依赖
- 在微服务中添加bootstrap.yml,配置nacos地址,当前环境,服务名称,文件后缀名。这些决定了程序启动时去nacos读取那个文件。
配置热更新
Nacos中的配置文件变更后,微服务无需重启就可以感知。不过需要通过下面两种配置实现:
package cn.itcast.user.web;
import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {
@Autowired
private UserService userService;
@Value("${pattern.dateformat}")
private String dataformat;
/**
* 路径: /user/110
*
* @param id 用户id
* @return 用户
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return userService.queryById(id);
}
@GetMapping("data")
public String getDataformat(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dataformat));
}
这样就完成了第一种方式的配置,然后我们看一下当前的显示效果:
将这里的配置修改一下,修改成其他样式都可以,然后我们点击【发布】:
出现这个确认界面,然后点击【确认发布】,之后我们重新访问刚才的Controller:
然后就看到,我们在没有重启服务的情况下,显示的效果就发生了改变,同时,在你的服务日志中,关于这次的配置文件修改也产生了对应的日志:
他会告诉你,dataId就是发生变化的配置文件,通知这些服务去更新一下。
package cn.itcast.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "pattern")
@Component
@Data
public class PatternProperties {
private String dataformat;
在之前学习SpringBoot的时候,我们知道,这种@ConfigurationProperties的方式是一种约定大于规则的方式,也就是说,我们配上一个配置的前缀,这个前缀后面的所有的配置项都会自动注入到类中的与配置名相同的变量中。
然后我们使用这个类中的变量去代替之前使用@Value注入的变量:
package cn.itcast.user.web;
import cn.itcast.user.config.PatternProperties;
import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {
@Autowired
private UserService userService;
// @Value("${pattern.dateformat}")
// private String dataformat;
@Autowired
private PatternProperties patternProperties;
/**
* 路径: /user/110
*
* @param id 用户id
* @return 用户
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return userService.queryById(id);
}
@GetMapping("data")
public String getDataformat(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDataformat()));
}
修改之后发布,那么现在我们再次刷新页面,此时的显示方式应该是将年月日按照斜杠分割开的显示方式:
现在看到确实是这样的,并且我们看到服务的更新日志也提示我们有对应的配置更新:
并且最重要的是,我们并没有做其他的多余的配置,这些都是跟我们之前学习使用@ConfigurationProperties的过程是一样,没有多余的配置,也就是没有之前我们的RefreshScope,这就表示,他推荐我们使用@ConfigurationProperties的方式读取配置,以及做自动注入的配置。
总结:
- 通过@Value注解注入,结合@RefreshScope来刷新
- 通过@ConfigurationProperties注入,自动刷新
- 不是所有的配置都适合放到配置中心,维护起来比较麻烦
- 建议将一些关键参数,需要运行时调整的参数放到nacos配置中心,一般都是自定义配置
微服务配置共享
当多环境中的某个配置的值是一样的,不管环境怎么变,都去这个配置中读取配置值。
- [spring.application.name]-[spring.profiles.active].yaml,例如:userserver-dev.yaml
- [spring.application.name].yaml,例如:userserver.yaml
无论profile如何变化,[spring.application.name].yaml这个文件一定会被加载,因此多环境共享配置可以写入这个文件。
然后我们来到Nacos的配置管理界面,我们新建一个配置文件,这个配置文件的文件名就叫做【userserver.yaml】,然后写入一些配置,至于配置的内容并不是很重要:
package cn.itcast.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "pattern")
@Component
@Data
public class PatternProperties {
private String dateformat;
private String envSharedValue;
然后我们来到user服务的Controller中,添加一个方法,直接将读取配置信息的类返回出去即可,如果对应的变量有内容,则说明成功的读取到了:
@GetMapping("prop")
public PatternProperties patternProperties(){
return patternProperties;
发现已经成功的读取到了两个配置文件,分别是dev环境的配置文件和环境共享配置文件,然后我们再次拷贝一个服务,这次我们将服务的环境改变,然后再次启动这个服务:
有一个配置项叫做【有效配置文件】,对应的英文名叫做【Active profiles】,在这里就可以不修改代码,而改变服务的运行环境,然后我们输入【test】,表示这个服务在测试环境中运行,启动之后,我们访问这个环境下的Controller:
此时启动了一个其他环境中的服务,就无法读取到dev服务中的变量了,但是依然能够读取到共享环境变量中中的属性值,这就是最基本的微服务的配置共享,就是不同环境之间的属性共享。
并且,每个服务所读取的配置文件名字,我们可以在运行日志中,看到服务所读取的内容是什么:
可以看到,这里就是读取了对应的环境配置文件,以及对应的环境共享配置文件。
属性冲突
当环境配置文件与环境共享配置文件中有属性冲突,会应用哪一个属性?又或者,我的云端配置属性与我的本地配置属性有冲突,会应用那个属性?这就是一个属性的优先级的问题。
其实我们可以在不同的配置文件中配置相同的属性,然后在Controller中读取,看最终是谁的值被读取了即可:
我们在三个地方分别配置同一个属性值:pattern.name
package cn.itcast.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "pattern")
@Component
@Data
public class PatternProperties {
private String dateformat;
private String envSharedValue;
private String name;
这一次是环境配置文件被读取,也就是说,当本地配置文件与云端配置文件冲突的时候,是以云端配置文件为准,并且都是云端配置文件,这里显示的是环境配置文件,而不是环境共享配置文件,那么也就说明,是环境配置文件大于环境共享配置文件,那么最终的配置文件优先级就是:
Nacos集群搭建
- 搭建数据库,初始化数据库表结构
- 下载nacos安装包
- 配置nacos
- 启动nacos集群
- nginx反向代理
初始化数据库
Nacos默认数据存储在内嵌数据库Derdy中,不属于生产可用的数据库
/*
* 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 database if not exists nacos;
use nacos;
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,
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 '租户字段',
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 '租户字段',
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');
这里有一个小小的坑,就是如果你去官网复制,那么你大概率复制的就是2.1版本之后的数据库初始SQL语句,但是如果你的安装包用的不是2.1之后的版本,那么在最后的时候,你在新建配置文件的时候会报错,就是提示你【发布失败 请检查参数是否正确】,这时候你就要去检查你的SQL使用的是不是和你的Nacos版本不一致,区别就在于2.1版本之后在第一张表,也就是config_info这张表中多加个一个字段:
而这张表也就是我们写入配置文件的表,而这个字段是非空的,也就是说在早先的版本是没有这个字段的,所以就会报错,如果你报错了,改成早期版本的初始化SQL语句,也就是我上面的语句即可。
下载Nacos
配置Nacos
之前我们基本没有做任何的配置就可以直接使用Nacos,但是对于集群的搭建,我们需要做一些比较复杂的配置。
在conf文件夹中找到cluster.conf.example文件,并复制一份,将后缀名的example去掉,然后打开这个文件:
在这个文件中,我们主要配置的就是服务的节点信息,由于我们是本机启动,所以我们的ip地址都是127.0.0.1,而端口号就根据自己的机器,选择任意三个没有被占用的端口号即可:
127.0.0.1:8845
127.0.0.1:8846
然后来到同一个文件夹下的另一个配置文件:application.properties配置文件,在这里,我们要配置MySQL的相关信息,因为我们的Nacos要将数据存储到MySQL中:
#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
# 表示使用MySQL数据源
spring.datasource.platform=mysql
### Count of DB:
# MySQK数据库的数量
db.num=1
### Connect URL of DB:
# MySQL数据库的连接信息
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
在WIndows中单点启动三台相同的服务,可以将安装包复制三份,然后将服务的端口号修改成三个不同的端口号,然后分别在不同的端口中启动相同的服务即可:
现在三个服务的端口号还没有修改,我们依次修改对应的端口号即可。
修改完成之后就可以启动服务,之前的启动方式我们是在启动程序后面加上了-m参数然后跟上单点启动的参数,但是现在我们用集群启动,就不需要加上参数,直接使用程序驱动即可:
Nginx反向代理
Nginx主要是做反向代理和负载均衡,也就是使用Nginx去管理这三台Nacos实例,我们首先拿到Nginx的安装压缩包:
打开之后,找到http节点,然后将下面的内容粘贴到http节点中任意一个位置即可:
upstream nacos-cluster {
server 127.0.0.1:8845;
server 127.0.0.1:8846;
server 127.0.0.1:8847;
}
server {
listen 1111;
server_name localhost;
location /nacos {
proxy_pass http://nacos-cluster
}
这段配置的意思就是说,upstream中配置的是要做代理的三个节点列表,然后server代理的相关配置,当我们访问localhost的80端口的时候,就相当于是访问上面的三个节点,并且当我们访问/nacos时,就相当于是访问下面的网址,打开nacos的UI管理界面,然后保存退出。
然后我们来到Nginx的主目录中,在这里打开一个黑窗口,输入命令启动Nginx:
开错啦哈哈,你的Nginx并没有运行。因为Nginx的默认端口是80端口,而现在的情况就是你的80端口被占用了,你需要去修改Nginx的默认端口,我改成了81,所以我需要访问下面的网址:
这个界面才是Nginx的正常登录界面,这个坑是因为我按照正常配置并没有看到对应的界面,我就去找找后台的进程去看看Nginx没有启动,但是我启动单点的Nacos能启动,我就想可能是Nginx没启动,没启动的原因是因为端口占用,大部分的服务一开始无法启动就是这个原因,确实是被占用了,就换个端口就行了,然后继续打开Nginx代理的Nacos界面:
只要你通过之前在Nginx中配置的地址和端口进入到Nacos,就表示已经进入了集群的Nacos中。
这里集群的端口号改了,那么在代码那边,之前写的nacos单点的地址就要改成现在的端口,也很简单,就是改成你现在启动的端口号就行,就是你在Nginx中配置的端口号:
之前这里是8848,现在改成1111即可,因为我在Nginx中配置的代理端口号就是1111,然后我们重启这个服务:
在新的界面,就可以看到我们刚才改配置之后重启的服务器就已经转移过来了。
这次写完之后就不一样了,我们在使用了MySQL的集群之后,这里的配置信息就会写入到MySQL中,我们可以看一下配置信息的写入位置:
总结
- 搭建MySQL集群并初始化数据库表
- 下载解压nacos
- 修改集群配置(节点信息)、数据库配置
- 分别启动多个nacos节点
- nginx反向代理
- 一个坑就是Nacos的2.1版本之前和之后的初始化数据库的SQL语句不一样
- 一个坑就是Nginx启动成功与失败没有提示,你只能自己看是否启动成功,并且如果端口占用就需要去修改默认的启动端口号。
- 在使用IP地址的时候,我非常的建议是使用真实的IP,别用127.0.0.1,有时候可能会在连接集群的时候报错,但是你就是不知道怎么回事,就是因为IP地址导致的无法找到对应的服务,所以还是用你的IP代替127.0.0.1吧。
相关文章:
SpringCLoud——Nacos配置中心
Nacos实现配置管理 统一配置管理 配置更新热更新 统一配置的创建是在UI界面中完成的: 首先我们点击【配置管理】然后点击【配置列表】: 然后我们就看到了配置管理界面,但是此时这里是空的,我们可以创建一些配置文件:…...
05目标检测-区域推荐(Anchor机制详解)
目录 一、问题的引入 二、解决方案-设定的anchor boxes 1.高宽比(aspect ratio)的确定 2.尺度(scale)的确定 3.anchor boxes数量的确定 三、Anchor 的在目标检测中是怎么用的 1、anchor boxes对真值bounding box编码的步骤 2、为什么要回归偏移量…...
SpringBoot如何保证接口安全?
对于互联网来说,只要你系统的接口暴露在外网,就避免不了接口安全问题。如果你的接口在外网裸奔,只要让黑客知道接口的地址和参数就可以调用,那简直就是灾难。 举个例子:你的网站用户注册的时候,需要填写手…...
构建可扩展的应用:六边形架构详解与实践
面试题分享 云数据解决事务回滚问题 点我直达 2023最新面试合集链接 2023大厂面试题PDF 面试题PDF版本 java、python面试题 项目实战:AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮…...
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 解决方案
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 解决方案 使用Git提交时报错,代码如下: $ git push -u origin "master" Counting objects: 100% (95/95), done. Delta compression using up to 12 threads Compressing ob…...
基于ssm智能停车场031
大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…...
【Git】万字git与gitHub
🎄欢迎来到边境矢梦的csdn博文🎄 🎄本文主要梳理在git和GitHub时的笔记与感言 🎄 🌈我是边境矢梦,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下🫰&…...
C++版本的OpenCV实现二维图像的卷积定理(通过傅里叶变换实现二维图像的卷积过程,附代码!!)
C版本的OpenCV库实现二维图像的卷积定理过程详解 前言一、卷积定理简单介绍二、不同卷积过程对应的傅里叶变换过程1、“Same”卷积2、“Full”卷积3、“Valid”卷积 三、基于OpenCV库实现的二维图像卷积定理四、基于FFTW库实现的二维图像卷积定理五、总结与讨论 前言 工作中用…...
打开深度学习的锁:(1)入门神经网络
打开深度学习的锁 导言PS:神经网络的训练过程一、导入的包和说明二、数据的预处理2.1 数据集说明2.2 数据集降维度并且转置2.3 数据预处理完整代码 三、逻辑回归3.1 线性回归函数公式3.2 sigmoid函数公式 四、初始化函数五、构建逻辑回归的前向传播和后向传播5.1 损…...
02- pytorch 实现 RNN
一 导包 import torch from torch import nn from torch.nn import functional as F import dltools 1.1 导入训练数据 batch_size, num_steps 32, 35 # 更改了默认的文件下载方式,需要将 article 文件放入该文件夹 train_iter, vocab dltools.load_data_time_…...
算法课作业1
https://vjudge.net/contest/581138 A - Humidex 模拟题 题目大意 给三个类型数字通过公式来回转化 思路 求e的对数有log函数,不懂为什么不会出精度错误,很迷,给的三个数字也没有顺序,需要多判断。 #include<cstdio>…...
linux文本处理 两行变一行
linux简单文本处理 [rootkvm ~]# cat test 1.1.1.1 test1 2.2.2.2 test2 3.3.3.3 test3 192.168.1.2 test4 10.23.9.19 test5 cat test | awk /^[0-9]/{T$1;next;}{print T,$1}1.1.1.1 test1 2.2.2.2 test2 3.3.3.3 test3 192.168.1.2 test4 10.23.9.19 test5 cat test | …...
第二次面试 9.15
首先就是自我介绍 项目拷打 总体介绍一下项目 谈一下对socket的理解 在数据接收阶段,如何实现一个异步的数据处理 谈一谈对qt信号槽的理解 有想过如何去编写一个信号槽吗 你是如何使用CMAKE编译文件的 C11特性了解些啥 shared_ptr 和 unique_ptr 的运用场景 …...
基于matlab实现的平面波展开法二维声子晶体能带计算程序
Matlab 平面波展开法计算二维声子晶体二维声子晶体带结构计算,材料是铅柱在橡胶基体中周期排列,格子为正方形。采用PWE方法计算 完整程序: %%%%%%%%%%%%%%%%%%%%%%%%% clear;clc;tic;epssys1.0e-6; %设定一个最小量,避免系统截断误差或除零错…...
Minio入门系列【2】纠删码
1 纠删码 Minio使用纠删码erasure code和校验和checksum来保护数据免受硬件故障和无声数据损坏。 即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据 1.1 什么叫纠删码 纠删码是一种用于重建丢失或损坏数据的数学算法。 纠删码(e…...
基于永磁同步发电机的风力发电系统研究(Simulink实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
5.后端·新建子模块与开发(自动模式)
文章目录 学习资料自动生成模式创建后端三层 学习资料 https://www.bilibili.com/video/BV13g411Y7GS?p11&spm_id_frompageDriver&vd_sourceed09a620bf87401694f763818a31c91e 自动生成模式创建后端三层 首先,运行起来若依的前后端整个项目,…...
vue的data为什么要写成data(return{})这样而不是data:{}这样?
在Vue.js中,为什么要将data写成一个返回对象的函数data()而不是一个普通的对象data: {} 为什么? 因为Vue.js的组件实例是可复用的,而且它们可以在应用中多次实例化。通过将data定义为一个返回对象的函数,可以确保每个组件实例都…...
MySQL基础运维知识点大全
一. MySQL基本知识 1. 目录的功能 通用 Unix/Linux 二进制包的 MySQL 安装下目录的相关功能 目录目录目录binMySQLd服务器,客户端和实用程序docs信息格式的 MySQL 手册manUnix 手册页include包括(头)文件lib图书馆share用于数据库安装的错…...
javascript获取样式表的规则及读取与写入
CSSStyleSheet是继承了StyleSheet的接口属性,它是用于找当前文档中的<link rel“” href“”…>这样文件的,有以下属性:lenght,cssRules,title,href,type,deleteRule,insertRule等 CSSStyleRule是继承于CSSRule,它是用于找<link re…...
什么是promise?
是JavaScript中用于处理异步操作的一种机制。 异步操作,例如从服务器获取数据、读取文件、执行数据库查询等等。 经典使用:Axios 是一个基于Promise的HTTP客户端 Promise具有三个状态: Pending(待定):Pr…...
从零开始学习软件测试-第45天笔记
monkey事件 事件:对app进行的操作,比如触摸事件,滑动事件...动作:构成一个事件所需要的步骤。 调整事件的百分比 adb shell monkey -p 包名 -v -v --pct-xxx 百分比 次数>输出文件的路径 分析日志有没有报错 到日志中去找…...
visual studio常用快捷键
CtrlM、CtrlO 折叠到定义 CtrlM、CtrlM 折叠当前定义 CtrlM、CtrlA 折叠全部 CtrlK、CtrlD 自动编排代码格式 F12 转到定义 ShiftF12 查看所有定义 ctrl] 转到定义首部或尾部 ctrlX 未选中文本时,剪切/删除光标所在行。ctrlV 未选中文本时,粘贴到…...
数据变换:数据挖掘的准备工作之一
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…...
Go语言实践案例之简单字典
一、程序要实现效果: 在命令行调用程序的时候,可以在命令行的后面查询一个单词,然后会输出单词的音标和注释。 二、思路分析: 定义一个结构体 DictRequest,用于表示翻译请求的数据结构。其中包含了 TransType&#…...
笔试面试相关记录(3)
(1)String String和String.append()的底层实现 C中string append函数的使用与字符串拼接「建议收藏」-腾讯云开发者社区-腾讯云 (tencent.com) String String 在 第二个String中遇到\0就截止,append()的方法则是所有字符都会加在后面。 &…...
第6章_瑞萨MCU零基础入门系列教程之串行通信接口(SCI)
本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…...
开源免费的流程图软件draw.io
2023年9月16日,周六上午 想买微软的visio,但发现不是很值得,因为我平时也不是经常需要画图。 所以我最后还是决定使用开源免费的draw.io来画图 draw.io网页版的网址: Flowchart Maker & Online Diagram Software draw.io的…...
Python绘图系统19:添加时间轴以实现动态绘图
文章目录 时间轴单帧跳转源代码 Python绘图系统: 📈从0开始的3D绘图系统📉一套3D坐标,多个函数📊散点图、极坐标和子图自定义控件:绘图风格📉风格控件📊定制绘图风格坐标设置进阶&a…...
深度解析shell脚本的命令的原理之rm
rm 是 Unix/Linux 系统中的一个基本命令,用于删除文件或目录。以下是对这个命令的深度分析: 基本操作:rm 命令删除一个或多个文件或目录。这是通过从文件系统中移除链接来完成的。在 Unix/Linux 中,文件是通过链接(可以…...
erp系统是怎样的一个软件/优化关键词排名
1. 定义 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。 使用 Lambda 表达式可以使代码变的更加简洁紧凑。 1.1 通用定义 lambda 表达…...
怎么看个人做的付费视频网站/深圳seo云哥
目录 正则表达式语法规则 字符 预定义字符集 数量词 贪婪和非贪婪 边界匹配(不消耗匹配字符串中的字符) 逻辑、分组 Python re模块介绍 引入模块 正则检索 正则分割字符串 字符串替换 分组引用 匹配中文 正则表达式语法规则 百度百科简介:…...
从哪些方面做好网站的seo/西安疫情最新数据
问题mysqlbinlog 是将 binlog 解析成可读可执行的 SQL 的重要工具。但解析体积较大的 binlog 时,如何查看 mysqlbinlog 的执行进度就变成了一个问题,mysqlbinlog 并未提供 –progress 这样的参数。那要怎么查看 mysqlbinlog 的解析进度?实验我…...
电脑上做网站/培训机构
使用for(String item:list)会很好,但是它只会迭代一个列表,而你需要一个显式迭代器用于另一个列表.或者,您可以为两者使用显式迭代器.以下是问题的示例,以及使用索引for循环的解决方案:import java.util.*;public class ListsToMap {static public void …...
网站建设 钱/百度应用商店下载
我们平时在linux下切换用户后命令行为什么会变成-bash-3.2$呢,我们来分析一下,这就是跟linux的机制有关联了,因为在linux下每次通过useradd创建新的用户时,都会将所有的配置文件从/etc/skel复制到新用户的主目录下,一般…...
郑州网站建设公司 艾特/移动建站模板
办公室是企业办公的地方,对于企业而言,一个办公室的形象对于企业在团队精神、宣传展示时十分关键,对于整体实力协作、客户信赖的展示也是有一定的影响。人们在对办公空间合理、利润较大化利用的同时,如何打造一个时尚的办公空间设…...