软件工程之系统架构设计和建模设计

我们正在深入探讨软件工程中的两个核心环节:系统架构设计和建模设计。这两者紧密相连,但关注点不同。系统架构设计关注高层结构、组件划分、技术选型等;建模设计则更具体,关注系统内部的结构和行为如何用模型表达。

由于之前已经讨论了系统工程、软件工程、架构组织、设计模式、建模语言和UML的关系,现在我们将更具体地聚焦于系统架构设计和建模设计。

一、系统架构设计
系统架构设计是软件工程中的一个关键阶段,它定义了系统的结构、组件、组件之间的关系、以及它们如何协作以满足需求。架构设计的目标是创建一个蓝图,该蓝图可以指导开发团队,并确保系统满足功能和非功能需求(如性能、可扩展性、可靠性等)。

核心机制和原理:

  1. 分解与抽象:将复杂系统分解为更小、更易管理的部分(模块或组件),并为每个部分提供清晰的抽象。

  2. 关注点分离:将不同的关注点(如业务逻辑、数据持久化、用户界面)分离到不同的组件中,以提高可维护性和可扩展性。

  3. 架构风格/模式:使用经过验证的架构风格(如分层架构、微服务架构、事件驱动架构等)作为基础,以解决特定类型的问题。

  4. 决策权衡:在多个可能的架构方案之间进行权衡,考虑成本、时间、技术、团队技能等因素。

二、建模设计
建模设计是使用模型来表示系统的各个方面,以便于理解、沟通和验证设计。模型可以是结构性的(如类图、组件图),也可以是行为性的(如时序图、状态图)。建模设计通常在架构设计之后,但在具体实现之前进行,它帮助开发团队可视化设计,并发现潜在问题。

核心机制和原理:

  1. 可视化:通过图形化的方式表示复杂的设计,使抽象概念更具体。

  2. 多视角:从不同视角(静态结构、动态行为、部署等)建模系统,以全面理解系统。

  3. 标准化:使用标准化的建模语言(如UML)确保团队成员之间的有效沟通。

  4. 迭代和细化:模型不是一成不变的,随着需求的变化和设计的深入,模型需要不断迭代和细化。

三、实例:在线支付系统(续)
我们继续使用在线支付系统的例子,来说明系统架构设计和建模设计的具体应用。

  1. 系统架构设计实例:
    假设我们决定采用微服务架构风格,将系统分解为多个服务:
  • 用户服务:管理用户信息和认证。

  • 账户服务:管理用户账户和余额。

  • 支付服务:处理支付交易。

  • 风控服务:评估交易风险。

  • 通知服务:发送交易通知。

每个服务都是独立的,可以独立开发、部署和扩展。服务之间通过REST API或消息队列进行通信。

架构设计决策:

  • 数据管理:每个服务拥有自己的数据库,确保服务之间的松耦合。

  • 通信机制:同步通信使用REST,异步通信使用消息队列(如Kafka)。

  • 服务发现:使用服务注册与发现机制(如Consul)来管理服务实例。

  • 配置管理:使用配置中心(如Spring Cloud Config)统一管理配置。

  • 容错:使用熔断器(如Hystrix)防止服务雪崩。

  1. 建模设计实例:
    我们使用UML来建模支付服务的关键部分。

a. 类图:表示支付服务的静态结构。

+----------------+       +----------------+       +----------------+
|   Payment      |       |   Payment      |       |   Payment      |
|   Service      |       |   Controller   |       |   Repository   |
+----------------+       +----------------+       +----------------+
| -repo: Payment |       | -service:      |       | +save(): void  |
|   Repository   |       |   PaymentService|       | +findById():  |
+----------------+       +----------------+       |   Payment      |
| +process():    |       | +processPay():  |       +----------------+
|   PaymentResult|       |   ResponseEntity|       
+----------------+       +----------------+       

+----------------+       +----------------+
|   Payment      |       |   Payment      |
|   Processor    |       |   Validator    |
+----------------+       +----------------+
| +execute():    |       | +validate():   |
|   void         |       |   boolean      |
+----------------+       +----------------+

b. 时序图:表示支付过程的动态行为。
参与者:用户、支付控制器、支付服务、风控服务、账户服务、通知服务。

步骤:

  1. 用户提交支付请求。
  2. 支付控制器接收请求,调用支付服务。
  3. 支付服务调用风控服务进行风险评估。
  4. 风控服务返回风险评估结果。
  5. 支付服务调用账户服务扣款。
  6. 账户服务返回扣款结果。
  7. 支付服务更新支付状态,并调用通知服务发送通知。
  8. 通知服务发送通知给用户。
  9. 支付服务返回支付结果给支付控制器,最后返回给用户。

c. 组件图:表示支付服务与其他服务的关系。

[支付服务] ---> [风控服务]
     |              |
     |              |
     v              v
[账户服务]      [通知服务]

d. 部署图:表示系统如何部署到硬件或云环境。

[Web服务器] ---> [支付服务实例1]
     |           [支付服务实例2]
     |           [支付服务实例3]
     |
     v
[数据库集群]     [消息队列集群]

四、概述总结

系统架构设计和建模设计是软件工程中不可或缺的部分。系统架构设计提供了高层次的蓝图,而建模设计则提供了更详细的可视化表示。两者结合,帮助团队构建出符合需求、可维护、可扩展的软件系统。

在实际项目中,架构设计和建模设计往往是迭代进行的。初始的架构设计可能会在建模过程中发现问题,进而调整架构。同时,建模设计也会随着实现的深入而不断细化。

最后,需要注意的是,建模设计不是为了产生大量的文档,而是为了帮助团队沟通和理解。在敏捷开发中,我们提倡“刚刚好”的建模,即建模只要满足当前沟通和设计的需求即可,避免过度设计。

软件工程之系统架构设计与建模设计

下面将深入解析软件工程中的两大核心环节:系统架构设计和建模设计,通过完整的实例展示它们如何协同工作。

一、系统架构设计

1.1 架构设计的层次体系

系统架构设计是一个多层次、多视角的决策过程:

业务架构 → 应用架构 → 数据架构 → 技术架构 → 部署架构
      ↓         ↓         ↓         ↓         ↓
 价值流     功能模块    数据模型    技术选型   基础设施

1.2 架构设计的基本原则

核心原则(以ACID记忆):

  • A (Abstraction) - 抽象:隐藏复杂性,暴露必要接口
  • C (Cohesion) - 内聚:相关功能集中,无关功能分离
  • I (Isolation) - 隔离:故障隔离、变更隔离、安全隔离
  • D (Decomposition) - 分解:将大问题拆解为可管理的小问题

1.3 现代架构设计方法论

1.3.1 领域驱动设计
  • 战略设计:限界上下文、上下文映射、通用语言
  • 战术设计:实体、值对象、聚合、仓储、领域服务
1.3.2 清洁架构
外部接口层 → 应用服务层 → 领域层 → 基础设施层
   (控制器)   (用例协调)   (业务规则)   (实现细节)
1.3.3 六边形架构(端口-适配器)
          ┌─────────────────────┐
          │      应用核心        │
          │  (领域模型+用例)    │
          └─────────┬───────────┘
                    │
┌─────────┐    ┌────┴────┐    ┌─────────┐
│ 驱动适配 │←──│  端口   │──→│ 驱动适配 │
│ (HTTP等) │    │        │    │ (DB等)  │
└─────────┘    └─────────┘    └─────────┘

1.4 架构决策记录

ADR模板示例:

# ADR 001: 微服务通信机制选择

## 状态
已采纳

## 上下文
系统需要处理高并发支付请求,服务间需要高效通信。

## 决策
采用 **同步REST + 异步事件驱动** 混合模式:
- 关键路径(支付处理)使用gRPC同步调用
- 非关键路径(通知、日志)使用Kafka异步事件

## 后果
**正面**:关键路径低延迟,非关键路径解耦
**负面**:增加技术复杂度,需要维护两种通信机制

二、建模设计

2.1 建模的四个维度

┌─────────────────────────────────────────┐
│           结构建模 (静态)                │
│   • 类图、组件图、部署图、对象图         │
├─────────────────────────────────────────┤
│           行为建模 (动态)                │
│   • 用例图、活动图、状态机图、时序图     │
├─────────────────────────────────────────┤
│           交互建模 (协作)                │
│   • 通信图、交互概览图、时序图           │
├─────────────────────────────────────────┤
│           约束建模 (规则)                │
│   • OCL(对象约束语言)、业务规则        │
└─────────────────────────────────────────┘

2.2 建模驱动的开发流程

反馈
业务需求
领域建模
用例建模
静态结构建模
动态行为建模
代码生成/实现
模型验证
迭代优化

2.3 实战:电商订单系统建模

2.3.1 领域模型(类图)
// 领域模型的核心抽象
@AggregateRoot
class Order {
    private OrderId id;
    private CustomerId customerId;
    private List<OrderItem> items;
    private OrderStatus status;
    private Address shippingAddress;
    private PaymentInfo paymentInfo;
    
    public void placeOrder() {
        // 领域逻辑:验证库存、计算总额、创建订单
        validate();
        calculateTotal();
        this.status = OrderStatus.CREATED;
        DomainEvents.publish(new OrderPlacedEvent(this));
    }
    
    public void cancel() {
        // 业务规则:只有特定状态的订单可以取消
        if (!status.canCancel()) {
            throw new IllegalStateException("订单无法取消");
        }
        this.status = OrderStatus.CANCELLED;
        DomainEvents.publish(new OrderCancelledEvent(this));
    }
}

@ValueObject
class OrderItem {
    private ProductId productId;
    private int quantity;
    private Money unitPrice;
    
    public Money calculateSubtotal() {
        return unitPrice.multiply(quantity);
    }
}
2.3.2 用例建模
@startuml
left to right direction
actor 顾客 as Customer
actor 商家 as Merchant
actor 系统管理员 as Admin

rectangle "电商系统" {
    usecase "浏览商品" as UC1
    usecase "下单购买" as UC2
    usecase "支付订单" as UC3
    usecase "查看订单状态" as UC4
    usecase "取消订单" as UC5
    usecase "管理商品库存" as UC6
    usecase "处理退款" as UC7
}

Customer --> UC1
Customer --> UC2
Customer --> UC3
Customer --> UC4
Customer --> UC5
Merchant --> UC6
Merchant --> UC7
Admin --> UC6
Admin --> UC7

UC2 .> UC3 : include
UC5 .> UC7 : extend <<如果已支付>>
@enduml
2.3.3 状态机建模
@startuml
state Order {
    [*] --> CREATED : 创建订单
    
    CREATED --> PAYMENT_PENDING : 提交订单
    PAYMENT_PENDING --> PAID : 支付成功
    PAYMENT_PENDING --> CANCELLED : 取消订单
    
    PAID --> PROCESSING : 开始处理
    PROCESSING --> SHIPPED : 发货
    SHIPPED --> DELIVERED : 签收
    
    PAID --> REFUNDING : 申请退款
    REFUNDING --> REFUNDED : 退款完成
    REFUNDING --> PAID : 退款驳回
    
    DELIVERED --> COMPLETED : 完成
    COMPLETED --> [*]
    
    CANCELLED --> [*]
    REFUNDED --> [*]
    
    note right of CREATED
        订单已创建但未提交
        可修改商品和数量
    end note
    
    note right of PAYMENT_PENDING
        等待用户支付
        15分钟超时自动取消
    end note
}
@enduml
2.3.4 时序图:下单流程
@startuml
participant Customer as C
participant "Order Service" as OS
participant "Inventory Service" as IS
participant "Payment Service" as PS
participant "Notification Service" as NS

activate C
C -> OS: 1. 提交订单\n(商品ID, 数量, 地址)
activate OS

OS -> IS: 2. 检查库存\n(商品ID, 数量)
activate IS
IS --> OS: 3. 库存充足
deactivate IS

OS -> OS: 4. 创建订单记录
OS -> PS: 5. 创建支付记录\n(订单ID, 金额)
activate PS
PS --> OS: 6. 支付记录创建成功\n(支付ID)
deactivate PS

OS --> C: 7. 订单创建成功\n跳转到支付页面
deactivate OS

C -> PS: 8. 发起支付\n(支付ID)
activate PS
PS -> PS: 9. 调用第三方支付网关
PS --> C: 10. 支付成功
deactivate PS

PS -> OS: 11. 支付成功事件
activate OS
OS -> OS: 12. 更新订单状态为已支付
OS -> NS: 13. 发送订单确认通知
activate NS
NS --> OS: 14. 通知发送成功
deactivate NS
deactivate OS

@enduml

三、架构设计与建模的协同

3.1 从模型到架构的转换

转换规则示例:

领域模型                  → 架构组件
─────────────────────────────────────────
聚合根 (Aggregate Root)   → 微服务边界
实体 (Entity)            → 服务内部领域对象
值对象 (Value Object)    → 不可变DTO
领域服务 (Domain Service) → 应用服务层
仓储接口 (Repository)    → 基础设施层实现
领域事件 (Domain Event)  → 消息队列事件

3.2 C4模型:完整的架构描述框架

层次1:系统上下文图

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│    顾客     │────│  电商系统   │────│  支付网关   │
└─────────────┘    └─────────────┘    └─────────────┘
                         │
                         │
                  ┌─────────────┐
                  │  物流系统   │
                  └─────────────┘

层次2:容器图(应用架构)

电商系统容器:
  - Web应用 (React + Nginx)
  - API网关 (Spring Cloud Gateway)
  - 订单服务 (Java/Spring Boot)
  - 商品服务 (Go)
  - 用户服务 (Python/Django)
  - 消息队列 (Apache Kafka)
  - 数据库集群 (PostgreSQL + Redis)

层次3:组件图(服务内部)

@startuml
package "订单服务" {
  [订单控制器] as Controller
  [订单应用服务] as AppService
  [订单领域服务] as DomainService
  [订单聚合] as Aggregate
  [订单仓储接口] as RepositoryInterface
  [数据库适配器] as DBAdapter
}

Controller -> AppService : 委托请求
AppService -> DomainService : 调用领域逻辑
AppService -> Aggregate : 操作聚合
AppService -> RepositoryInterface : 持久化
RepositoryInterface <- DBAdapter : 实现接口
@enduml

层次4:代码图(类级别)

// 基于组件的代码结构
src/main/java/com/example/orderservice/
├── OrderApplication.java          # 应用启动类
├── adapter/                       # 适配器层
│   ├── web/                       # Web适配器
│   │   ├── OrderController.java
│   │   └── OrderDTO.java
│   └── persistence/               # 持久化适配器
│       ├── OrderRepositoryImpl.java
│       └── OrderJpaEntity.java
├── application/                   # 应用服务层
│   ├── OrderApplicationService.java
│   └── PlaceOrderCommand.java
├── domain/                        # 领域层
│   ├── model/                     # 领域模型
│   │   ├── Order.java
│   │   ├── OrderId.java
│   │   └── OrderItem.java
│   ├── service/                   # 领域服务
│   │   └── OrderValidator.java
│   └── event/                     # 领域事件
│       └── OrderPlacedEvent.java
└── infrastructure/                # 基础设施层(可选)
    └── messaging/                 # 消息基础设施
        └── KafkaEventPublisher.java

3.3 架构关键决策框架

决策矩阵示例:

决策项选项A选项B选项C选择理由
服务通信RESTgRPC消息队列选择混合:关键路径gRPC,非关键消息队列
数据存储SQLNoSQL混合选择混合:交易数据SQL,商品缓存NoSQL
部署策略虚拟机容器Serverless选择容器:平衡控制力和弹性
监控方案日志中心链路追踪指标监控全选:三位一体的可观测性

四、现代架构模式实例

4.1 事件溯源与CQRS架构

// 事件溯源的核心实现
class OrderAggregate {
    private List<DomainEvent> changes = new ArrayList<>();
    private OrderState state;
    
    public void placeOrder(PlaceOrderCommand command) {
        // 1. 业务规则验证
        validate(command);
        
        // 2. 生成领域事件
        OrderPlacedEvent event = new OrderPlacedEvent(
            command.getOrderId(),
            command.getItems(),
            command.getCustomerId()
        );
        
        // 3. 应用事件到当前状态
        apply(event);
        
        // 4. 记录未提交的事件
        changes.add(event);
    }
    
    private void apply(OrderPlacedEvent event) {
        // 根据事件重建聚合状态
        this.state = OrderState.recreateFrom(event);
    }
    
    // 从事件流重建聚合
    public static OrderAggregate recreateFrom(List<DomainEvent> events) {
        OrderAggregate aggregate = new OrderAggregate();
        events.forEach(aggregate::apply);
        return aggregate;
    }
}

// CQRS:命令端和查询端分离
// 命令端(写模型)
@Service
class OrderCommandService {
    public OrderId handle(PlaceOrderCommand command) {
        OrderAggregate aggregate = loadAggregate(command.getOrderId());
        aggregate.placeOrder(command);
        saveAggregate(aggregate); // 保存事件到事件存储
        publishEvents(aggregate.getChanges()); // 发布事件
        return command.getOrderId();
    }
}

// 查询端(读模型)
@Service
class OrderQueryService {
    // 专门优化的查询方法
    public OrderView getOrderView(OrderId orderId) {
        return orderViewRepository.findById(orderId);
    }
    
    public List<OrderSummary> searchOrders(OrderSearchCriteria criteria) {
        return orderSummaryRepository.search(criteria);
    }
}

// 事件处理器:更新读模型
@Component
class OrderViewUpdater {
    @EventListener
    public void on(OrderPlacedEvent event) {
        // 更新物化视图
        orderViewRepository.updateFromEvent(event);
        orderSummaryRepository.updateFromEvent(event);
    }
}

4.2 六边形架构实现

// 端口定义(领域层)
interface OrderRepositoryPort {
    Order findById(OrderId id);
    void save(Order order);
}

interface PaymentServicePort {
    PaymentResult processPayment(PaymentRequest request);
}

interface NotificationPort {
    void sendOrderConfirmation(OrderConfirmedEvent event);
}

// 领域层(内部)
@Service
class OrderService {
    private final OrderRepositoryPort orderRepository;
    private final PaymentServicePort paymentService;
    private final NotificationPort notificationPort;
    
    public Order processOrder(OrderRequest request) {
        // 1. 创建订单(领域逻辑)
        Order order = Order.create(request);
        
        // 2. 持久化
        orderRepository.save(order);
        
        // 3. 处理支付(通过端口)
        PaymentResult result = paymentService.processPayment(
            new PaymentRequest(order.getId(), order.getTotalAmount())
        );
        
        if (result.isSuccess()) {
            order.confirm();
            orderRepository.save(order);
            
            // 4. 发送通知
            notificationPort.sendOrderConfirmation(
                new OrderConfirmedEvent(order.getId())
            );
        }
        
        return order;
    }
}

// 适配器实现(基础设施层)
@Repository
class OrderRepositoryAdapter implements OrderRepositoryPort {
    private final JpaOrderRepository jpaRepository;
    
    @Override
    public Order findById(OrderId id) {
        OrderEntity entity = jpaRepository.findById(id.getValue())
            .orElseThrow(() -> new OrderNotFoundException(id));
        return mapToDomain(entity);
    }
    
    @Override
    public void save(Order order) {
        OrderEntity entity = mapToEntity(order);
        jpaRepository.save(entity);
    }
}

@Component
class PaymentServiceAdapter implements PaymentServicePort {
    private final ThirdPartyPaymentClient client;
    
    @Override
    public PaymentResult processPayment(PaymentRequest request) {
        // 调用第三方支付API
        ThirdPartyPaymentResponse response = client.charge(
            request.getOrderId().toString(),
            request.getAmount()
        );
        
        return mapToDomainResult(response);
    }
}

// 驱动适配器(Web层)
@RestController
@RequestMapping("/orders")
class OrderController {
    private final OrderService orderService;
    
    @PostMapping
    public ResponseEntity<OrderResponse> createOrder(@RequestBody CreateOrderRequest request) {
        Order order = orderService.processOrder(
            mapToDomainRequest(request)
        );
        return ResponseEntity.ok(mapToResponse(order));
    }
}

五、架构质量属性设计

5.1 质量属性场景分析

可伸缩性:
  场景: "黑色星期五期间,订单量增长10倍"
  刺激源: 大量用户同时下单
  环境: 正常运营,促销期间
  响应: 系统在5秒内处理请求,成功率>99.9%
  架构策略:
    - 水平扩展: 自动伸缩订单服务实例
    - 缓存: Redis缓存商品信息和库存
    - 异步处理: 非关键操作通过消息队列异步处理

可用性:
  场景: "数据库主节点故障"
  刺激源: 硬件故障
  环境: 生产环境,正常工作时间
  响应: 30秒内自动切换到备用节点,服务中断<1分钟
  架构策略:
    - 多活部署: 数据库主从复制,跨可用区部署
    - 健康检查: 定期检查服务状态
    - 熔断机制: 失败服务快速熔断,防止雪崩

安全性:
  场景: "防止支付信息泄露"
  刺激源: 恶意攻击者尝试SQL注入
  环境: 生产环境
  响应: 攻击被阻止,无数据泄露,管理员收到告警
  架构策略:
    - 输入验证: 所有输入参数严格验证
    - 参数化查询: 防止SQL注入
    - 加密存储: 敏感数据加密存储
    - 审计日志: 记录所有数据访问

5.2 架构权衡分析

# 架构权衡分析的量化示例
class ArchitectureTradeoffAnalyzer:
    def analyze(self, requirements):
        """分析不同架构方案在不同质量属性上的表现"""
        schemes = {
            'monolithic': self._evaluate_monolithic(requirements),
            'microservices': self._evaluate_microservices(requirements),
            'event_driven': self._evaluate_event_driven(requirements)
        }
        
        # 使用加权评分法
        weights = {
            'performance': 0.3,
            'scalability': 0.25,
            'maintainability': 0.2,
            'reliability': 0.15,
            'cost': 0.1
        }
        
        scores = {}
        for scheme, attributes in schemes.items():
            total = sum(attributes[attr] * weights[attr] 
                       for attr in weights)
            scores[scheme] = total
        
        return sorted(scores.items(), key=lambda x: x[1], reverse=True)
    
    def _evaluate_microservices(self, req):
        return {
            'performance': 7,  # 网络延迟影响
            'scalability': 9,  # 独立扩展性好
            'maintainability': 8,  # 模块清晰
            'reliability': 7,  # 故障隔离但依赖网络
            'cost': 6  # 基础设施成本高
        }

六、架构演进与治理

6.1 架构演进策略

业务复杂化
团队扩展
独立部署需求
极致弹性
单体应用
垂直拆分
服务化
微服务
无服务器

6.2 架构治理框架

架构治理委员会:
  职责:
    - 审批架构决策记录(ADR)
    - 评审重大架构变更
    - 制定架构标准和规范
    - 监督架构合规性
    
架构原则:
  - 标准化原则: 服务接口、错误处理、日志格式标准化
  - 自治原则: 服务独立开发、部署、扩展
  - 容错原则: 设计时考虑故障,实现优雅降级
  - 可观测原则: 所有服务必须提供指标、日志、追踪
  
技术雷达:
  采纳:
    - Kubernetes: 容器编排标准
    - gRPC: 服务间通信
    - GraphQL: 客户端数据查询
    
  试验:
    - Service Mesh: Istio
    - Serverless: Knative
    
  评估:
    - WebAssembly: 边缘计算
    
  淘汰:
    - SOAP: 传统Web服务
    - EJB: 重量级Java组件

总结

系统架构设计与建模设计是软件工程的两大支柱

  1. 架构设计关注 “为什么这样组织” —— 从业务目标、质量属性、技术约束出发,做出高层次的结构性决策。

  2. 建模设计关注 “如何精确表达” —— 使用标准化的语言和图表,精确描述系统的静态结构和动态行为。

核心实践建议:

  • 始于业务,终于价值:架构和建模都是为了支持业务目标
  • 演进优于完美:从简单开始,随着复杂度增长逐步演进
  • 文档即代码:架构决策、模型图都应该纳入版本控制
  • 持续验证:通过原型、度量、用户反馈持续验证架构有效性
  • 团队共识:架构决策需要团队理解和认同

架构和建模不是一次性的活动,而是贯穿软件生命周期的持续过程。优秀的软件工程师需要在这两个维度上都具备扎实的能力,才能在复杂系统的设计与构建中游刃有余。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千江明月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值