一、初始微服务
1 单体架构
- 将业务的所有功能集中在一个项目中开发,打成一个包部署
- 优点:架构简单、成本低、易部署;缺点:耦合度高、维护升级困难
2 分布式架构
- 根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,称为一个服务,比如一个系统的用户模块和支付模块
- 优点:耦合度低、利于升级和服务;缺点:各个服务直接的调复杂
3 微服务架构
- 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
- 自治:团队独立、技术独立、数据独立,独立部署和交付
- 面向服务:服务提供统一标准的接口,与语言和技术无关
- 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
4 微服务技术对比
5 服务拆分
5.1 原则
- 不同微服务,不要重复开发相同业务
- 微服务数据独立,不要访问其它微服务的数据库,其他服务的数据库是不知道的,所以不能直接访问
- 微服务可以将自己的业务暴露为接口,供其它微服务调用
5.2 demo
有一个订单模块和一个用户模块。两个模块相互独立,都有自己对应的数据库。根据id分别查询用户和订单,要求在订单中嵌套用户。
订单走8081端口、用户走8080端口
用户查询:
订单查询:
{"id":101,"price":699900,"name":"Apple 苹果 iPhone 12 ","num":1,"userId":1,"user":null}
可以看到,因为两个模块相互独立,没有嵌套sql,所以订单查询出来的用户为null。
解决方法:
1> 在启动类中注入RestTemplate
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}/*** 创建RestTemplate并注入容器* @return*/@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}}
2> 在sevice方法接口中向用户模块发送http请求,查询User数据
public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);//2. 利用restTemplate发送http请求String url = "http://localhost:8081/user/" + order.getUserId();User user = restTemplate.getForObject(url, User.class);//3. 封装user数据order.setUser(user);// 4.返回return order;}
查询结果:
{"id":101,"price":699900,"name":"Apple 苹果 iPhone 12 ","num":1,"userId":1,"user":{"id":1,"username":"柳岩","address":"湖南省衡阳市"}}
通过上述步骤就实现了一个最基本的服务拆分
二、 Eureka注册中心
1 拆分问题
如果我们的服务提供者有多个部署,多个ip地址和端口,那么消费者就不知道该调用哪一个服务,如下图:
需思考:
- order-service在发起远程调用的时候,该如何得知user-service实例的ip地址和端口?
- 有多个user-service实例地址,order-service调用时该如何选择?
- order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
2 Eureka的结构和作用
上述思考问题都需要SpringCloud中的注册中心来解决来解决,常用的就是Eureka
问题回答:
问题1:order-service如何得知user-service实例地址?
- 服务注册:user-service启动后会将自己的信息注册到eureka-server(Eureka服务端)
- eureka-server保存服务名到实例地址之间的映射
- 服务拉取:order-service根据服务名称拉取实例地址列表
问题2:order-service如何从多个user-service实例中选择具体的实例?
- order-service从实例列表中利用负载均衡算法选中一个实例地址
- 向该实例地址发起远程调用
问题3:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
- user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳
- 当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
- order-service拉取服务时,就能将故障实例排除了
注意:一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册(生产者)、服务发现(消费者)等功能统一封装到了eureka-client端
3 搭建Eureka注册中心
3.1 导入依赖
<!--Eureka服务端依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>
3.2 编写启动类
//使用@SpringBootApplication时 启动类要放到子包中 如com.qing下 不能直接放到java包下@SpringBootApplication@EnableEurekaServerpublic class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}}
3.3 编写配置文件
server:#eureka服务端口port: 10086spring:application:#eureka服务名称name: eureka-servereureka:client:#eureka地址信息service-url:defaultZone: http://127.0.0.1:10086/eureka
访问:http://127.0.0.1:10086 即可成功
4 服务注册(生产者)
4.1 导入依赖
<!--Eureka客户端依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
4.2 编写配置文件
spring:application:name: orderserviceeureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
4.3 注册多个服务
首先点击右上角的Edit Configurations
勾选Allow parallel run
最后在配置文件中更改端口 避免冲突
5 服务发现(消费者)
4.1 导入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
4.2 编写配置文件
spring:application:name: orderserviceeureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
4.3 服务拉取和负载均衡
1> 服务拉取:修改消费者接口方法中的url路径,用服务名代替ip、端口
原先的:
修改后的:
2> 负载均衡:在消费者的主启动类中的RestTemplate上添加@LoadBalanced注解, 默认轮询
三、Ribbon
1 负载均衡原理
基本流程如下:
- 拦截我们的RestTemplate请求http://userservice/user/1
- RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
- DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
- eureka返回列表,localhost:8081、localhost:8082
- IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
- RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求
2 负载均衡策略
负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:
不同规则的含义如下:
| 内置负载均衡规则类 | 规则描述 |
|---|---|
| RoundRobinRule | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
| AvailabilityFilteringRule | 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。 |
| WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
| ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。 |
| BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器。 |
| RandomRule | 随机选择一个可用的服务器。 |
| RetryRule | 重试机制的选择逻辑 |
默认的实现就是ZoneAvoidanceRule,是一种轮询方案
3 自定义负载均衡策略
3.1 代码方式
编写一个IRoleConfig配置类,注入自定义配置规则(全局配置 对任何服务都生效)
@Configurationpublic class IRoleConfig {@Beanpublic IRule myIRole() {//随机策略return new RandomRule();//简单轮询策略//return new RoundRobinRule();}}
3.2 配置文件方式
application.yml文件中,添加新的配置(指定服务配置)
# 给某个微服务配置负载均衡规则,这里是userservice服务userservice:ribbon:# 负载均衡规则NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
注意:一般用默认的负载均衡规则,不做修改。
4 饥饿加载
可以看到第一次访问时用时398ms,第二次只用了18ms,两次请求耗时相差几十倍。
这就是Ribbon默认的懒加载策略,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
可以通过配置饥饿加载,让项目启动时加载,减少第一次访问的时间:
ribbon:eager-load:#开启饥饿加载enabled: true#指定服务名生效clients:- userservice#- xxxservice
四、Nacos注册中心
1 安装启动
安装后点击bin目录下的startup.cmd,第一次直接点击启动会报错。原因是nacos默认的都是集群模式,这里单机测试就是用单机模式。
解决方法:
1> 右键点击编辑startup.cmd
2> 通过cmd启动,输入命令startup.cmd -m standalone(推荐使用)
启动成功后访问http://192.168.137.1:8848/nacos/index.html 账号:nacos 密码:nacos
2 服务注册
2.1 引入依赖
<!--父工程引入SpringCloudAlibaba的nacos管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.6.RELEASE</version><type>pom</type><scope>import</scope></dependency><!--生产者消费者引入nacos-discovery依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
引入nacos-discovery依赖后需要注释掉原来的Eureka依赖
2.2 修改配置文件
application.yml中添加nacos地址:
spring:cloud:nacos:server-addr: localhost:8848
要注释掉之前的Eureka配置
配置好后启动生产者消费者,在Nacos控制台就可以看到服务注册成功
3 配置集群
一个服务可以有多个实例,如一个user-service可以有127.0.0.1:8081 127.0.0.1:8082 127.0.0.1:8083。每个实例又可以分布在不同的机房,如
- 127.0.0.1:8081,在上海机房
- 127.0.0.1:8082,在上海机房
- 127.0.0.1:8083,在杭州机房
Nacos就将同一机房内的实例 划分为一个集群。
3.1 修改配置文件
spring:cloud:nacos:server-addr: localhost:8848discovery:#集群名 HZ代指杭州cluster-name: HZ
配置成功后,启动两个HZ实例,再启动一个SH实例,可以在nacos控制台看到:
3.2 修改集群负载均衡
1> 修改order-service(消费者)的application.yml文件,修改负载均衡规则:
userservice:ribbon:# 负载均衡规则 NacosRule:优先选择本地集群 本地集群内部随机访问NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
2> 之前order-service(消费者)配置了自定义负载均衡IRole规则的需要将其注销
4实例权重配置
在nacos控制台可以修改每个实例的权重。服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
在控制台点击编辑就可以修改实例的权重,权重比越大,访问的次数越多,如果实例权重修改为0,则不会访问这个实例。
5 环境隔离
Nacos提供了namespace来实现环境隔离功能。
- nacos中可以有多个namespace
- namespace下可以有group、service等
- 不同namespace之间相互隔离,例如不同namespace的服务互相不可见
1> nacos控制台创建namespace
2> 修改配置文件
只需要在配置文件中新增一个namespace: spaceId即可,spaceId是命名空间的ID,可以在控制台查看
6 Eureka、Nacos区别
Nacos的服务实例分为两种l类型:
- 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。
- 非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。
在配置文件中设置非临时实例
spring:cloud:nacos:discovery:# 设置为非临时实例ephemeral: false
nacos工作原理:
Nacos与eureka的共同点
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
Nacos与Eureka的区别
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
- 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
- Nacos支持服务列表变更的消息推送模式(pull+push),服务列表更新更及时;Eureka是30s更新一次,更新不够及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
五 Nacos配置管理
当微服务配置的实例越来越多时,管理一个实例的配置文件就会很繁琐,特别是一些相同的、经常修改的配置,如时间格式等。
可以在Nacos管理控制台进行配置管理,Nacos一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新。
1 统一配置
1.1 nacos添加配置文件
点击配置管理->配置列表->新增配置
1.2 配置拉取
微服务要拉取nacos管理端的配置文件,与本地配置文件合并后才能完成项目启动
因此spring引入了一种新的配置文件:bootstrap.yaml文件,会在application.yml之前被读取,流程如下:
1》 在生产者pom文件中引入依赖
<!--nacos配置管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
2》 添加bootstrap.yaml
spring:application:name: userservice # 服务名称profiles:active: dev #开发环境,这里是devcloud:nacos:server-addr: localhost:8848 # Nacos地址config:file-extension: yaml # 文件后缀名
这里会根据${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}作为文件id,来读取配置
与nacos控制台的配置文件名(userservice-dev.yaml)一一对应
测试:
@Slf4j@RestController@RequestMapping("/user")public class UserController {@Autowiredprivate UserService userService;//用 @Value拉取远程配置@Value("${pattern.dateformat}")private String dateformat;@GetMapping("now")public String now(){return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));}// ...略}
1.3 出现问题
如果启动报错,大部分原因可能如下:
- nacos控制台的配置文件和服务列表不在同一个环境下,所属namespace不同,测试时我都放在public环境下
- nacos控制台的配置文件名和本地bootstrap.yaml文件中没有一一对应
- bootstrap.yaml配置文件加载不出,需添加cloud-bootstrap依赖
<!--cloud-bootstrap--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.0.3</version></dependency>
2 配置热更新
热更新:每当我们修改了nacos控制台中的配置时,希望不需要重启服务就能实现动态修改,这就是配置文件热更新
2.1 @Value+@RefreshScope
在@Value注入的变量所在类上添加注解@RefreshScope:
2.2 @ConfigurationProperties
使用@ConfigurationProperties注解代替@Value注解+@RefreshScope注解
可以新建一个配置类PatternPropertiesConfig,在里面拉取nacos控制台中所有的配置:
@Data@Component@ConfigurationProperties(prefix = "pattern")public class PatternPropertiesConfig {private String dateformat;}
使用时只需要注入配置类就行
@AutowiredPatternPropertiesConfig patternPropertiesConfig;
3 配置共享
微服务启动时,会去nacos读取多个配置文件,例如:
[spring.application.name]-[spring.profiles.active].yaml,例如:userservice-dev.yaml(开发环境)[spring.application.name].yaml,例如:userservice.yaml(全局环境)
而[spring.application.name].yaml(userservice.yaml)不包含环境,因此可以被多个环境共享
3.1 测试
1》 在nacos控制台新建一个环境配置,取名userservice.yaml,作为全局环境配置
2》 PatternPropertiesConfig配置类中新增envSharedValue属性值
3》 修改bootstrap.yaml配置,将发布版本改为test,重启userservice8082端口,8081仍然为dev版本不变
可以看到8082端口拿不到8081dev版本的dateformat值
3.2 配置共享的优先级
当nacos、服务本地同时出现相同属性时,优先级有高低之分:

4 搭建nacos集群
搭建集群的基本步骤:
- 搭建数据库,初始化数据库表结构
- 下载nacos安装包
- 配置nacos
- 启动nacos集群
- nginx反向代理
4.1 搭建数据库
新建一个数据库,命名为nacos,执行SQL
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');
4.2 配置Nacos
1》 进入nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf:
2》 然后添加内容:
127.0.0.1:8845127.0.0.1.8846127.0.0.1.8847
3》 修改application.properties文件,修改数据库配置
数据库的账号密码和数据库名要正确
4》 启动nacos,因为是集群启动,所以不需要在cmd窗口加-M参数了 直接双击startup.cmd即可
4.3 启动nacos
将nacos文件夹复制三份,分别命名为:nacos1、nacos2、nacos3

然后分别修改三个文件夹中的application.properties,
nacos1:
server.port=8845
nacos2:
server.port=8846
nacos3:
server.port=8847
4.4 Nginx反向代理
修改conf/nginx.conf文件,配置如下:
upstream nacos-cluster {server 127.0.0.1:8845;server 127.0.0.1:8846;server 127.0.0.1:8847;}server {listen 80;server_name localhost;location /nacos {proxy_pass http://nacos-cluster;}}
需加载http括号中
启动ngnix,访问http://localhost/nacos即可。
因为配置了ngnix代理,所以代码中所有的nacos地址都需要改成localhost:80
