Spring Cloud Alibaba:Nacos, Sentinel, Seata 等组件

Spring Cloud Alibaba:一场微服务架构的“饕餮盛宴”

各位看官,大家好!今天咱们聊聊微服务架构领域里的一颗璀璨明珠——Spring Cloud Alibaba。这玩意儿可不是随便冒出来的,它是阿里巴巴在微服务架构实践中积累的经验,然后贡献给开源社区的一套解决方案。简单来说,它就像一套瑞士军刀,功能强大,能帮你解决微服务架构中遇到的各种难题。

说到微服务,那可是个好东西,能把一个庞大的单体应用拆分成多个小的、独立的服务,每个服务都可以独立部署、独立扩展,大大提高了系统的灵活性和可维护性。但是,微服务也不是那么好玩的,它带来了很多新的挑战,比如服务发现、配置管理、流量控制、分布式事务等等。而Spring Cloud Alibaba,就是来帮你应对这些挑战的。

Spring Cloud Alibaba 包含了一系列组件,其中最核心、最常用的莫过于 Nacos、Sentinel 和 Seata 了。咱们今天就重点聊聊这三个家伙,看看它们各自有啥本事,以及如何一起配合,让你在微服务架构的世界里游刃有余。

1. Nacos:微服务界的“登记处”和“情报中心”

Nacos,全称是Naming Configuration Service,顾名思义,它主要负责服务发现和配置管理。你可以把它想象成微服务世界的“登记处”和“情报中心”。

  • 服务发现: 就像你刚到一个新的城市,要找一家餐厅,你需要一个地图或者导航软件,告诉你餐厅的位置。在微服务架构中,各个服务也需要知道彼此的位置,才能互相调用。Nacos 就扮演了这个“地图”的角色,它负责注册和管理服务实例,让服务消费者能够找到服务提供者。
  • 配置管理: 不同的服务可能需要不同的配置,比如数据库连接信息、缓存参数等等。如果把这些配置硬编码到服务代码里,那每次修改配置都要重新发布服务,简直是噩梦。Nacos 可以集中管理这些配置,并且支持动态更新,让你的服务能够根据环境变化自动调整。

1.1 Nacos 的基本用法

首先,你需要在你的 Spring Boot 项目中引入 Nacos 的依赖:

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

然后,在 application.propertiesapplication.yml 文件中配置 Nacos 的地址:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  # Nacos 服务器地址
      config:
        server-addr: 127.0.0.1:8848  # Nacos 服务器地址
        file-extension: yaml  # 配置文件扩展名

接下来,你就可以在你的服务中使用 @EnableDiscoveryClient 注解,将你的服务注册到 Nacos 中:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class MyServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyServiceApplication.class, args);
    }
}

现在,你的服务就已经成功注册到 Nacos 了。你可以通过 Nacos 的控制台查看注册的服务列表。

1.2 配置管理示例

假设你的服务需要一个名为 my.property 的配置项,你可以在 Nacos 的控制台上创建一个名为 my-service.yaml 的配置文件,内容如下:

my:
  property: "Hello Nacos!"

然后,在你的服务中使用 @Value 注解来获取这个配置项:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Value("${my.property}")
    private String myProperty;

    @GetMapping("/hello")
    public String hello() {
        return myProperty;
    }
}

现在,访问 /hello 接口,你就能看到 "Hello Nacos!" 的输出了。如果你修改了 Nacos 中的 my.property 的值,你的服务会自动更新,无需重启。

2. Sentinel:微服务界的“交通警察”

Sentinel,中文意思是“哨兵”,它主要负责流量控制、熔断降级、系统负载保护等。你可以把它想象成微服务世界的“交通警察”,它负责维护系统的稳定和可用性。

  • 流量控制: 就像高速公路上的限速一样,Sentinel 可以限制服务的并发访问量,防止服务被过多的请求压垮。
  • 熔断降级: 就像电路中的保险丝一样,Sentinel 可以在服务出现故障时,自动熔断,防止故障蔓延到其他服务。
  • 系统负载保护: Sentinel 可以根据系统的负载情况,自动调整服务的处理能力,防止系统崩溃。

2.1 Sentinel 的基本用法

首先,你需要在你的 Spring Boot 项目中引入 Sentinel 的依赖:

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

然后,在 application.propertiesapplication.yml 文件中配置 Sentinel 的地址:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080  # Sentinel 控制台地址

接下来,你就可以在你的服务中使用 @SentinelResource 注解,来保护你的接口:

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @GetMapping("/hello")
    @SentinelResource("hello")
    public String hello() {
        return "Hello Sentinel!";
    }
}

现在,你的 /hello 接口就被 Sentinel 保护起来了。你可以通过 Sentinel 的控制台配置流量控制规则、熔断规则等等。

2.2 流量控制示例

假设你想限制 /hello 接口的每秒访问量不超过 10 次,你可以在 Sentinel 的控制台上创建一个流量控制规则,配置如下:

  • 资源名: hello
  • 流控模式: 直接
  • 单机阈值: 10
  • 流控效果: 快速失败

现在,如果你每秒访问 /hello 接口超过 10 次,Sentinel 就会拒绝你的请求,返回一个 Blocked by Sentinel (flow limiting) 的错误信息。

2.3 熔断降级示例

假设你的 /hello 接口依赖于一个外部服务,如果这个外部服务出现故障,你的 /hello 接口也会受到影响。你可以使用 Sentinel 的熔断降级功能来解决这个问题。

首先,你需要定义一个 fallback 方法,当 /hello 接口出现异常时,Sentinel 会自动调用这个方法:

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @GetMapping("/hello")
    @SentinelResource(value = "hello", fallback = "helloFallback")
    public String hello() {
        // 模拟外部服务故障
        throw new RuntimeException("External service is unavailable!");
    }

    public String helloFallback() {
        return "Hello Sentinel (fallback)!";
    }
}

然后,你需要在 Sentinel 的控制台上创建一个熔断规则,配置如下:

  • 资源名: hello
  • 降级模式: 异常比例
  • 熔断触发比例: 0.5
  • 熔断时长: 5 秒

现在,如果 /hello 接口的异常比例超过 0.5,Sentinel 就会自动熔断,在 5 秒内拒绝所有请求。5 秒后,Sentinel 会尝试恢复服务,如果服务仍然不可用,就会继续熔断。

3. Seata:微服务界的“事务协调员”

Seata,全称是 Simple Extensible Autonomous Transaction Architecture,它主要负责解决分布式事务的问题。你可以把它想象成微服务世界的“事务协调员”,它负责保证多个服务之间的数据一致性。

在微服务架构中,一个业务流程可能涉及到多个服务,每个服务都有自己的数据库。如果这些服务之间需要进行事务操作,就可能会出现数据不一致的问题。Seata 就是来解决这个问题的。

Seata 使用的是 AT (Automatic Transaction) 模式,它通过以下几个步骤来保证分布式事务的一致性:

  1. Begin: 事务发起者向 TC (Transaction Coordinator) 注册全局事务。
  2. Execute: 各个业务分支执行本地事务,并记录 undo log。
  3. Commit/Rollback:
    • Commit: TC 通知各个业务分支提交本地事务,如果所有分支都提交成功,则全局事务提交成功。
    • Rollback: TC 通知各个业务分支回滚本地事务,各个业务分支根据 undo log 恢复数据,全局事务回滚成功。

3.1 Seata 的基本用法

首先,你需要在你的 Spring Boot 项目中引入 Seata 的依赖:

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.4.2</version>
</dependency>

然后,在 application.propertiesapplication.yml 文件中配置 Seata 的地址:

seata:
  tx-service-group: default_tx_group
  service:
    vgroup-mapping:
      default_tx_group: default
  client:
    rm:
      undo:
        data-validation: true
        log-created: true

接下来,你需要在你的服务中使用 @GlobalTransactional 注解,来开启全局事务:

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MyService {

    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional
    public void doSomething() {
        // 业务逻辑
    }
}

现在,你的 doSomething 方法就被 Seata 保护起来了。如果 doSomething 方法中涉及到多个服务,Seata 就会自动协调这些服务之间的事务,保证数据一致性。

3.2 Seata 示例

假设你有两个服务:订单服务和库存服务。当你创建一个订单时,需要同时减少库存。如果订单创建成功,但库存减少失败,就会出现数据不一致的问题。你可以使用 Seata 来解决这个问题。

首先,在订单服务和库存服务中都引入 Seata 的依赖,并配置 Seata 的地址。

然后,在订单服务中使用 @GlobalTransactional 注解,开启全局事务:

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderService {

    @Autowired
    private StockService stockService;

    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional
    public void createOrder(String productId, int quantity) {
        // 创建订单
        // ...

        // 减少库存
        stockService.reduceStock(productId, quantity);
    }
}

在库存服务中,你需要使用 @LocalTCC 注解,来标记 TCC (Try-Confirm-Cancel) 模式的事务:

import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.LocalTCC;
import org.springframework.stereotype.Service;

@LocalTCC
@Service
public interface StockService {

    boolean prepareReduceStock(BusinessActionContext actionContext, String productId, int quantity);

    boolean commitReduceStock(BusinessActionContext actionContext);

    boolean rollbackReduceStock(BusinessActionContext actionContext);

}
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class StockServiceImpl implements StockService {

    @Override
    @Transactional
    public boolean prepareReduceStock(BusinessActionContext actionContext, String productId, int quantity) {
        // 预扣库存
        // ...
        return true;
    }

    @Override
    @Transactional
    public boolean commitReduceStock(BusinessActionContext actionContext) {
        // 确认扣减库存
        // ...
        return true;
    }

    @Override
    @Transactional
    public boolean rollbackReduceStock(BusinessActionContext actionContext) {
        // 回滚预扣库存
        // ...
        return true;
    }
}

现在,当你调用 orderService.createOrder 方法时,Seata 就会自动协调订单服务和库存服务之间的事务,保证数据一致性。如果订单创建成功,但库存减少失败,Seata 就会自动回滚订单,保证数据一致性。

4. Spring Cloud Alibaba 的“黄金搭档”:Nacos + Sentinel + Seata

Nacos、Sentinel 和 Seata 是 Spring Cloud Alibaba 中最核心的三个组件,它们可以一起配合,形成一个强大的微服务架构解决方案。

  • Nacos: 提供服务发现和配置管理,让服务能够找到彼此,并且能够动态更新配置。
  • Sentinel: 提供流量控制、熔断降级、系统负载保护,保证系统的稳定和可用性。
  • Seata: 提供分布式事务解决方案,保证多个服务之间的数据一致性。

这三个组件就像一个“黄金搭档”,互相配合,互相补充,让你在微服务架构的世界里游刃有余。

5. 总结

Spring Cloud Alibaba 是一套功能强大的微服务架构解决方案,它包含了一系列组件,其中最核心、最常用的莫过于 Nacos、Sentinel 和 Seata 了。Nacos 负责服务发现和配置管理,Sentinel 负责流量控制、熔断降级、系统负载保护,Seata 负责解决分布式事务的问题。这三个组件可以一起配合,形成一个强大的微服务架构解决方案,让你在微服务架构的世界里游刃有余。

当然,Spring Cloud Alibaba 还有很多其他的组件,比如 RocketMQ、Dubbo 等等,它们也各自有各自的用途。如果你想深入了解 Spring Cloud Alibaba,建议你多多查阅官方文档,多多实践,相信你一定能掌握这套强大的工具。

好了,今天的分享就到这里了。希望这篇文章能够帮助你更好地理解 Spring Cloud Alibaba,并在你的微服务架构实践中发挥作用。祝大家编码愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注