Spring Cloud知识点全总结(五)

简介: Spring Cloud知识点全总结

重启order-service后,访问控制台,可以看到下面的结果:


92aa1e303d5e4efa93a136f9a0db9c45.png

ef24c064f3ee4660b2147c988950bbe7.png


此时访问order-service,因为namespace不同,会导致找不到userservice,控制台会报错:


e76eb1ad64fe47fbb5c504faf2b6cae1.png

ebac8f4063fd42f89e6da6f938e25909.png


这里环境隔离我们就演示完了。


12.Nacos和Eureka的区别


我们先来看下图,这个图大家应该比较熟悉了吧,我们之前在学习Eureka的时候也见到过。不管是什么样的注册中心啊,我们服务提供者在启动时都会把自己的信息提交给注册中心,而注册中心就会把这些信息保留下来。那么当我们的服务消费者需要去消费时,就会去找注册中心,去拉去服务的信息。不过啊,当时我没讲的一点是,这个拉去的动作,并不是每一次都要做的。如果每一次发请求都要去做一次拉取,那么这样对Eureka和Nacos来讲压力是不是太大了。所以作为消费者在做服务拉取时,它会将获取到的服务信息缓存到一个列表当中。我拉去了一次,那么我接下来一段时间我就可以不用去拉去了,而是直接缓存中的服务信息了。当然了,我这个缓存一直不更新也不行,万一服务提供者变化了怎么办呢,所以会每隔30秒去拉去一次信息进行更新。


3f0d437eceef4b94aedab94c6a3f06a1.png


消费者拿到服务信息以后,再去进行负载均衡,挑选一个发起远程调用。当时在Nacos里面,它于Eureka会有一些差别,差别在于服务提供者的健康检测。我们的Nacos会把服务提供者划分成临时实例和非临时实例。


我们打开Nacos的控制台,随便打开一个服务的详情:


046e603f594b4a438e85b178dcf60ae6.png


服务默认都是临时实例,因为我们没有配置。也就是说默认情况下,所有的实例都是临时实例。


临时实例和非临时实例在Nacos里面在做健康检测时是不一样的。


临时实例在Nacos做检测时采用的是心跳检测,这一点和Eureka的心跳检测完全一致。服务提供者每隔一段时间发一个请求到Nacos。


589eecd07fa54ac88ee3087e98b1a1d9.png


但是呢,我们的非临时实例就不一样了。非临时实例我们的Nacos不会去做心跳,这个时候健康检测这么检测的呢?是由Nacos主动发请求给服务提供者询问。并且如果非临时实例如果挂掉了,Nacos不会把它从列表中剔除,只会标注这个服务实例不健康,等这个服务恢复健康。


052eab726eb74e548a8693fd5cd31bd1.png


还有一个差别在于消费者,我们的Eureka采用的是定时拉去,每隔一段时间拉去一次。那你思考一下,如果在30秒内有服务提供者挂了,那服务消费者知道吗?如果它不知道,去调用挂掉了的服务提供者实例,不久出问题了吗?我们的Eureka做服务拉取的效率比较差,更新的不够及时,而我们的Nacos做了一件事,叫消息推送 。也就是说我们的Eureka采用的是pull,而我们的Nacos采用的是pull加push两者结合,我们的Nacos如果发现有服务挂了,它会发一条消息推送给我们的消费者,然后告诉你服务变更了,更加具有时效性。


ff75ecb992524da28b3d3cad2682a052.png



这就是Eureka和Nacos之间的差别了。


下面小小总结一下:


Nacos的服务实例分为两种l类型:


临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。


非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。


配置一个服务实例为永久实例(非临时实例):


spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例


Nacos与eureka的共同点


都支持服务注册和服务拉取

都支持服务提供者心跳方式做健康检测

Nacos与Eureka的区别


Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式

临时实例心跳不正常会被剔除,非临时实例则不会被剔除

Nacos支持服务列表变更的消息推送模式,服务列表更新更及时

Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式


六. Nacos配置管理


Nacos除了可以做注册中心,同样可以做配置管理来使用。在这一章中,我们会学习统一配置管理的相关知识,然后会学习怎么去实现配置的热更新,还有不同微服务之间,微服务不同环境之间的配置共享,最后会学习搭建一个生产环境可用的Nacos集群。


1.统一配置管理


当微服务部署的实例越来越多,达到数十、数百时,逐个修改微服务配置就会让人抓狂,而且很容易出错。我们需要一种统一配置管理方案,可以集中管理所有实例的配置。


535461fdc2d54d04a8d1cb3ec9888d88.png


Nacos一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新。


我们可以点开Nacos的控制台的配置管理的配置列表,发现配置列表是空的:


1a37f17df91648e287cb8990bba10960.png


我们点击右上角的那个加号:


5864e25554964471b167067d5164387b.png


他会弹出一个新建配置的表单要我们填写:


d9339ae81bd94a26843dde6a97f16b4c.png


到这里,第一个要填写的东西叫Data ID,其实就是配置文件的名称。但是你注意了,这个名字你不能像我们Idea里面那样都起application.yml ,因为你叫这个名字的话就有一个问题了,将来我们所有的微服务都来找Nacos管理,大家叫这个名字,那不就冲突了吗?所以我们的Data ID必须唯一,不能冲突。那怎么办呢?


微服务的名称是不冲突的吧,所以Data ID的命名方式一般是这样子的,第一部分是服务名称 (如userservice)。第二部分是我们的运行环境,我们之前不是学过环境隔离,我们的环境有开发环境和测试环境等,所以这里可以命名成dev、test或者prod。最后一部分我们写后缀名,我们写.yaml。


然后就是Group分组名称,我们不要去更改,它默认就好了。


描述就是介绍你的配置文件是干什么的。


配置格式 我们选择yaml就好(目前只支持yaml和properties这两种格式)。


最后一个是配置内容,但是并不是把项目里面application.yml的所有配置内容都粘过来,这里填的配置都是用来做热更新的配置。


73f32e3a6c0344459c3e1ac1594e9722.png


注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。


发布之后,配置列表里面就有配置了:


bec6c614a9d242199eff4cfa379f3939.png


关于怎么读取这些配置,我们在下一小节来学习。


2.微服务拉取配置


我们在Nacos里面编写了配置列表,我们的微服务就要想办法得到这些配置了吧。那么怎样去得到呢?


我们下面先来看一下在没有Nacos服务时如何获取配置的。它的流程大概是这样子的:


ad8dd2585dd44fa599b40be531379b52.png


首先项目启动,启动完了以后,会读取本地application.yml配置文件,读取完了以后会去创建Spring容器,而后会加载各种bean,之后就不说了,我们只关心配置这一部分。


在这里读取的是本地的yml配置文件,但现在我们多了Nacos里面的配置文件,将来我们的项目会把Nacos里面的配置与本地的配置文件做一个合并,然后再去完成容器创建和加载bean的操作。我们的项目启动的过程就会变成如下的过程:


51b2654a794f4543bc5a86bbfe450434.png


这个时候,流程听起来很简单对不对?但是你们要注意一件事儿啊,项目在读取Nacos配置文件的时候,它需要去知道一些信息。第一,去哪读取?第二,读取谁?所以在读取Nacos配置文件的时候,得先知道它得地址吧?这个地址就在application.yml当中。但这里既然要先读取Nacos的配置,再去读取本地的yml配置,那这个Nacos地址还得用其他的办法提前知道才行啊。那有什么是比本地application.yml还要提前的?其实有,Spring里提供了一个bootstrap.yml的文件,这个文件的优先级会比application.yml的优先级要高很多。所以项目启动以后,他会先读取bootstrap.yml文件,我们只要把Nacos地址啊,文件的相关信息啊,都配置进来,那是不是就可以先完成Nacos配置的读取了,然后再和本地的application.yml结合,接着完成后续的操作。


701977e6a73b4dce8fad9bde977be761.png


下面演示一下具体的操作:


我们在操作做之前,先把dev那个namespace命名空间给删掉,然后配置文件配置的namespace也删掉先,,然后在public里面重新创建配置,为了方便后面的一些操作。


并且这里还有一个注意点,就是我们之前用的是最新版(2.1.0版本)的Nacos,但是最新版的Nacos与Spring Cloud兼容性并不是非常好,往往会出很多奇奇怪怪的问题。所以我们尽量使用1.4.1版本的Nacos。


下面也列出了一张Spring Cloud与其各组件的版本兼容表(最新版本用*标记)::


image.png

image.png

下表为按时间顺序发布的 Spring Cloud Alibaba 以及对应的适配 Spring Cloud 和 Spring Boot 版本关系(由于 Spring Cloud 版本命名有调整,所以对应的 Spring Cloud Alibaba 版本号也做了对应变化)


image.png

image.png

(1)引入nacos-config依赖

首先,在user-service服务中,引入nacos-config的客户端依赖:


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

(2)添加bootstrap.yaml

然后,在user-service的resources目录中添加一个bootstrap.yaml文件,内容如下:

spring:


spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名


这里会根据spring.cloud.nacos.server-addr获取nacos地址,再根据


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


本例中,就是去读取userservice-dev.yaml:


462fffb09ad64014923a69795c15cc97.png


(3)读取nacos配置

在user-service中的UserController中添加业务逻辑,读取pattern.dateformat配置:


c169537c9bb94478a24a2d4952acb7fb.png


全部代码如下:


package com.haiexijun.user.web;
import com.haiexijun.user.pojo.User;
import com.haiexijun.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.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Value("${pattern.dateformat}")
    private String dateformat;
  // 获得当前时间,通过nacos配置格式化。
    @GetMapping("/now")
    public String now(){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }
    /**
     * 路径: /user/110
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }
}


在页面访问,可以看到效果:


到这里就实现了配置管理的第二步,微服务获取Nacos中的配置了。


3.配置热更新


我们最终的目的,是修改nacos中的配置后,微服务中无需重启即可让配置生效,也就是配置热更新。


要实现配置热更新,可以使用两种方式:


方式一:


eeb52158376d4eeca2be543f5fa37d5c.png


方式二:

使用@ConfigurationProperties注解代替@Value注解。


在user-service服务中,添加一个类,读取patterrn.dateformat属性:


package com.haiexijun.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
    private String dateformat;
}


在UserController中使用这个类来代替@Value:


bcb7ac0dc7a64d8aa04d576e41a3a477.png


完整代码:


package com.haiexijun.user.web;
import com.haiexijun.user.config.PatternProperties;
import com.haiexijun.user.pojo.User;
import com.haiexijun.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private PatternProperties patternProperties;
    @GetMapping("now")
    public String now(){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }
    // 略
}


更改后重启项目,我们更改Nacos的配置来测试一下热更新:


784033dc37964000bbcc07361a1f0349.png

b59d9f650c9146dc8184314c73770009.png


相关文章
|
5月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关
|
5月前
|
Java 开发工具 git
实现基于Spring Cloud的配置中心
实现基于Spring Cloud的配置中心
|
5月前
|
设计模式 监控 Java
解析Spring Cloud中的断路器模式原理
解析Spring Cloud中的断路器模式原理
|
5月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14997 33
|
5月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
521 15
|
5月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
115 3
|
5月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
191 5
|
5月前
|
Java API 开发工具
Spring Boot与Spring Cloud Config的集成
Spring Boot与Spring Cloud Config的集成
|
5月前
|
存储 安全 Java
实现基于Spring Cloud的分布式配置管理
实现基于Spring Cloud的分布式配置管理