国际集运计费引擎实现:策略模式+规则引擎处理复杂运费计算

简介: 本文详解Taocarts系统在阿里云的高可用部署方案:基于SLB+多ECS(2核4G)+RDS主从+Redis主备+OSS静态分离架构,集成CDN/WAF防护;提供一键初始化脚本、PM2集群部署及读写分离实现,支撑单站日处理5万订单,海外访问延迟降低60%。(239字)

摘要:反向海淘运费计算涉及首重续重、体积重、多国家差异化、多渠道路由。本文使用Java策略模式和Drools规则引擎实现灵活可配置的计费系统,支持实时计算和批量试算。

一、需求建模
运费规则示例:

美国云途专线:首重0.5kg/85元,续重0.5kg/25元,按实际重量计费

美国EMS:首重0.5kg/110元,续重0.5kg/35元,按体积重(长宽高/5000)取大

加拿大专线:首重1kg/120元,续重0.5kg/30元

二、策略模式实现
java
// 计费策略接口
public interface FreightCalculator {
BigDecimal calculate(ShippingPackage pkg, FreightRule rule);
}

// 实际重量策略
@Component
public class ActualWeightCalculator implements FreightCalculator {
@Override
public BigDecimal calculate(ShippingPackage pkg, FreightRule rule) {
double weight = pkg.getActualWeightKg();
if (weight <= rule.getFirstWeight()) {
return rule.getFirstPrice();
}
double additional = weight - rule.getFirstWeight();
int units = (int) Math.ceil(additional / rule.getAdditionalUnit());
return rule.getFirstPrice().add(rule.getAdditionalPrice().multiply(BigDecimal.valueOf(units)));
}
}

// 体积重策略
@Component
public class VolumetricWeightCalculator implements FreightCalculator {
@Override
public BigDecimal calculate(ShippingPackage pkg, FreightRule rule) {
double volumetric = pkg.getLengthCm() pkg.getWidthCm() pkg.getHeightCm() / 5000.0;
double weight = Math.max(pkg.getActualWeightKg(), volumetric);
// 复用实际重量计算逻辑
return actualWeightCalculator.calculate(new ShippingPackage(weight), rule);
}
}

// 策略工厂
@Component
public class FreightCalculatorFactory {
private final Map calculatorMap = new HashMap<>();

public FreightCalculatorFactory() {
    calculatorMap.put("actual", new ActualWeightCalculator());
    calculatorMap.put("volumetric", new VolumetricWeightCalculator());
    // 更多策略...
}

public FreightCalculator getCalculator(String type) {
    return calculatorMap.getOrDefault(type, calculatorMap.get("actual"));
}

}
三、规则引擎配置运费模板
java
// Drools规则文件 freight.drl
package com.taocarts.freight;

import com.taocarts.domain.ShippingRequest;
import com.taocarts.domain.FreightResult;

rule "US_YunExpress_Rule"
when
$req: ShippingRequest(destinationCountry == "US", channel == "YunExpress")
then
FreightRule rule = new FreightRule();
rule.setFirstWeight(0.5);
rule.setFirstPrice(new BigDecimal("85"));
rule.setAdditionalUnit(0.5);
rule.setAdditionalPrice(new BigDecimal("25"));
rule.setCalculatorType("actual");
$req.setMatchedRule(rule);
end

rule "US_EMS_Rule"
when
$req: ShippingRequest(destinationCountry == "US", channel == "EMS")
then
FreightRule rule = new FreightRule();
rule.setFirstWeight(0.5);
rule.setFirstPrice(new BigDecimal("110"));
rule.setAdditionalUnit(0.5);
rule.setAdditionalPrice(new BigDecimal("35"));
rule.setCalculatorType("volumetric");
$req.setMatchedRule(rule);
end
四、合并发货与拼单分摊
java
@Service
public class CombinedFreightService {
public CombinedFreightResult combineAndCalculate(List orderIds, String channel) {
// 1. 汇总订单商品
List orders = orderService.listByIds(orderIds);
double totalActualWeight = orders.stream().mapToDouble(Order::getTotalWeight).sum();
double totalVolumetricWeight = orders.stream()
.mapToDouble(o -> o.getLengthCm() o.getWidthCm() o.getHeightCm() / 5000.0)
.max().orElse(0);
double finalWeight = Math.max(totalActualWeight, totalVolumetricWeight);

    // 2. 获取运费规则
    FreightRule rule = freightRuleMapper.selectByChannelAndCountry(channel, orders.get(0).getCountry());
    FreightCalculator calculator = calculatorFactory.getCalculator(rule.getCalculatorType());
    BigDecimal totalFreight = calculator.calculate(new ShippingPackage(finalWeight), rule);

    // 3. 按重量分摊
    List<FreightShare> shares = new ArrayList<>();
    for (Order order : orders) {
        double shareRatio = order.getTotalWeight() / totalActualWeight;
        BigDecimal shareFreight = totalFreight.multiply(BigDecimal.valueOf(shareRatio));
        shares.add(new FreightShare(order.getId(), shareFreight));
    }
    return new CombinedFreightResult(totalFreight, shares);
}

}
五、性能优化
运费模板缓存到Redis,每小时刷新一次

体积重计算使用本地缓存减少重复计算

批量计费时使用CompletableFuture并行处理

经压测,单机可支持500次/秒的运费计算请求,P99延迟低于50ms。

目录
相关文章
|
1月前
|
Web App开发 缓存 安全
Quick BI使用案例25:重启电脑打开Chrome浏览器登录后,不到30分钟提示“未登录,当前请求被禁止”
本文详解Chrome浏览器因本地数据保存策略导致Quick BI登录30分钟内自动退出的成因,并提供两种可选的浏览器设置方案,助您稳定登录、释放产品价值。
|
机器学习/深度学习 JSON 数据格式
CatBoost模型部署与在线预测教程
CatBoost模型部署与在线预测教程【2月更文挑战第16天】
703 2
|
7天前
|
监控 NoSQL API
Flask + Celery实现异步任务处理:从同步阻塞到异步非阻塞的改造实战
本文介绍如何用Celery+Redis对Flask跨境电商接口进行异步优化:将邮件发送、物流API调用、PDF生成等耗时操作解耦为后台任务,接口响应从1850ms降至100ms内;并涵盖任务状态查询、自动重试、定时调度及监控告警等完整实践。
53 1
|
设计模式 缓存 前端开发
一款清新优雅的中后台模板,内置丰富可配置的主题(强烈推荐)
Soybean Admin 是一个基于 Vue3、Vite3、TypeScript、NaiveUI、Pinia 和 UnoCSS 的清新优雅的中后台模版,它使用了最新的前端技术栈,内置丰富的主题配置,有着极高的代码规范,基于 mock 实现的动态权限路由,开箱即用的中后台前端解决方案,也可用于学习参考。
|
1月前
|
Python
反向海淘订单系统设计:状态机与分布式事务实战
本文详解Taocarts反向海淘订单状态机设计与集运计费引擎:基于8状态有限状态机实现订单全生命周期管理,结合本地消息表+MQ保障分布式一致性;采用策略模式支持多渠道、体积重/实际重、首续重、拼单分摊等复杂计费场景,日均稳定处理数千订单。(239字)
87 0
|
1月前
|
人工智能 前端开发 数据挖掘
全链路实战:依托Codex完成PPT、数据分析、网页与APP一站式AI开发教程
在AI技术飞速迭代的当下,代码生成早已不是AI工具的单一能力边界。OpenAI旗下的Codex经过持续升级,如今已经成长为一款综合性智能生产力平台,除了经典的代码编写能力外,还支持插件调用、电脑远程操控、数据分析、多媒体制作、全品类应用开发等多元功能。本文将结合完整实操流程,一步步演示如何使用Codex完成PPT制作、体育赛事数据分析预测、网页开发以及移动端APP开发四大核心场景,全程记录操作指令、执行过程、代码实现以及问题优化方案,直观展现AI如何重塑传统工作与开发流程,同时剖析这套全链路AI工作模式的优势与现存局限。整套流程无需深厚的专业功底,普通办公人员、初级开发者都可以参考落地。
688 1
|
1月前
|
人工智能 JSON 自然语言处理
阿里云百炼产品月报【2026年5月】
本月阿里云百炼平台重磅升级:发布Qwen3.7系列大模型(Max版推理后付费5折)、Qwen3.5实时语音翻译模型及HappyHorse-1.0(8折体验);上线官方CLI工具,支持10+模态一键调用;Token Plan支持多座席共享与精细化管理;MCP广场新增航班、天气等专业服务;金融、法律垂直领域上新20+智能应用模板。
373 3
|
1月前
|
人工智能 缓存 运维
重磅发布丨云监控 AI Agent 可观测,企业生产级 Agent 首选全域观测平台
AI Agent 可观测是面向企业生产级 Agent 的全域观测平台,提供从接入、建模、分析到 Agentic Ops 的全域观测和分析能力,帮助企业彻底打开 Agent 的黑箱,实现 Agent 执行过程的可追踪、可诊断、可优化。
507 20
|
1月前
|
人工智能 安全 机器人
【AI 尝鲜实验室】上新 | QwenPaw:本地优先的多渠道个人 AI 助手,让 AI 分身住进你的钉钉与飞书
QwenPaw 是 AgentScope 团队开源的本地优先个人 AI 助手(GitHub 17.4k+ Stars,Apache-2.0 协议),非普通 ChatBot,而是具备长期记忆、多渠道接入(钉钉/飞书/微信/Discord)、本地跑模型、多 Agent 协作能力的“AI 分身”。本实验通过阿里云计算巢一键云端部署,浏览器安全代理即可快速配置使用。
|
1月前
|
缓存 Prometheus 监控
💰 1688开放平台API收费标准与资源包购买攻略(2026最新版)
1688开放平台API采用「免费额度+资源包+按量付费」三层计费模型:基础接口(商品/订单/物流)免费但限QPS;高频或实时库存、分销等需购年费资源包;超量部分按次计费(约0.001元/次)。合理配置可零成本支撑中小B2B系统。