在电信行业快速发展的今天,资费管理系统的复杂性已经远超传统人工处理的能力范围。作为一名经历过多个电信项目开发的老兵,我深刻理解这个领域的痛点所在。记得2018年参与某省级运营商项目时,他们的资费套餐组合多达2000余种,每月处理的话单数据超过10亿条,仅靠Excel和简单数据库已经难以为继。
电信资费管理系统的核心挑战主要体现在三个方面:
经过多个项目的实践对比,Django框架在电信级系统开发中展现出独特优势:
python复制class Package(models.Model):
name = models.CharField(max_length=100)
fee_items = models.ManyToManyField('FeeItem', through='PackageFeeItem')
class FeeItem(models.Model):
name = models.CharField(max_length=50)
price = models.DecimalField(max_digits=10, decimal_places=2)
python复制class FeeItemAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(region=request.user.userprofile.region)
经过多次迭代,我们最终采用的架构方案如下:
code复制[前端Vue.js] ←HTTP→ [Django REST Framework] ←→ [核心业务层]
↓
[Celery Workers] ←→ [Redis] ←→ [MySQL集群]
↑
[话单采集系统] → [Kafka] → [流处理引擎]
关键设计要点:
电信资费的本质是资源定价模型,我们将其抽象为四个核心实体:
python复制class ResourceItem(models.Model):
RESOURCE_TYPES = (
('VOICE', '通话时长(分钟)'),
('SMS', '短信条数'),
('DATA', '流量(MB)'),
)
resource_type = models.CharField(max_length=20, choices=RESOURCE_TYPES)
amount = models.PositiveIntegerField()
class FeeItem(models.Model):
name = models.CharField(max_length=100)
base_price = models.DecimalField(max_digits=10, decimal_places=2)
resources = models.ManyToManyField(ResourceItem, through='FeeItemResource')
计费核心采用规则引擎+批处理模式:
python复制def calculate_bill(user, start_date, end_date):
# 获取用户套餐
subscriptions = UserSubscription.objects.filter(
user=user,
start_date__lte=end_date,
end_date__gte=start_date
)
# 获取话单记录
call_records = CallRecord.objects.filter(
user=user,
call_time__range=(start_date, end_date)
)
bill = Bill.objects.create(user=user, period_start=start_date, period_end=end_date)
# 分资源类型计费
for sub in subscriptions:
for fee_item in sub.package.fee_items.all():
calculate_fee_item(bill, fee_item, call_records)
return bill
重要提示:电信计费必须考虑事务一致性,我们采用Django的transaction.atomic装饰器保证计费过程的原子性。
针对高频查询场景,我们采用多级缓存策略:
python复制@cache_page(60 * 5)
@cache_control(private=True)
def get_balance(request, user_id):
cache_key = f'user_balance_{user_id}'
balance = cache.get(cache_key)
if balance is None:
balance = calculate_real_time_balance(user_id)
cache.set(cache_key, balance, timeout=60)
return JsonResponse({'balance': balance})
当多个套餐或活动叠加时,容易产生资费规则冲突。我们开发了冲突检测算法:
python复制def check_conflict(new_fee_item, existing_items):
conflict_rules = []
for item in existing_items:
# 检查资源类型重叠
common_resources = set(new_fee_item.resources.all()) & set(item.resources.all())
if common_resources:
conflict_rules.append(f"与套餐{item.name}资源冲突")
# 检查时间重叠
if (new_fee_item.start_date <= item.end_date and
new_fee_item.end_date >= item.start_date):
conflict_rules.append(f"与套餐{item.name}时间冲突")
return conflict_rules
月末出账时的话单处理压力极大,我们的优化方案:
python复制@shared_task
def process_call_records(records):
# 批量创建话单对象
objs = [CallRecord(**r) for r in records]
CallRecord.objects.bulk_create(objs, batch_size=1000)
# 触发实时计费
user_ids = {r['user_id'] for r in records}
for uid in user_ids:
update_real_time_billing.delay(uid)
推荐的基础设施配置:
| 组件 | 规格 | 数量 | 备注 |
|---|---|---|---|
| 应用服务器 | 8核16G | 2+ | 建议Docker部署 |
| MySQL | 16核64G SSD | 3 | 主从复制+读写分离 |
| Redis | 8核16G | 2 | 哨兵模式 |
| Celery Worker | 按业务分队列 | 4+ | 话单处理单独队列 |
数据库优化:
缓存策略:
前端优化:
在实际运营中,我们持续迭代了以下功能:
这个Django实现的电信资费管理系统已经在多个省级运营商稳定运行,日均处理话单超过5000万条,支持同时在线用户查询超过1万QPS。开发过程中最大的体会是:电信业务虽然复杂,但只要做好领域建模和性能规划,Django完全能够胜任企业级应用开发。