用例背景:
需求分析 :
现在有两个服务分别是订单服务和用户信息服务,由于每个服务只能提供单一的功能,所以我们想查询一个订单,并且在该订单的查询结果中显示订单的详情之外也显示订单所属用户的基本信息,显然根据微服务设计原则,订单模块只能查出订单的信息,无法查询出用户的信息,所以 下文都是围绕该问题进行书写。
所以在下面的代码中Nacos即服务端,orderService和userService即客户端
一、前期配置:
1、开启服务:
在bin目录下找到startup.cmd,双击启动即可:
点开上面的网址即nacos的管理页面。
2、在服务端导入依赖:
1、导入服务端依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
3、在客户端导入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
修改客户端的配置文件,使其与服务端的Nacos相关联:(每一个子服务都要配置)
spring:
cloud:
nacos:
server-addr: localhost:8848 # nacos 服务端地址
配置成功之后打开Nachos的管理网页即可查看刚刚已经配置的子服务:
二、Nacos数据集群:
为了达到负载均衡、就近访问、权重负载均衡等特点我们必须实现数据集群,Nacos提供了很好的集群服务,下面我们一一介绍对应的功能。
1、跨集群调用:
例如上图的userService的一个方法在北京、上海、杭州都有相应的集群点,并且在每个集群点的内部为了实现负载均衡都有多个端口用于解决同一问题,此时上海的用户调用了该接口想访问数据,直观的分析我们应该调用上海的这个接口来提供数据,不应该调用远距的北京接口。
上述问题要解决的实质就是:
服务应该尽可能的调用本地集群的数据,而不是选择更远的集群从而导致高延时,只有当本地集群不可访问时才去考虑远处集群。
1、为了实现这一目的,我们首先需要在每个客户端的配置文件中修改 cluster-name 属性来确定集群名称。
spring:
cloud:
nacos:
server-addr: localhost:8848 # nacos 服务端地址
discovery:
cluster-name: HZ # 配置集群名称,也就是机房位置,例如:HZ,杭州
2、配置上述属性之后,只是将各个集群进行了分类,但是真正方法哪一个集群是由ribbon负载均衡来实现的。
目前的需求是order需要调用userService的内容,所以我们要在order内配置访问userService的负载均衡策略。由默认的轮询方式转化为负载均衡方式。
userservice: # 服务名称,在每个服务的Spring.application.name配置(下文有)
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
服务名称在每个服务的yml配置中通过name属性确定:
spring:
application:
name: userservice # 微服务的名称,调用不同服务等各种配置都要用
之后在进行调用服务的时候Nacos会优先分配属于同一集群名称(即本地集群)的服务。
2、根据权重进行负载均衡:
应用场景:
根据上一步跨集群调用,我们已经实现了就近集群调用。而集群内部又有多个为了实现负载均衡的小服务,这些服务功能相同,分布在不同的服务器上由ribbon进行随机调用。但是我们想让某些设备先进的机器调用的次数高于那些设备相对较次的机器的调用次数,即高性能机器处理的频率高于较次机器,此时需要用到权重负载均衡。
实现上述步骤十分简单,我们只需要打开Nacos的管理页面,找到对应的实例后面的编辑按钮,设置权重即可:(权重越低,访问的几率越小)
1、权重的取值在0-1之间。
2、若权重的取值为0则不再访问该实例。
三)Nacos注册中心原理:
1、Nacos对供应者类型分为临时实例和非临时实例。
- 临时实例:采用心跳模式,三十秒给注册中心发一个请求,如果没有发送则立刻杀死该实例,并通知消费者该实例无法访问。
- 非临时实例:注册中心会不断给临时实例发送询问,即使非临时实例出现异常,注册中心也不会剔除非临实例,会一直等待,直到恢复。
2、消费者实例获取:
- 消费者向服务中心获取实例,通过一步骤之后服务中心将可以使用的实例推送给消费者。
- 为了防止重复拉取消费者将实例保存在本地缓存,方便多次调用
- 服务中心一旦发现某一个实例无法使用,会立即向消费者推送消息,然后消费者将该实例在本地缓存删除。
Nacos统一配置管理:
针对集群部署,有以下问题需要解决:
1、很多服务为了负载均衡实现相同功能,这些服务之间会存在很多相同的配置,Nacos能否将这些相同的配置统一提取到一起,统一书写统一修改。
2、每次我们修改这些配置时,为了让其生效,能否实现配置的热更新。
1、统一配置管理:
该配置的目的是 创建一些生产环境、测试环境、部署环境的开关类配置,书写之后不仅能方便的修改,还能实现热更新。
1、首先我们来到Nacos的控制台添加新配置:
2、书写配置的相关信息: (ID名称必须是唯一的,注意命名规范)
3、客户端导入Nacos的配置依赖:
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
4、在客户端添加一个bootstrap.yml的配置文件书写Nacos的配置信息:(读取Nacos里的配置文件)
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: localhost:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
2、实现配置的热刷新:
核心就是 @ConfigurationProperties 注解:加上之后该类下的所有属性都实现了热更新
1、我们创建一个全局的配置类(在该配置类下的属性才实现热刷新):
- 注解的prefix参数必须与上面nacos中的一致
- 下面的属性名也必须与模板的参数保持一致
@Component
@Data
//下面的前缀就是配置文件的根名称,前文有介绍
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
private String dateformat;//该属性是Nacos中配置好的那个属性
}
3、多环境共享配置:
该配置用于书写在生产环境、测试环境、部署环境都一样的配置,不常修改的配置
此处的配置一定是 服务名.yml 服务名是Spring.name处配置的名称
我们可以继续来到刚刚的配置类添加新成员:
@Component
@Data
//下面的前缀就是配置文件的根名称,前文有介绍
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
private String dateformat;//该属性是Nacos中配置好的那个属性
private String envShareValue; //新属性名称
}
目前我们有三种配置文件:
1、第一步配置的统一配置文件 服务名-profile.yaml
2、刚刚第三步配置的多环境共享配置 服务名称.yaml
3、Spring自带的application,yml
三者的优先级: 服务名-profile.yaml > 服务名称.yaml > 本地application.yml