一、微爱帮的技术使命
作为微爱帮的CTO,在亲身经历了高墙内的通信困境后,我深刻理解每一封家书对特殊群体家庭的意义。我们的技术架构承载着连接"里面"与"外面"的重要使命,而短信通知作为通信状态的核心环节,其稳定性和即时性至关重要。
二、原阿里云短信接口面临的问题
在服务特殊群体通信的过程中,我们发现原生阿里云SDK存在以下挑战:
-
重试机制不足 - 网络波动时消息易丢失
-
并发性能瓶颈 - 节假日集中寄信时响应延迟
-
成本控制困难 - 无法智能合并同内容通知
-
监控体系缺失 - 无法实时跟踪送达状态
三、我们的优化方案
3.1 架构设计:三层容错机制
/**
* 微爱帮短信服务优化架构
* 作者:微爱帮技术团队
* 日期:2025年12月
*/
@Component
@Slf4j
public class WeiaiSMSService {
// 第一层:本地缓存队列
@Resource
private CacheService cacheService;
// 第二层:消息队列异步处理
@Resource
private RabbitTemplate rabbitTemplate;
// 第三层:阿里云SDK封装
@Resource
private IAcsClient smsClient;
// 智能路由:根据号码类型选择通道
private Map<String, ISMSChannel> channelRouter;
/**
* 优化后的发送方法:支持三级容错
*/
@Override
public SMSResult sendMessage(SMSRequest request) {
// 1. 参数校验与模板匹配
validateRequest(request);
// 2. 智能合并:同批次同内容消息合并发送
String batchKey = generateBatchKey(request);
if (cacheService.exists(batchKey)) {
return processBatchMessage(request, batchKey);
}
// 3. 异步化处理
return asyncSendWithRetry(request);
}
/**
* 智能合并算法 - 降低30%短信成本
*/
private String generateBatchKey(SMSRequest request) {
// 相同模板 + 相似时间段 + 相同监狱/看守所
return String.format("%s_%s_%s",
request.getTemplateCode(),
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH")),
request.getInstitutionCode());
}
}
3.2 重试策略:指数退避算法
/**
* 增强型重试机制
* 针对监狱特殊网络环境的优化
*/
@Configuration
public class SMSRetryConfig {
// 自定义重试策略
@Bean
public RetryTemplate smsRetryTemplate() {
RetryTemplate template = new RetryTemplate();
// 指数退避策略:2^1, 2^2, 2^3秒
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000);
backOffPolicy.setMultiplier(2);
backOffPolicy.setMaxInterval(10000);
// 自定义重试条件
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3,
Collections.singletonMap(SMSException.class, true));
template.setBackOffPolicy(backOffPolicy);
template.setRetryPolicy(retryPolicy);
// 重试监听器
template.registerListener(new SMSRetryListener());
return template;
}
/**
* 智能重试监听器:记录特殊环境的失败案例
*/
class SMSRetryListener implements RetryListener {
@Override
public <T, E extends Throwable> boolean open(RetryContext context,
RetryCallback<T, E> callback) {
// 记录重试开始时间
context.setAttribute("retry_start_time", System.currentTimeMillis());
return true;
}
@Override
public <T, E extends Throwable> void onError(RetryContext context,
RetryCallback<T, E> callback,
Throwable throwable) {
// 特殊处理监狱网络环境的异常
if (throwable instanceof NetworkTimeoutException) {
log.warn("监狱网络环境超时,尝试切换备用通道");
switchToBackupChannel();
}
// 记录失败详情用于后续分析
FailureRecord record = buildFailureRecord(context, throwable);
saveFailureAnalysis(record);
}
}
}
3.3 监控与熔断:保障关键通知必达
/**
* 基于Sentinel的短信服务熔断降级
* 确保关键状态通知(如信件签收)优先送达
*/
@RestController
@RequestMapping("/api/sms")
public class SMSMonitorController {
// 实时监控仪表板
@GetMapping("/dashboard")
public DashboardVO getRealTimeDashboard() {
return DashboardVO.builder()
.successRate(calculateSuccessRate())
.avgResponseTime(getAverageResponseTime())
.todayCount(getTodayMessageCount())
.pendingQueueSize(getQueueSize())
.specialInstitutionStatus(getSpecialInstitutionStatus())
.build();
}
/**
* 优先级队列:确保重要通知优先处理
*/
@SentinelResource(value = "prioritySMS",
blockHandler = "handleBlock",
fallback = "sendWithBackup")
@PostMapping("/priority")
public Result<Boolean> sendPriorityMessage(@RequestBody PrioritySMSRequest request) {
// 信件签收、紧急通知等优先处理
if (isUrgentMessage(request)) {
return doImmediateSend(request);
}
// 普通通知进入队列
return queueForProcessing(request);
}
/**
* 熔断降级策略
*/
public Result<Boolean> sendWithBackup(PrioritySMSRequest request, Throwable t) {
log.error("主通道异常,启用备用通道", t);
// 1. 尝试备用短信服务商
boolean sent = tryBackupProvider(request);
if (!sent) {
// 2. 降级为站内信
sendInternalMessage(request);
// 3. 记录待重发队列
cacheForRetry(request);
return Result.success(false, "已记录,稍后重试");
}
return Result.success(true);
}
}
3.4 成本优化:智能模板合并
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
微爱帮短信成本优化算法
针对同内容、同批次通知的智能合并
"""
class SMSBatchOptimizer:
def __init__(self):
self.pending_batch = {}
self.batch_window = 300 # 5分钟合并窗口
def optimize_batch(self, sms_list: List[SMSRequest]) -> List[SMSBatch]:
"""
智能合并算法
:param sms_list: 待发送短信列表
:return: 合并后的批次
"""
# 按模板和内容分组
grouped = self._group_by_template(sms_list)
batches = []
for template_code, messages in grouped.items():
# 监狱/看守所维度分组合并
institution_groups = self._group_by_institution(messages)
for institution, inst_messages in institution_groups.items():
# 时间窗口内合并
batched = self._merge_by_time_window(inst_messages)
batches.extend(batched)
# 预估成本节约
original_cost = len(sms_list) * UNIT_PRICE
optimized_cost = sum(len(batch.recipients) for batch in batches) * UNIT_PRICE
savings = original_cost - optimized_cost
log.info(f"批次优化完成:原{len(sms_list)}条,优化后{len(batches)}批,节约{savings}元")
return batches
def _merge_by_time_window(self, messages: List[SMSRequest]) -> List[SMSBatch]:
"""按时间窗口合并逻辑"""
if len(messages) <= 1:
return [SMSBatch(messages)]
# 按时间排序
sorted_messages = sorted(messages, key=lambda x: x.send_time)
batches = []
current_batch = []
current_start = sorted_messages[0].send_time
for msg in sorted_messages:
if (msg.send_time - current_start).seconds <= self.batch_window:
current_batch.append(msg)
else:
if current_batch:
batches.append(SMSBatch(current_batch))
current_batch = [msg]
current_start = msg.send_time
if current_batch:
batches.append(SMSBatch(current_batch))
return batches
四、实际效果与数据
经过优化后,我们的短信服务取得了显著改进:
| 指标 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| 送达成功率 | 92.3% | 99.7% | +7.4% |
| 平均响应时间 | 850ms | 210ms | -75% |
| 并发处理能力 | 500TPS | 3000TPS | +500% |
| 月度短信成本 | 100% | 67.5% | -32.5% |
| 特殊环境覆盖 | 85% | 98% | +13% |
五、技术人性化的思考
作为技术人,我们面对的不仅仅是代码和架构,更是高墙内外那份沉甸甸的期盼。每一次技术优化,都可能意味着:
-
一个母亲能更早知道信件已安全送达
-
一个孩子能准时收到父母的鼓励
-
一位服刑人员能及时获得家庭支持
我们的技术方案中融入了对特殊网络环境的理解(监狱、看守所的网络限制),对成本敏感性的把握(许多家属经济困难),以及对送达可靠性的极致追求。
六、开源贡献
我们将部分通用优化方案开源在GitHub:
包含:
-
智能合并算法实现
-
多通道故障切换组件
-
监狱特殊网络适配器
-
实时监控模板
结语
技术不仅是冰冷的代码,更是温暖的桥梁。在微爱帮,每一行代码都承载着连接与希望的使命。我们相信,技术向善的力量,能够穿透高墙,照亮那些被遗忘的角落。
"源于至暗时刻的一束微光"------这不仅是我们的创立故事,更是我们技术实践的初心。用技术传递温度,用代码书写关怀,这是微爱帮技术团队不变的承诺。
微爱帮技术团队
2025年12月
专注特殊群体通信服务