多SMS网关运行时切换的最优设计模式选型
推荐设计方案:策略模式+工厂模式+动态权重调度
核心模式组合
1. 策略模式(Strategy Pattern)
- 先定义一个统一的
SMSGateway接口,要求所有短信网关供应商的实现类都实现这个接口,包含发送短信、获取成功率、获取单条成本、健康检查这些核心方法。 - 每个网关(比如Twilio、Plivo)各自编写专属实现类,封装自身的发送逻辑和数据。这样切换网关时完全不用修改核心的短信发送逻辑,直接替换实现类即可。
2. 工厂模式(Factory Pattern)
- 实现一个
SMSGatewayFactory工厂类,它的核心职责是根据你设定的规则(比如优先成功率、优先成本,或两者加权),从所有可用网关中筛选出最合适的实例。 - 工厂内部可维护各网关的实时状态,比如是否在线、近期成功率波动情况,这些数据都能作为选择网关的依据。
关键补充逻辑(保障100%可用+成本最优)
- 实时健康检查:给每个网关实现类添加健康检测方法,定期调用网关测试接口或统计近期发送成功率,标记不可用的网关,调度时直接跳过。
- 动态权重计算:结合你准备的成本、成功率数据,搭配实时状态计算每个网关的权重。比如可以设定权重公式:
权重=成功率*0.7 + (1/单条成本)*0.3(比例可根据业务侧重调整),权重越高的网关优先级越高。 - 失败自动降级:如果当前选中的网关发送失败,工厂自动切换到下一个权重最高的可用网关,直到发送成功或遍历完所有可用网关。
简化版代码示例
统一网关接口
public interface SMSGateway { // 发送短信 boolean sendSMS(String phoneNumber, String content); // 获取成功率 double getSuccessRate(); // 获取单条短信成本 double getCostPerSMS(); // 健康检查 boolean isHealthy(); }
具体网关实现(以Twilio为例)
public class TwilioGateway implements SMSGateway { @Override public boolean sendSMS(String phoneNumber, String content) { // 这里编写Twilio的实际发送逻辑 return true; } @Override public double getSuccessRate() { // 可设为预设值或实时统计结果 return 0.98; } @Override public double getCostPerSMS() { return 0.01; // 单位:美元/条 } @Override public boolean isHealthy() { // 编写实时健康检查逻辑,比如调用Twilio状态接口 return true; } }
网关工厂与调度逻辑
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class SMSGatewayFactory { // 初始化所有网关实例 private List<SMSGateway> gateways = Arrays.asList(new TwilioGateway(), new PlivoGateway()); public SMSGateway selectOptimalGateway() { // 先过滤出健康的网关 List<SMSGateway> healthyGateways = gateways.stream() .filter(SMSGateway::isHealthy) .collect(Collectors.toList()); if (healthyGateways.isEmpty()) { throw new IllegalStateException("所有短信网关均不可用"); } // 按权重从高到低排序,返回优先级最高的网关 return healthyGateways.stream() .sorted((g1, g2) -> Double.compare(calculateWeight(g2), calculateWeight(g1))) .findFirst() .get(); } // 自定义权重计算逻辑,可按需调整 private double calculateWeight(SMSGateway gateway) { // 侧重成功率(70%)+ 成本优势(30%) return gateway.getSuccessRate() * 0.7 + (1 / gateway.getCostPerSMS()) * 0.3; } }
短信Wrapper核心逻辑
import java.util.ArrayList; import java.util.List; public class SMSWrapper { private SMSGatewayFactory gatewayFactory; public SMSWrapper(SMSGatewayFactory gatewayFactory) { this.gatewayFactory = gatewayFactory; } public boolean sendSMS(String phoneNumber, String content) { List<SMSGateway> triedGateways = new ArrayList<>(); while (true) { SMSGateway currentGateway = gatewayFactory.selectOptimalGateway(); // 避免重复尝试同一个网关 if (triedGateways.contains(currentGateway)) { return false; } boolean sendSuccess = currentGateway.sendSMS(phoneNumber, content); if (sendSuccess) { return true; } triedGateways.add(currentGateway); // 可选:标记该网关临时不可用(比如5分钟内不再选中) } } }
方案适配性说明
- 运行时切换:策略模式让网关实现完全解耦,工厂可随时根据规则调整选中的网关,无需修改核心发送代码。
- 高可用性:健康检查+失败降级机制,确保单个网关故障时自动切换到其他可用网关,最大化发送成功率。
- 成本效益:动态权重计算能平衡成功率和成本,既不会盲目选择最便宜但不可靠的网关,也不会只选最可靠但成本过高的选项,完全贴合你的需求。
内容的提问来源于stack exchange,提问作者Muthu Nadar
相关产品推荐
相关产品推荐

