英文:
System Design: Real Time Location Based Notification System
问题
问题描述
如何使用Firebase Messaging和Android/iOS应用程序设计一个基于实时位置的通知系统?
场景
- 用户A创建了一个报告。
- 如果用户B位于用户A报告位置的5公里半径范围内,用户B应该收到通知(即:所有附近的用户都会收到通知)。
该应用程序可能有数千名并发用户频繁发布报告。
通知应尽可能实时地传递。
通知应传递给应用程序内5公里半径范围内的任何人。使用地理围栏选项,在特定区域设备唤醒不是一个选择,因为当附近发生报告时,用户应始终收到通知。
考虑的方法
方法A:
- 定期将用户位置上传到服务器并存储在数据库中。
- 当有新报告时,查找半径内的用户,并向每个个体设备/FCM令牌发送通知。
优点:
- 必须不断将用户位置上传到服务器(服务器负载、可扩展性、隐私)。
方法B:
- 每个客户端应用程序订阅FCM主题,例如'new-reports'。
- 当有新报告时,服务器发布"data-only" FCM事件到'new-reports'主题。
- FCM向所有设备发送消息,设备唤醒并检查用户是否在报告半径内。
- 如果是,应用程序创建通知。
优点:
- 较少的服务器处理
缺点:
- 不适用于iOS,因为后台数据仅消息不总是传递到iOS客户端。
- 事件发送给应用程序的每个用户,无论他们是否在该区域内。
方法B似乎是两种方法中较小的恶,但由于iOS中后台数据仅消息不会被传递,所以不适用于iOS。方法A听起来像是电池耗尽的问题,并且如果不断发送位置到服务器,可能会引发隐私问题。
对于在这里采取的良好方法有何想法?
英文:
Problem Statement
How to design a Live Location Based Notification system using Firebase Messaging with Android / iOS Apps?
Scenario
- User A creates a report
- If User B is located within a 5km radium of User A's report location, User B should get a notification (ie: all nearby users get notified)
The app can have 1000's of concurrent users, publishing reports frequently.
Notifications should be delivered as real time as possible.
The notification should be delivered to anyone with the app within a 5km radius. Using GeoFencing option, where device wakes up in a certain area is not an option, as user should always be notified when a report near them happens.
Considered Approaches
A:
- Upload user locations to server every so often and store in database
- When new report, find users within radius, and send notification to each individual device/FCM token
Cons:
- Have to constantly upload user location to server (server load, scalability, privacy)
B:
- Each client app subscribes to FCM Topic such as 'new-reports'
- When new report, server publishes 'data-only' FCM event to 'new-reports' topic
- FCM sends message to all devices, device wakes up and checks if users is within report radius
- If so, app creates notification
Pros:
- Less server processing
Cons:
- Does not work with iOS, as background data only messages are not always delivered to iOS clients
- Event sent to every user of app - regardless of if they're in that area or not
Approach B seems the lesser of 2 evils to me, however does not work with iOS due to data only messages not being delivered on iOS in background. Approach A sounds like a battery drain, and potential privacy concern if have to keep sending location to server.
Any thoughts on what a good approach would be to take here?
答案1
得分: 0
B 无法扩展到成千上万的用户。假设您有 N 个用户,每小时生成 R 份报告。这意味着您每小时总共有 NR 份报告。您需要将这些报告发送给 N 个用户,意味着每小时将有 N^2R 条消息。您的负载将随用户数量的平方增长。您将花费大量资金用于服务器和处理。更不用说您很快会达到消息限制(电源节省模式只允许每小时发送有限数量的消息,之后将停止允许高优先级的推送通知)。虽然 A 在隐私方面更好,但它无法扩展。实际上,无论如何,使用此应用程序都不会保护隐私,因为每次将报告发送到服务器时,您都必须发送位置信息。
如果您想稍微模糊位置,可以将地图分成区域,并仅报告您所在的区域(整个5公里圆的方法本来就不会很好,因为进行不精确但更快速的纬度/经度查找而不是计算精确圆更为高效)。然后,您只需要将位置以25平方公里的块形式发送到服务器。
英文:
B isn't going to scale to thousands of users. Let's say you have N users each with R reports per hour. That means you have NR reports per hour total. You need to send that to N users, meaning N^2R messages per hour. Your load scales at the square of your number of users. You'll spend a fortune on servers and processing. Not to mention that you'll quickly hit message limits (power savings mode only allows so many messages per hour before they stop allowing high priority push notifications). While A is the better one for privacy, it does not scale. Realistically you'll have no privacy with this app anyway, anytime you send a report to the server you'd have to send the location.
If you want to obscure location a bit, break the map into zones and only report what zone you're in (the whole 5km circle thing was never going to work well anyway since its so much more efficient to just do less accurate but faster lat/lng lookups without calculating exact circles). Then you'd only have their locations going to the server in 25 square km blocks.
答案2
得分: 0
这是我最终采用的方法,解决了上述许多缺点。
- 当创建新报告时,在该纬度和经度处计算GeoHash。
- 将报告发布到FCM主题,“new-reports-< geohash值 >”。
- Android/iOS客户端订阅“new-reports-<附近geohash>”。
- 对于所有落入5公里半径内的GeoHash,重复步骤3。
这种方法的主要缺点在于精确性 - 例如:5公里半径可能落入一个GeoHash区域的一半,这意味着即使在5公里半径之外,您也会收到通知。对于我的目的来说,这种权衡是可以接受的,因为它不必非常精确。
在这里了解更多关于GeoHash的信息。
英文:
Here's the approach I ended up using which addresses a lot of the cons above.
- When a new report is created, calculate the GeoHash at that latitude, longitude
- Publish report to FCM topic, 'new-reports-< geohash value >'
- Android/iOS Client subscribes to 'new-reports-< geohash near them>'
- Repeat Step 3 for all geohashes that fall within the 5km radius
The main con with this approach is around accuracy - eg: 5km radius may fall into half of a GeoHash Zone, meaning you get notified even though it's outside the 5km radius. For my purposes, this tradeoff is acceptable as it does not have to be extremely accurate.
Read more on GeoHashes here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论