大模型平台的计费与成本架构——多租户的 Token 计量与配额管理
大模型平台的计费与成本架构——多租户的 Token 计量与配额管理一、计费是商业化的基石大模型平台的商业化运营绕不开一个核心问题如何精确计量每个租户的 Token 消耗并进行准确计费。与传统的 SaaS 产品按功能或用户数计费不同LLM 平台本质上是按算力消耗计费——而 Token 就是算力消耗的核心度量单位。一个成熟的计费架构需要同时支撑毫秒级的实时 Token 累计、多模型差异化定价、多租户预充值/后付费/混合配额管理以及对账级别的账单准确性。二、计费架构的全局设计graph TB subgraph 租户管理层 TENANT[租户注册与配置] QUOTA[配额管理] PRICE[定价规则引擎] end subgraph 实时计量层 GW[AI 网关] -- METER[Token 计量引擎] METER -- CACHE[(Redis 实时累计)] METER -- STREAM[消息流 Kafka] end subgraph 准实时聚合层 STREAM -- AGG[流式聚合 Flink] AGG -- OLAP[(ClickHouse)] STREAM -- ALERT[超限告警] end subgraph 离线计费层 OLAP -- BILL[账单计算引擎] BILL -- INVOICE[(账单表)] BILL -- DEDUCT[余额扣减] end subgraph 控制面 ALERT -- BLOCK{超限阻断} BLOCK -- GW CACHE -- GW end三、Token 计量的核心挑战3.1 不同模型的 Token 计量方式不同不同模型对 Token 的定义存在差异——GPT 系列使用 cl100k_base 分词器Claude 使用自己的 tokenizerLlama 系列使用 BPE tokenizer。平台需要支持多种模型的 Token 计量适配/** * Token 计量引擎——多模型 Token 计数适配 */ Service public class TokenMeteringEngine { /** 模型 → Tokenizer 映射 */ private final MapString, Tokenizer tokenizerCache new ConcurrentHashMap(); /** 缓存大小上限——LRU 淘汰 */ private static final int MAX_CACHED_TOKENIZERS 20; /** * 计量一次推理请求的 Token 消耗 * * param request 推理请求元数据 * return Token 使用量摘要 */ public TokenUsageSummary meter(InferenceRequest request) { String modelName request.getModelName(); try { // Step 1: 获取对应模型的 Tokenizer Tokenizer tokenizer getTokenizer(modelName); // Step 2: 计算 Prompt Token实际生产中优先使用 API 返回值 int promptTokens request.getUsage().getPromptTokens(); int completionTokens request.getUsage().getCompletionTokens(); // Step 3: 如果 API 未返回 Token 数本地估算 if (promptTokens 0) { promptTokens tokenizer.countTokens( buildPromptText(request.getMessages())); } if (completionTokens 0) { completionTokens tokenizer.countTokens( request.getResponseText()); } int totalTokens promptTokens completionTokens; // Step 4: 计算实际费用 long costMicroDollars calculateCost(modelName, promptTokens, completionTokens); TokenUsageSummary summary TokenUsageSummary.builder() .requestId(request.getRequestId()) .tenantId(request.getTenantId()) .userId(request.getUserId()) .modelName(modelName) .promptTokens(promptTokens) .completionTokens(completionTokens) .totalTokens(totalTokens) .costMicroDollars(costMicroDollars) .timestamp(System.currentTimeMillis()) .build(); // Step 5: 实时累计到 Redis accumulateRealtime(summary); // Step 6: 异步发送至 Kafka 供流式聚合 publishToKafka(summary); return summary; } catch (Exception e) { log.error(Token 计量失败requestId{}, model{}, request.getRequestId(), modelName, e); // 计量失败不应该阻塞用户请求异步补偿 compensationService.markForCompensation(request); return TokenUsageSummary.unknown(request); } } /** * 多模型差异化定价计算 * 单位微美元1/1000000 USD避免浮点精度问题 */ private long calculateCost(String modelName, int promptTokens, int completionTokens) { PricingRule rule pricingService.getRule(modelName); // prompt 和 completion 通常不同价 long promptCost promptTokens * rule.getPromptPricePerMillionTokens() / 1_000_000L; long completionCost completionTokens * rule.getCompletionPricePerMillionTokens() / 1_000_000L; return promptCost completionCost; } /** * Redis 实时累计——支持毫秒级的配额检查 */ private void accumulateRealtime(TokenUsageSummary summary) { String key String.format(token:usage:%s:%s:%s, summary.getTenantId(), summary.getModelName(), LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)); // Redis Lua 脚本保证原子性INCRBY 设置过期时间 String luaScript local current redis.call(INCRBY, KEYS[1], ARGV[1]) if current tonumber(ARGV[1]) then redis.call(EXPIRE, KEYS[1], ARGV[2]) end return current ; DefaultRedisScriptLong script new DefaultRedisScript(); script.setScriptText(luaScript); script.setResultType(Long.class); redisTemplate.execute(script, Collections.singletonList(key), String.valueOf(summary.getTotalTokens()), String.valueOf(86400 * 35) // 保存 35 天 ); } }四、配额管理与超限控制多租户平台需要支持预充值、后付费、试用额度等多种配额模型同时保证在配额耗尽时能及时阻断/** * 配额管理器——租户级 Token 使用额度检查与扣减 */ Service public class QuotaManager { private static final Logger log LoggerFactory.getLogger( QuotaManager.class); private final StringRedisTemplate redisTemplate; /** 配额检查的 Lua 脚本——原子化检查预留 */ private static final String QUOTA_CHECK_SCRIPT local quotaKey KEYS[1] -- 总配额 key local usedKey KEYS[2] -- 已使用 key local requested tonumber(ARGV[1]) -- 本次请求 Token 数 -- 1. 获取总配额 local totalQuota redis.call(GET, quotaKey) if not totalQuota then return -1 -- 配额未配置 end totalQuota tonumber(totalQuota) -- 2. 获取已使用量 local used redis.call(GET, usedKey) if not used then used 0 else used tonumber(used) end -- 3. 检查是否超限 if used requested totalQuota then return -2 -- 配额不足 end -- 4. 原子扣减 redis.call(INCRBY, usedKey, requested) return used requested -- 返回累计使用量 ; /** * 检查并扣减配额 * * param tenantId 租户 ID * param requestedTokens 请求消耗的 Token 数 * return 配额检查结果 */ public QuotaCheckResult checkAndDeduct(String tenantId, long requestedTokens) { String quotaKey quota: tenantId :total; String usedKey quota: tenantId :used: LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); DefaultRedisScriptLong script new DefaultRedisScript(); script.setScriptText(QUOTA_CHECK_SCRIPT); script.setResultType(Long.class); Long result redisTemplate.execute(script, List.of(quotaKey, usedKey), String.valueOf(requestedTokens) ); if (result -1) { log.warn(租户 {} 无配额配置, tenantId); return QuotaCheckResult.notConfigured(); } if (result -2) { log.warn(租户 {} Token 配额不足当前使用已超限, tenantId); return QuotaCheckResult.exceeded(); } // 检查是否接近限额80%推送预警 Long totalQuota Long.valueOf( redisTemplate.opsForValue().get(quotaKey)); if (result totalQuota * 0.8) { alertService.sendQuotaWarning(tenantId, result, totalQuota); } return QuotaCheckResult.allowed(result, totalQuota); } }五、账单生成与对账账单需要同时保留两个维度的数据分钟级的时间序列数据供实时监控和告警和天级的聚合账单供结算和对账/** * 账单计算——基于 ClickHouse 的 OLAP 查询生成租户账单 */ Repository public class BillingRepository { private final JdbcTemplate clickHouseTemplate; /** * 生成指定租户的月度账单 * * param tenantId 租户 ID * param yearMonth 账单月份格式202607 * return 账单明细 */ public BillingStatement generateMonthlyBill(String tenantId, String yearMonth) { // 按模型汇总 Token 使用量 String sql SELECT model_name, sum(prompt_tokens) AS total_prompt_tokens, sum(completion_tokens) AS total_completion_tokens, sum(total_tokens) AS total_tokens, sum(cost_micro_dollars) / 1000000.0 AS total_cost_usd, count(DISTINCT user_id) AS active_users, count(DISTINCT request_id) AS total_requests FROM token_usage_hourly WHERE tenant_id ? AND toYYYYMM(timestamp) ? GROUP BY model_name ORDER BY total_cost_usd DESC ; try { ListModelBillingItem items clickHouseTemplate.query( sql, new Object[]{tenantId, Integer.parseInt(yearMonth)}, (rs, rowNum) - ModelBillingItem.builder() .modelName(rs.getString(model_name)) .totalPromptTokens(rs.getLong(total_prompt_tokens)) .totalCompletionTokens(rs.getLong(total_completion_tokens)) .totalTokens(rs.getLong(total_tokens)) .totalCostUsd(rs.getBigDecimal(total_cost_usd)) .activeUsers(rs.getInt(active_users)) .totalRequests(rs.getLong(total_requests)) .build() ); BillingStatement statement new BillingStatement(); statement.setTenantId(tenantId); statement.setBillingPeriod(yearMonth); statement.setItems(items); statement.setTotalCostUsd( items.stream() .map(ModelBillingItem::getTotalCostUsd) .reduce(BigDecimal.ZERO, BigDecimal::add) ); return statement; } catch (DataAccessException e) { log.error(账单生成失败tenant{}, period{}, tenantId, yearMonth, e); throw new BillingException(账单生成异常, e); } } /** * 账单对账——比对网关日志和计费系统的数据一致性 */ public ReconciliationReport reconcile(String date) { // 从网关日志统计 BigDecimal gatewayTotal getGatewayTotalCost(date); // 从计费系统统计 BigDecimal billingTotal getBillingTotalCost(date); BigDecimal diff gatewayTotal.subtract(billingTotal).abs(); BigDecimal diffPercent diff.divide(gatewayTotal, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); ReconciliationReport report new ReconciliationReport(); report.setDate(date); report.setGatewayTotal(gatewayTotal); report.setBillingTotal(billingTotal); report.setDifference(diff); report.setDifferencePercent(diffPercent); // 差异超过 0.1% 触发告警 if (diffPercent.compareTo(BigDecimal.valueOf(0.1)) 0) { log.error(计费对账差异超阈值date{}, 差异{}%, gateway{}, billing{}, date, diffPercent, gatewayTotal, billingTotal); alertService.sendReconciliationAlert(report); } return report; } }六、成本优化视角计费系统不仅要关心收了多少钱还要与成本系统打通支持投入产出分析/** * 模型推理成本计算——将 GPU 使用时间折算为单次推理成本 */ Service public class InferenceCostCalculator { /** * 计算单次推理的实际成本 * * param modelName 模型名称 * param executionTimeMs GPU 执行时间毫秒 * param gpuType GPU 类型 * return 推理成本美元 */ public BigDecimal calculateInferenceCost( String modelName, long executionTimeMs, String gpuType) { // GPU 单价美元/小时——来自云服务商或自建机房核算 double gpuHourlyRate getGpuHourlyRate(gpuType); // GPU 利用率实际使用率通常 70%-85% double utilizationRate getGpuUtilizationRate(); // 实际 GPU 小时 执行时间 * 利用率修正 double gpuHours executionTimeMs / 3_600_000.0 / utilizationRate; // 推理成本 GPU 小时 * 单价 BigDecimal inferenceCost BigDecimal.valueOf(gpuHours * gpuHourlyRate); // 加上基础设施成本分摊网络、存储、运维人力 BigDecimal infrastructureOverhead inferenceCost.multiply(BigDecimal.valueOf(0.15)); // 15% 分摊 return inferenceCost.add(infrastructureOverhead); } }计费数据一致性的工程保障计费系统对数据一致性的要求极高——少计会导致收入损失多计会引发客户投诉和信任危机。我们的生产实践中计费链路的数据一致性问题主要出现在三个环节第一流式响应场景下的 Token 计数。SSE 流式输出时如果客户端中途断开连接LLM 可能已经生成了部分 Token 但未返回完整的 usage 信息。如果按 API 返回的 usage 计费会丢失这部分消耗。我们的解决方案是在 AI 网关层独立维护 Token 计数器——使用与模型一致的 tokenizer 对已发送的每个 chunk 进行本地计数即使客户端断开也至少能记录已生成的部分。这块的差异通常在 5%-10% 之间对账单准确性影响显著。第二分布式场景下的计费重复。当网关发送 Kafka 消息时at-least-once 语义可能出现同一请求的 Token 使用量被多次写入。我们在计费聚合层Flink使用requestId作为去重键配合 24 小时的去重窗口和 Bloom Filter 判定将重复率控制在 0.01% 以下。第三跨天计费的时间边界。部分长推理请求可能跨越 00:00 的日配额重置边界。我们的处理策略是以请求发起时间作为归属日在上层配额管理中按时间戳归日避免因跨天导致的配额计算偏差。此外多模型定价的差异化也对计费系统提出了挑战。同一个 Prompt 在不同模型上的 Token 化结果差异可达 15%-30%这会直接影响用户的成本感知。我们建议在管理面提供成本预览功能——用户在发送请求前可以预估各模型的 Token 消耗和费用帮助用户做出成本最优的模型选择也能有效降低事后的费用争议。七、计费架构的边界与 Trade-offs7.1 实时计费的延迟与一致性权衡Redis 实时累计方案的最大优势是毫秒级的配额检查响应但其代价是数据持久化的延迟。在我们的生产实践中Redis 异步写入 ClickHouse 的延迟通常在 3-8 秒这意味着用户在前端看到的今日已用 Token 量与实际情况之间存在时间窗差异。对于高频调用用户如每秒数十次推理请求这个时间窗内可能发生超额使用。解决方法是对高消耗租户单次请求超过 10 万 Token采用同步双写策略同时写入 Redis 和 ClickHouse确保实时账单的准确性但这会将高消耗请求的 P99 延迟增加约 15-20ms需要在网关层对这种请求单独处理。7.2 多租户场景下的资源隔离成本当多个租户共享同一套 GPU 推理集群时计费系统还需要处理资源隔离的问题。如果租户 A 的大量请求导致 GPU 显存占满会影响租户 B 的推理延迟。一种方案是为每个租户预留固定的 GPU 资源资源隔离但这样会大幅降低 GPU 整体利用率通常低于 40%。我们在生产中采用的方案是软隔离 优先级抢占默认所有租户共享资源池但当某个租户的 Token 消耗速率超过其购买配额的 2 倍时动态降低其请求优先级。这种方案的计费复杂度在于需要实时计算超额使用的惩罚费用需要在计费引擎中增加动态的单价调整逻辑。7.3 预付费与后付费的坏账风险预付费模式对平台现金流更友好但对用户的资金占用较高可能导致用户流失后付费模式用户体验更好但存在坏账风险。我们在生产中采用混合模式新注册用户默认后付费但当月消费超过 1000 美元时强制切换为预付费或提供信用卡担保。计费系统需要实时计算用户的信用风险评分基于历史付款及时性、账户余额趋势、调用量增长速度并在评分低于阈值时自动触发限额或暂停服务。这部分逻辑需要与计费系统深度集成在 Token 计量引擎中增加信用检查步骤通常增加的延迟在 5ms 以内基于 Redis 缓存的信用评分结果。八、总结大模型平台的计费架构需要同时兼顾实时性毫秒级配额检查、准确性微美元级费用计算和可靠性对账差异 0.1%。核心技术选型上推荐Redis Lua 脚本实现实时累计Kafka Flink实现准实时聚合ClickHouse存储历史账单数据。在业务层面至少需要支持预充值、后付费和混合配额三种模式并保持与成本系统的打通。数据一致性的保障需要从流式计数、幂等去重和时间边界三个维度同时治理。计费架构的设计不是一次性的工作而是需要随业务规模增长持续演进的系统工程。

相关新闻

LLM 服务的高可用架构——多 AZ 部署、故障转移与流量切换

LLM 服务的高可用架构——多 AZ 部署、故障转移与流量切换

LLM 服务的高可用架构——多 AZ 部署、故障转移与流量切换 一、背景与挑战 在企业级 AI 应用中,LLM(大语言模型)推理服务的可用性直接影响业务连续性。与传统的无状态微服务不同,LLM 推理服务具有 GPU 资源密集、推理延迟高、模型…

2026/7/19 0:19:08阅读更多 →
AI 编程工具如何参与真实项目?从需求分析到代码提交的完整流程

AI 编程工具如何参与真实项目?从需求分析到代码提交的完整流程

随着 AI 编程工具不断发展,越来越多开发者开始尝试让 AI 参与真实的软件开发流程。但很多人第一次使用时,会发现一个问题:让 AI 写一个函数很简单,但让它参与一个完整项目,却没有想象中那么容易。原因在于,…

2026/7/19 0:19:08阅读更多 →
内核启动核心——bootargs 启动参数详解与自定义配置

内核启动核心——bootargs 启动参数详解与自定义配置

内核启动核心——bootargs 启动参数详解与自定义配置本文由 黒漂技术佬 原创,首发于 CSDN,转载请注明出处。一、引言 前面我们学会了用 setenv 修改环境变量,今天要看的这个变量是 U-Boot 所有环境变量中的"王者"——bootargs。它决…

2026/7/19 0:17:08阅读更多 →
及时做APP开发实战(十四)-专注页面待办选择优化

及时做APP开发实战(十四)-专注页面待办选择优化

及时做APP开发实战(十四)-专注页面待办选择优化本文将介绍如何修复专注页面待办任务只显示5条的BUG,并优化弹窗交互体验。一、问题分析 1.1 问题现象┌─────────────────────────────────────┐ │ 选择待办任务 …

2026/7/19 2:31:26阅读更多 →
嵌入式应届生求职指南:从0项目经验到实战能力构建

嵌入式应届生求职指南:从0项目经验到实战能力构建

最近在嵌入式技术交流群中,经常看到应届生同学提问:"0项目经验找工作,包装简历靠谱吗?" 这确实是一个很现实的问题。作为从嵌入式开发一路走过来的技术人,我理解大家在求职季的焦虑,但更想从行业…

2026/7/19 2:31:26阅读更多 →
Anthropic发现语言模型J-space机制:AI思维可解释性与安全监控新突破

Anthropic发现语言模型J-space机制:AI思维可解释性与安全监控新突破

Anthropic最新研究发现,语言模型内部存在一个类似人类"全局工作空间"的机制,他们称之为J-space。这个发现不仅改变了我们对大语言模型工作原理的理解,更为模型可解释性和安全性监控提供了全新工具。这项研究基于Anthropic团队开发的…

2026/7/19 2:31:26阅读更多 →
STM32开发三件套:sys.c/delay.c/usart.c深度解析

STM32开发三件套:sys.c/delay.c/usart.c深度解析

1. STM32开发中的核心三件套:sys.c/delay.c/usart.c深度解析在STM32嵌入式开发领域,有三个基础文件几乎出现在每个工程中——sys.c、delay.c和usart.c。这三个文件构成了STM32开发的"铁三角",承担着系统初始化、精确延时和串口通信…

2026/7/19 2:31:26阅读更多 →
数据模型:让每条信息都带上时间戳

数据模型:让每条信息都带上时间戳

SkillGraphNode 技能图谱节点新增三个时间字段&#xff0c;追踪创建→更新→使用的完整生命周期&#xff1a; pub struct SkillGraphNode { // … 原有字段 … pub created_at: DateTime, pub updated_at: DateTime, pub last_used_at: Option<DateTime>, } created_at 和…

2026/7/19 2:31:26阅读更多 →
C#邮件发送实战:SmtpClient配置与高级应用

C#邮件发送实战:SmtpClient配置与高级应用

1. C#邮件发送基础与SmtpClient概述在C#开发中&#xff0c;邮件发送是一个常见需求&#xff0c;无论是系统通知、验证码发送还是业务报表&#xff0c;都需要可靠的邮件传输功能。.NET Framework提供了System.Net.Mail命名空间下的SmtpClient类来实现这一功能。这个类封装了SMTP…

2026/7/19 2:29:26阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/18 22:49:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/18 14:49:24阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/18 18:49:35阅读更多 →