一、初始微服务

1 单体架构

  • 将业务的所有功能集中在一个项目中开发,打成一个包部署
  • 优点:架构简单、成本低、易部署;缺点:耦合度高、维护升级困难

2 分布式架构

  • 根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,称为一个服务,比如一个系统的用户模块和支付模块
  • 优点:耦合度低、利于升级和服务;缺点:各个服务直接的调复杂

3 微服务架构

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
  • 自治:团队独立、技术独立、数据独立,独立部署和交付
  • 面向服务:服务提供统一标准的接口,与语言和技术无关
  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

4 微服务技术对比

5 服务拆分

5.1 原则

  • 不同微服务,不要重复开发相同业务
  • 微服务数据独立,不要访问其它微服务的数据库,其他服务的数据库是不知道的,所以不能直接访问
  • 微服务可以将自己的业务暴露为接口,供其它微服务调用

5.2 demo

有一个订单模块和一个用户模块。两个模块相互独立,都有自己对应的数据库。根据id分别查询用户和订单,要求在订单中嵌套用户。

订单走8081端口、用户走8080端口

用户查询:

订单查询:

  1. {"id":101,"price":699900,"name":"Apple 苹果 iPhone 12 ","num":1,"userId":1,"user":null}

可以看到,因为两个模块相互独立,没有嵌套sql,所以订单查询出来的用户为null。

解决方法:

1> 在启动类中注入RestTemplate

  1. public class OrderApplication {
  2. public static void main(String[] args) {
  3. SpringApplication.run(OrderApplication.class, args);
  4. }
  5. /**
  6. * 创建RestTemplate并注入容器
  7. * @return
  8. */
  9. @Bean
  10. public RestTemplate restTemplate(){
  11. return new RestTemplate();
  12. }
  13. }

2> 在sevice方法接口中向用户模块发送http请求,查询User数据

  1. public Order queryOrderById(Long orderId) {
  2. // 1.查询订单
  3. Order order = orderMapper.findById(orderId);
  4. //2. 利用restTemplate发送http请求
  5. String url = "http://localhost:8081/user/" + order.getUserId();
  6. User user = restTemplate.getForObject(url, User.class);
  7. //3. 封装user数据
  8. order.setUser(user);
  9. // 4.返回
  10. return order;
  11. }

查询结果:

  1. {"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 导入依赖

  1. <!--Eureka服务端依赖-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  5. </dependency>

3.2 编写启动类

  1. //使用@SpringBootApplication时 启动类要放到子包中 如com.qing下 不能直接放到java包下
  2. @SpringBootApplication
  3. @EnableEurekaServer
  4. public class EurekaApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(EurekaApplication.class, args);
  7. }
  8. }

3.3 编写配置文件

  1. server:
  2. #eureka服务端口
  3. port: 10086
  4. spring:
  5. application:
  6. #eureka服务名称
  7. name: eureka-server
  8. eureka:
  9. client:
  10. #eureka地址信息
  11. service-url:
  12. defaultZone: http://127.0.0.1:10086/eureka

访问:http://127.0.0.1:10086 即可成功

4 服务注册(生产者)

4.1 导入依赖

  1. <!--Eureka客户端依赖-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>

4.2 编写配置文件

  1. spring:
  2. application:
  3. name: orderservice
  4. eureka:
  5. client:
  6. service-url:
  7. defaultZone: http://127.0.0.1:10086/eureka

4.3 注册多个服务

首先点击右上角的Edit Configurations

勾选Allow parallel run

最后在配置文件中更改端口 避免冲突

5 服务发现(消费者)

4.1 导入依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4. </dependency>

4.2 编写配置文件

  1. spring:
  2. application:
  3. name: orderservice
  4. eureka:
  5. client:
  6. service-url:
  7. 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配置类,注入自定义配置规则(全局配置 对任何服务都生效)

  1. @Configuration
  2. public class IRoleConfig {
  3. @Bean
  4. public IRule myIRole() {
  5. //随机策略
  6. return new RandomRule();
  7. //简单轮询策略
  8. //return new RoundRobinRule();
  9. }
  10. }

3.2 配置文件方式

application.yml文件中,添加新的配置(指定服务配置)

  1. # 给某个微服务配置负载均衡规则,这里是userservice服务
  2. userservice:
  3. ribbon:
  4. # 负载均衡规则
  5. NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

注意:一般用默认的负载均衡规则,不做修改。

4 饥饿加载

可以看到第一次访问时用时398ms,第二次只用了18ms,两次请求耗时相差几十倍。

这就是Ribbon默认的懒加载策略,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

可以通过配置饥饿加载,让项目启动时加载,减少第一次访问的时间:

  1. ribbon:
  2. eager-load:
  3. #开启饥饿加载
  4. enabled: true
  5. #指定服务名生效
  6. clients:
  7. - userservice
  8. #- 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 引入依赖

  1. <!--父工程引入SpringCloudAlibaba的nacos管理依赖-->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  5. <version>2.2.6.RELEASE</version>
  6. <type>pom</type>
  7. <scope>import</scope>
  8. </dependency>
  9. <!--生产者消费者引入nacos-discovery依赖-->
  10. <dependency>
  11. <groupId>com.alibaba.cloud</groupId>
  12. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  13. </dependency>

引入nacos-discovery依赖后需要注释掉原来的Eureka依赖

2.2 修改配置文件

application.yml中添加nacos地址:

  1. spring:
  2. cloud:
  3. nacos:
  4. 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 修改配置文件

  1. spring:
  2. cloud:
  3. nacos:
  4. server-addr: localhost:8848
  5. discovery:
  6. #集群名 HZ代指杭州
  7. cluster-name: HZ

配置成功后,启动两个HZ实例,再启动一个SH实例,可以在nacos控制台看到:

3.2 修改集群负载均衡

1> 修改order-service(消费者)的application.yml文件,修改负载均衡规则:

  1. userservice:
  2. ribbon:
  3. # 负载均衡规则 NacosRule:优先选择本地集群 本地集群内部随机访问
  4. 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类型:

  • 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型
  • 非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。

在配置文件中设置非临时实例

  1. spring:
  2. cloud:
  3. nacos:
  4. discovery:
  5. # 设置为非临时实例
  6. 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文件中引入依赖

  1. <!--nacos配置管理依赖-->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  5. </dependency>

2》 添加bootstrap.yaml

  1. spring:
  2. application:
  3. name: userservice # 服务名称
  4. profiles:
  5. active: dev #开发环境,这里是dev
  6. cloud:
  7. nacos:
  8. server-addr: localhost:8848 # Nacos地址
  9. config:
  10. file-extension: yaml # 文件后缀名

这里会根据${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}作为文件id,来读取配置

与nacos控制台的配置文件名(userservice-dev.yaml)一一对应

测试:

  1. @Slf4j
  2. @RestController
  3. @RequestMapping("/user")
  4. public class UserController {
  5. @Autowired
  6. private UserService userService;
  7. //用 @Value拉取远程配置
  8. @Value("${pattern.dateformat}")
  9. private String dateformat;
  10. @GetMapping("now")
  11. public String now(){
  12. return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
  13. }
  14. // ...略
  15. }

1.3 出现问题

如果启动报错,大部分原因可能如下:

  • nacos控制台的配置文件和服务列表不在同一个环境下,所属namespace不同,测试时我都放在public环境下
  • nacos控制台的配置文件名和本地bootstrap.yaml文件中没有一一对应
  • bootstrap.yaml配置文件加载不出,需添加cloud-bootstrap依赖
  1. <!--cloud-bootstrap-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-bootstrap</artifactId>
  5. <version>3.0.3</version>
  6. </dependency>

2 配置热更新

热更新:每当我们修改了nacos控制台中的配置时,希望不需要重启服务就能实现动态修改,这就是配置文件热更新

2.1 @Value+@RefreshScope

在@Value注入的变量所在类上添加注解@RefreshScope:

2.2 @ConfigurationProperties

使用@ConfigurationProperties注解代替@Value注解+@RefreshScope注解

可以新建一个配置类PatternPropertiesConfig,在里面拉取nacos控制台中所有的配置:

  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "pattern")
  4. public class PatternPropertiesConfig {
  5. private String dateformat;
  6. }

使用时只需要注入配置类就行

  1. @Autowired
  2. PatternPropertiesConfig 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、服务本地同时出现相同属性时,优先级有高低之分:

SpringCloud学习笔记 - 图1

4 搭建nacos集群

搭建集群的基本步骤:

  • 搭建数据库,初始化数据库表结构
  • 下载nacos安装包
  • 配置nacos
  • 启动nacos集群
  • nginx反向代理

4.1 搭建数据库

新建一个数据库,命名为nacos,执行SQL

  1. CREATE TABLE `config_info` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  3. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  4. `group_id` varchar(255) DEFAULT NULL,
  5. `content` longtext NOT NULL COMMENT 'content',
  6. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  7. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  8. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  9. `src_user` text COMMENT 'source user',
  10. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  11. `app_name` varchar(128) DEFAULT NULL,
  12. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  13. `c_desc` varchar(256) DEFAULT NULL,
  14. `c_use` varchar(64) DEFAULT NULL,
  15. `effect` varchar(64) DEFAULT NULL,
  16. `type` varchar(64) DEFAULT NULL,
  17. `c_schema` text,
  18. PRIMARY KEY (`id`),
  19. UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
  20. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
  21. /******************************************/
  22. /* 数据库全名 = nacos_config */
  23. /* 表名称 = config_info_aggr */
  24. /******************************************/
  25. CREATE TABLE `config_info_aggr` (
  26. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  27. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  28. `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  29. `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  30. `content` longtext NOT NULL COMMENT '内容',
  31. `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  32. `app_name` varchar(128) DEFAULT NULL,
  33. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  34. PRIMARY KEY (`id`),
  35. UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
  36. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
  37. /******************************************/
  38. /* 数据库全名 = nacos_config */
  39. /* 表名称 = config_info_beta */
  40. /******************************************/
  41. CREATE TABLE `config_info_beta` (
  42. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  43. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  44. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  45. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  46. `content` longtext NOT NULL COMMENT 'content',
  47. `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  48. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  49. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  50. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  51. `src_user` text COMMENT 'source user',
  52. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  53. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  54. PRIMARY KEY (`id`),
  55. UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
  56. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
  57. /******************************************/
  58. /* 数据库全名 = nacos_config */
  59. /* 表名称 = config_info_tag */
  60. /******************************************/
  61. CREATE TABLE `config_info_tag` (
  62. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  63. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  64. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  65. `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  66. `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  67. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  68. `content` longtext NOT NULL COMMENT 'content',
  69. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  70. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  71. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  72. `src_user` text COMMENT 'source user',
  73. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  74. PRIMARY KEY (`id`),
  75. UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
  76. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
  77. /******************************************/
  78. /* 数据库全名 = nacos_config */
  79. /* 表名称 = config_tags_relation */
  80. /******************************************/
  81. CREATE TABLE `config_tags_relation` (
  82. `id` bigint(20) NOT NULL COMMENT 'id',
  83. `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  84. `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  85. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  86. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  87. `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  88. `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  89. PRIMARY KEY (`nid`),
  90. UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  91. KEY `idx_tenant_id` (`tenant_id`)
  92. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
  93. /******************************************/
  94. /* 数据库全名 = nacos_config */
  95. /* 表名称 = group_capacity */
  96. /******************************************/
  97. CREATE TABLE `group_capacity` (
  98. `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  99. `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
  100. `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  101. `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  102. `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  103. `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
  104. `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  105. `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  106. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  107. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  108. PRIMARY KEY (`id`),
  109. UNIQUE KEY `uk_group_id` (`group_id`)
  110. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
  111. /******************************************/
  112. /* 数据库全名 = nacos_config */
  113. /* 表名称 = his_config_info */
  114. /******************************************/
  115. CREATE TABLE `his_config_info` (
  116. `id` bigint(64) unsigned NOT NULL,
  117. `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  118. `data_id` varchar(255) NOT NULL,
  119. `group_id` varchar(128) NOT NULL,
  120. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  121. `content` longtext NOT NULL,
  122. `md5` varchar(32) DEFAULT NULL,
  123. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  124. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  125. `src_user` text,
  126. `src_ip` varchar(50) DEFAULT NULL,
  127. `op_type` char(10) DEFAULT NULL,
  128. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  129. PRIMARY KEY (`nid`),
  130. KEY `idx_gmt_create` (`gmt_create`),
  131. KEY `idx_gmt_modified` (`gmt_modified`),
  132. KEY `idx_did` (`data_id`)
  133. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
  134. /******************************************/
  135. /* 数据库全名 = nacos_config */
  136. /* 表名称 = tenant_capacity */
  137. /******************************************/
  138. CREATE TABLE `tenant_capacity` (
  139. `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  140. `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  141. `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  142. `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  143. `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  144. `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
  145. `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  146. `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  147. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  148. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  149. PRIMARY KEY (`id`),
  150. UNIQUE KEY `uk_tenant_id` (`tenant_id`)
  151. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
  152. CREATE TABLE `tenant_info` (
  153. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  154. `kp` varchar(128) NOT NULL COMMENT 'kp',
  155. `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  156. `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  157. `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  158. `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  159. `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
  160. `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
  161. PRIMARY KEY (`id`),
  162. UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  163. KEY `idx_tenant_id` (`tenant_id`)
  164. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
  165. CREATE TABLE `users` (
  166. `username` varchar(50) NOT NULL PRIMARY KEY,
  167. `password` varchar(500) NOT NULL,
  168. `enabled` boolean NOT NULL
  169. );
  170. CREATE TABLE `roles` (
  171. `username` varchar(50) NOT NULL,
  172. `role` varchar(50) NOT NULL,
  173. UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
  174. );
  175. CREATE TABLE `permissions` (
  176. `role` varchar(50) NOT NULL,
  177. `resource` varchar(255) NOT NULL,
  178. `action` varchar(8) NOT NULL,
  179. UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
  180. );
  181. INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
  182. INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

4.2 配置Nacos

1》 进入nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf:

2》 然后添加内容:

  1. 127.0.0.1:8845
  2. 127.0.0.1.8846
  3. 127.0.0.1.8847

3》 修改application.properties文件,修改数据库配置

数据库的账号密码和数据库名要正确

4》 启动nacos,因为是集群启动,所以不需要在cmd窗口加-M参数了 直接双击startup.cmd即可

4.3 启动nacos

将nacos文件夹复制三份,分别命名为:nacos1、nacos2、nacos3

SpringCloud学习笔记 - 图2

然后分别修改三个文件夹中的application.properties,

nacos1:

  1. server.port=8845

nacos2:

  1. server.port=8846

nacos3:

  1. server.port=8847

4.4 Nginx反向代理

修改conf/nginx.conf文件,配置如下:

  1. upstream nacos-cluster {
  2. server 127.0.0.1:8845;
  3. server 127.0.0.1:8846;
  4. server 127.0.0.1:8847;
  5. }
  6. server {
  7. listen 80;
  8. server_name localhost;
  9. location /nacos {
  10. proxy_pass http://nacos-cluster;
  11. }
  12. }

需加载http括号中

启动ngnix,访问http://localhost/nacos即可。

因为配置了ngnix代理,所以代码中所有的nacos地址都需要改成localhost:80