SpringCloud Alibaba - Nacos学习笔记

微服务进阶

前面我们了解了微服务的一套解决方案,但是它是基于Netflix的解决方案,实际上我们发现,很多框架都已经停止维护了,来看看目前我们所认识到的SpringCloud各大组件的维护情况:

  • 注册中心:Eureka(属于Netflix,2.x版本不再开源,1.x版本仍在更新)
  • 服务调用:Ribbon(属于Netflix,停止更新,已经彻底被移除)、SpringCloud Loadbalancer(属于SpringCloud官方,目前的默认方案)
  • 服务降级:Hystrix(属于Netflix,停止更新,已经彻底被移除)
  • 路由网关:Zuul(属于Netflix,停止更新,已经彻底被移除)、Gateway(属于SpringCloud官方,推荐方案)
  • 配置中心:Config(属于SpringCloud官方)

可见,我们之前使用的整套解决方案中,超过半数的组件都已经处于不可用状态,并且部分组件都是SpringCloud官方出手提供框架进行解决,因此,寻找一套更好的解决方案势在必行,也就引出了我们本章的主角:SpringCloud Alibaba

阿里巴巴作为业界的互联网大厂,给出了一套全新的解决方案,官方网站(中文):https://spring-cloud-alibaba-group.github.io/github-pages/2021/zh-cn/index.html

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里分布式应用解决方案,通过阿里中间件来迅速搭建分布式应用系统。

目前 Spring Cloud Alibaba 提供了如下功能:

  1. 服务限流降级:支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Dubbo 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  2. 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
  3. 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
  4. Rpc服务:扩展 Spring Cloud 客户端 RestTemplate 和 OpenFeign,支持调用 Dubbo RPC 服务
  5. 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
  6. 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
  7. 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
  8. 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
  9. 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

可以看到,SpringCloudAlibaba实际上是对我们的SpringCloud组件增强功能,是SpringCloud的增强框架,可以兼容SpringCloud原生组件和SpringCloudAlibaba的组件。

开始学习之前,把我们之前打包好的拆分项目解压,我们将基于它进行讲解。


image-20220326110940692

Nacos 更加全能的注册中心

Nacos(Naming Configuration Service)是一款阿里巴巴开源的服务注册与发现、配置管理的组件,相当于是Eureka+Config的组合形态。

安装与部署

Nacos服务器是独立安装部署的,因此我们需要下载最新的Nacos服务端程序,下载地址:https://github.com/alibaba/nacos

在这里插入图片描述
在这里插入图片描述

可以看到目前最新的版本是1.4.3版本(2022年2月27日发布的),我们直接下载zip文件即可。

接着我们将文件进行解压,得到以下内容:
在这里插入图片描述

我们直接将其拖入到项目文件夹下,便于我们一会在IDEA内部启动,接着添加运行配置:

在这里插入图片描述

其中-m standalone表示单节点模式,Mac和Linux下记得将解释器设定为/bin/bash,由于Nacos在Mac/Linux默认是后台启动模式,我们修改一下它的bash文件,让它变成前台启动,这样IDEA关闭了Nacos就自动关闭了,否则开发环境下很容易忘记关:

# 注释掉 nohup $JAVA ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
# 替换成下面的
$JAVA ${JAVA_OPT} nacos.nacos

接着我们点击启动:

image-20220326132051779

windos下,我们将启动模式从集群换为单机即可启动,或者直接找到**nacos/bin路径 运行 .\startup.cmd -m standalone**

在这里插入图片描述

OK,启动成功,可以看到它的管理页面地址也是给我们贴出来了: http://localhost:8848/nacos,访问这个地址:

在这里插入图片描述

默认的用户名和管理员密码都是nacos,直接登陆即可,可以看到进入管理页面之后功能也是相当丰富:

image-20220326132455674

至此,Nacos的安装与部署完成。

服务注册与发现

现在我们要实现基于Nacos的服务注册与发现,那么就需要导入SpringCloudAlibaba相关的依赖,我们在父工程将依赖进行管理:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
      
      	<!-- 这里引入最新的SpringCloud依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2021.0.1</version>
          	<type>pom</type>
            <scope>import</scope>
        </dependency>

     	  <!-- 这里引入最新的SpringCloudAlibaba依赖,2021.0.1.0版本支持SpringBoot2.6.X -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2021.0.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

接着我们就可以在子项目中添加服务发现依赖了,比如我们以图书服务为例:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

和注册到Eureka一样,我们也需要在配置文件中配置Nacos注册中心的地址:

server:
  port: 8201
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloudstudy?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
    username: root
    password: mysql123456
  # 应用名称 bookservice
  application:
    name: bookservice
  cloud:
    nacos:
      discovery:
        # 配置Nacos注册中心地址
        server-addr: localhost:8848

按照同样的方法,我们接着将另外两个服务也注册到Nacos中:

在这里插入图片描述

接着我们使用OpenFeign,实现服务发现远程调用以及负载均衡,在BorrowService中导入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 这里需要单独导入LoadBalancer依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

编写接口:

@FeignClient("userservice")
public interface UserClient {
    
    @RequestMapping("/user/{uid}")
    User getUserById(@PathVariable("uid") int uid);
}
@FeignClient("bookservice")
public interface BookClient {

    @RequestMapping("/book/{bid}")
    Book getBookById(@PathVariable("bid") int bid);
}
@Service
public class BorrowServiceImpl implements BorrowService {

    @Resource
    BorrowMapper mapper;

    @Resource
    BookClient bookClient;

    @Resource
    UserClient userClient;

    @Override
    public UserBorrowDetail getUserBorrowDetailByUid(int uid) {

        List<Borrow> borrow = mapper.getBorrowsByUid(uid);
        //那么问题来了,现在拿到借阅关联信息了,怎么调用其他服务获取信息呢?

        User user = userClient.findUserById(uid);

        List<Book> bookList = borrow
                .stream()
                .map(borrowTemp -> bookClient.findBookById(borrowTemp.getBid()))
                .collect(Collectors.toList());

        return new UserBorrowDetail(user, bookList);
    }
}
@EnableFeignClients
@SpringBootApplication
public class BorrowApplication {
    public static void main(String[] args) {
        SpringApplication.run(BorrowApplication.class, args);
    }
}

接着我们进行测试:

在这里插入图片描述

测试正常,可以自动发现服务,接着我们来多配置几个实例,图书服务和用户服务的端口配置。

然后我们在图书服务和用户服务中添加一句打印方便之后查看:

@RequestMapping("/user/{uid}")
public User findUserById(@PathVariable("uid") int uid){
    System.out.println("调用用户服务");
    return service.getUserById(uid);
}

现在将全部服务启动:
在这里插入图片描述

可以看到Nacos中的实例数量已经显示为2

在这里插入图片描述

接着我们调用借阅服务,看看能否负载均衡远程调用:

在这里插入图片描述

在这里插入图片描述

OK,负载均衡远程调用没有问题,这样我们就实现了基于Nacos的服务的注册与发现,实际上大致流程与Eureka一致。

值得注意的是,Nacos区分了临时实例和非临时实例:

在这里插入图片描述

那么临时和非临时有什么区别呢?

  • 临时实例:和Eureka一样,采用心跳机制向Nacos发送请求保持在线状态,一旦心跳停止,代表实例下线,不保留实例信息。
  • 非临时实例:由Nacos主动进行联系,如果连接失败,那么不会移除实例信息,而是将健康状态设定为false,相当于会对某个实例状态持续地进行监控。

我们可以通过配置文件进行修改临时实例:

spring:
  application:
    name: borrow-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        # 将ephemeral修改为false,表示非临时实例
        ephemeral: false

集群分区

实际上集群分区概念在之前的Eureka中也有出现,比如:

eureka:
  client:
		fetch-registry: false
    register-with-eureka: false
    service-url:
      defaultZone: http://localhost:8888/eureka
      # 这个defaultZone是个啥玩意,为什么要用这个名称?为什么要要用这样的形式来声明注册中心?

在一个分布式应用中,相同服务的实例可能会在不同的机器、位置上启动,比如我们的用户管理服务,可能在成都有1台服务器部署、重庆有一台服务器部署,而这时,我们在成都的服务器上启动了借阅服务,那么如果我们的借阅服务现在要调用用户服务,就应该优先选择同一个区域的用户服务进行调用,这样会使得响应速度更快。

image-20220326150024118

因此,我们可以对部署在不同机房的服务进行分区,可以看到实例的分区是默认:
在这里插入图片描述

我们可以直接在配置文件中进行修改:

我们将01端口的服务都设为广州集群,02端口服务都设置为北京集群,借阅服务设置为北京集群。

spring:
  application:
    name: borrow-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        # 修改为北京地区的集群
        cluster-name: Beijing

当然由于我们这里使用的是不同的启动配置,直接在启动配置中添加环境变量spring.cloud.nacos.discovery.cluster-name也行,这里我们将用户服务和图书服务两个区域都分配一个,借阅服务就配置为北京地区:

在这里插入图片描述

修改完成之后,我们来尝试重新启动一下(Nacos也要重启),观察Nacos中集群分布情况:

在这里插入图片描述

可以看到现在有两个集群,并且都有一个实例正在运行。我们接着去调用借阅服务,按照区域优先,它应该首先掉用北京地区的,但是发现并没有按照区域进行优先调用,而依然使用的是轮询模式的负载均衡调用。

我们必须要提供Nacos的负载均衡实现才能开启区域优先调用机制,只需要在borrowservice配制文件中进行修改即可:

spring:
  application:
    name: borrowservice
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: Beijing
    # 将loadbalancer的nacos支持开启,集成Nacos负载均衡
    loadbalancer:
      nacos:
        enabled: true

现在我们重启借阅服务,会发现优先调用的是同区域的用户和图书服务:
在这里插入图片描述

现在我们可以将北京地区的服务下线:

image-20220326153002500
可以看到,在北京的服务下线之后,由于本区域内没有可用服务了,借阅服务将会调用广州区域的用户服务。
在这里插入图片描述

除了根据区域优先调用之外,同一个区域内的实例也可以单独设置权重,Nacos会优先选择权重更大的实例进行调用,我们可以直接在管理页面中进行配置:

image-20220326152659294

或是在配置文件中进行配置:

spring:
  application:
    name: borrowservice
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: Beijing
        # 权重大小,越大越优先调用,默认为1
        weight: 0.5

通过配置权重,某些性能不太好的机器就能够更少地被使用,而更多的使用那些网络良好性能更高的主机上的实例。

配置中心

前面我们学习了SpringCloud Config,我们可以通过配置服务来加载远程配置,这样我们就可以在远端集中管理配置文件。

实际上我们可以在bootstrap.yml中配置远程配置文件获取,然后再进入到配置文件加载环节,而Nacos也支持这样的操作,使用方式也比较类似,比如我们现在想要将借阅服务的配置文件放到Nacos进行管理,那么这个时候就需要在Nacos中创建配置文件:

image-20220326161111523

将借阅服务的配置文件全部(当然正常情况下是不会全部CV的,只会复制那些需要经常修改的部分,这里为了省事就直接全部CV了)复制过来,注意Data ID的格式跟我们之前一样,应用名称-环境.yml,如果只编写应用名称,那么代表此配置文件无论在什么环境下都会使用,然后每个配置文件都可以进行分组,也算是一种分类方式,注意我们一定要以文件格式结尾,我这里是之前的错误示范截图,正确的应该为 userservice-dev.yml

在这里插入图片描述
完成之后点击发布即可:
在这里插入图片描述
然后在项目中导入依赖,这里我们只配置了用户服务的,所以我们先在用户服务模块中添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

接着我们在借阅服务中添加bootstrap.yml文件:

spring:
  application:
    # 服务名称和配置中心的userservice-dev文件保持一致
    name: userservice
  profiles:
    # 环境也是和配置文件保持一致
    active: dev
  cloud:
    nacos:
      config:
        # 配置文件后缀名
        file-extension: yml
        # 配置中心服务器地址,也就是Nacos地址
        server-addr: localhost:8848

现在我们启动服务试试看:
在这里插入图片描述
可以看到成功读取配置文件并启动了,实际上使用上来说跟之前的Config是基本一致的。

Nacos还支持配置文件的热更新,比如我们在配置文件中添加了一个属性,而这个时候可能需要实时修改,并在后端实时更新,那么这种该怎么实现呢?

我们修改一下配置文件,然后重启服务器:
在这里插入图片描述
可以看到已经可以正常读取了:

那么如何才能实现配置热更新呢?我们可以像下面这样:

@RestController
@RefreshScope   // 添加此注解就能实现自动刷新了
public class TestController {

    @Value("${test.txt}")
    String txt;

    @RequestMapping("/test")
    public String test(){
        return txt;
    }
}

重启服务器,再次重复上述实验,成功。

本人跟着青空の霞光学习的笔记,代码示例全部都成功,改编于 ---- 青空の霞光

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值