如何用Firebase或SNS向150万用户发送含用户名的自定义推送通知?
针对150万用户的个性化推送优化方案
你当前使用messaging.send()单条逐个发送的方式,150万次独立HTTP请求必然导致耗时极长——每次请求都要建立连接、处理响应,效率极低。以下是基于Firebase和AWS SNS的优化方案:
一、Firebase Cloud Messaging (FCM) 优化方案
1. 改用批量发送API
FCM提供send_multicast()接口,一次最多可发送500条消息,大幅减少HTTP请求次数。每条消息可携带独立的用户个性化数据:
from firebase_admin import messaging # 假设user_list包含所有用户的{username, device_token}数据 messages = [] for user in user_list: update_body = { "username": user["username"], "content": "hope you are doing good...." } message = messaging.Message( data=update_body, token=user["device_token"], ) messages.append(message) # 每攒够500条发送一次 if len(messages) == 500: response = messaging.send_multicast(messaging.MulticastMessage(messages=messages)) print(f"批次发送:成功{response.success_count}条,失败{response.failure_count}条") messages = [] # 发送剩余不足500条的消息 if messages: response = messaging.send_multicast(messaging.MulticastMessage(messages=messages)) print(f"剩余发送:成功{response.success_count}条,失败{response.failure_count}条")
2. 客户端渲染个性化内容
把通用模板和用户名作为数据字段发送,由客户端负责拼接成完整通知正文,减少服务器端的字符串拼接开销:
// Android客户端示例 override fun onMessageReceived(remoteMessage: RemoteMessage) { val username = remoteMessage.data["username"] ?: "there" val content = remoteMessage.data["content"] ?: "hope you're doing well" val notificationBody = "Hey $username, $content" // 调用本地通知展示逻辑 showCustomNotification(notificationBody) }
3. 异步并发处理
用线程池并行发送批量请求,进一步提升发送效率:
from concurrent.futures import ThreadPoolExecutor from firebase_admin import messaging def send_batch(msg_batch): response = messaging.send_multicast(messaging.MulticastMessage(messages=msg_batch)) return response.success_count, response.failure_count # 拆分用户列表为500条一组的批次 batches = [user_list[i:i+500] for i in range(0, len(user_list), 500)] message_batches = [] for batch in batches: msg_batch = [] for user in batch: msg = messaging.Message( data={"username": user["username"], "content": "hope you are doing good...."}, token=user["device_token"] ) msg_batch.append(msg) message_batches.append(msg_batch) # 用10个线程并行发送 with ThreadPoolExecutor(max_workers=10) as executor: results = executor.map(send_batch, message_batches) # 统计总结果 total_success, total_failure = 0, 0 for success, failure in results: total_success += success total_failure += failure print(f"总发送结果:成功{total_success}条,失败{total_failure}条")
二、AWS SNS 推送方案
1. 注册设备端点并关联用户属性
将用户设备令牌注册为SNS端点,同时绑定username属性,方便后续模板调用:
import boto3 sns = boto3.client('sns', region_name='your-region') # 批量注册端点(需提前创建SNS平台应用) for user in user_list: endpoint_arn = sns.create_platform_endpoint( PlatformApplicationArn='your-platform-app-arn', Token=user["device_token"], Attributes={"username": user["username"]} )["EndpointArn"] # 将endpoint_arn与用户ID关联存入数据库 save_user_endpoint(user["id"], endpoint_arn)
2. 使用模板批量发送
提前在SNS创建消息模板(内容示例:Hey {{username}}, hope you are doing good....),然后批量发送到端点:
# 从数据库获取所有用户的endpoint_arn endpoint_arns = [user["endpoint_arn"] for user in user_list] template_arn = 'your-sns-template-arn' # 每100条为一组批量发送 for i in range(0, len(endpoint_arns), 100): batch = endpoint_arns[i:i+100] request_entries = [ { 'Id': str(idx), 'TargetArn': arn, 'TemplateArn': template_arn } for idx, arn in enumerate(batch) ] response = sns.publish_batch(PublishBatchRequestEntries=request_entries) print(f"批次发送:成功{len(response['Successful'])}条,失败{len(response['Failed'])}条")
三、方案对比
- FCM:适合已有Firebase生态的项目,批量API简单易用,免费额度足够支撑大流量,客户端个性化处理灵活。
- AWS SNS:适合AWS生态项目,端点管理和模板功能更成熟,支持多平台推送,按发送量计费。
内容的提问来源于stack exchange,提问作者santosh kumar panda
相关产品推荐
相关产品推荐

