linux - 持有TCP连接的大规模websocket系统设计
问题描述
假设您有一个非常大的系统(在任何给定时刻都有数亿用户活跃),并且您需要主动将消息/通知从服务器推送到其客户端端点。有几千台机器专门用于与活动用户保持 TCP 连接是否很常见?
如果是这样,我想在这些机器前面有一个“查找服务”,它决定哪台机器user_id
应该连接到哪台机器(例如:使用映射user_id
到 a的哈希函数server_id
),对吧?
我的问题是,像 Facebook/Twitter 的通知层这样的大型系统是这样构建的吗?通过使用大量专用于保持 TCP 连接的机器,并在前面有一个映射user_id
到的查找服务server_id
?如果是这样,他们如何处理服务器故障的情况?当您需要添加更多服务器时会发生什么,因为服务器编号发生了变化,我们不需要重新散列所有用户吗?
谢谢!
解决方案
对此有许多不同的方法,但它们都归结为“分而治之”的技术。
这些技术将网络划分为“区域”,其中每个“区域”负责数据/网络的一个子集。
这些“区域”可以进一步细分为更小的“区域”,以便随着需求的变化进一步扩展。
这个“区域”树上的每个叶节点都可能拥有一整套机器(负载均衡器、缓存(即内存缓存)、数据库或 API 端点),具体取决于应用程序的要求。
AWS 受欢迎的部分原因是因为它提供了很多工具,使可扩展性更易于管理。
这取决于您的用例,但在地理上划分区域是有意义的(考虑 CDN 的工作方式)。
例如,可以将应用程序划分为每个大陆的区域,即亚洲、欧洲、美洲、非洲、大洋洲等。
这些区域中的每一个都可能按国家/州进一步划分。
由于流量大(第三层路由/重定向),某些州可能需要多个(子)区域。
这些子区域中的每一个都将拥有自己的(子)域、负载平衡器和许多管理该区域的连接和数据的机器。
这个地理划分的例子可以(理论上)通过地理定位 DNS 响应来最小化网络流量和延迟。这将允许(例如)纽约市的流量保持在纽约市,除非需要“跨境”通信。
“跨境”通信有时会延迟和聚合,以最大限度地减少流量和数据库事务(对于实时应用程序您不会这样做)。
显然,这有许多并发症。例如:如果美国用户在英国旅行怎么办?我们是将他的数据移动到不同的区域,还是将连接路由到美国服务器,并具有所有延迟?...
然而,最终,别无选择,只能“分而治之”。即使是数据库也无法在一台机器上保存所有数据,必须将数据划分为不同数据库上的子集。
此外,一些数据(如区域分配)很难划分。有些数据坚持“全局”(例如,我们如何知道用户属于哪个区域?)......这通常是使用哈希值的地方。
使用哈希值计算分布时,以后重新分布数据变得更加困难。这仍然是可能的,尤其是在使用对数区域划分时,但这只是众多可能解决方案中的一种方法。
推荐阅读
- python - 插件 allennlp_models 无法加载:没有名为“allennlp.modules.transformer.t5”的模块
- reactjs - 反应中useCallback()挂钩上缺少依赖项(道具)错误
- sql - 通过 2 个类别 SQL (Amazon Redshift) 输出平均总计
- sql-server - Devexpress:如何在同一列中显示不同的编辑器
- material-ui - MUI Select 消失在屏幕外
- javascript - XLSX 包在桌面应用程序中下载为 Excel
- java - 如何在 Harmony OS 中显示图像网格(GridLayout)?
- airflow - 在 Airflow 中更改现有 DAG 的开始日期
- reactjs - 如何使用 JEST 和 React 测试库模拟 Geolocation API
- java - 修改后的单元格字体无法保存 (XSSF)