返回首页
最新
嗨,HackerNews!
我最近为我的AI增强平台Ampledata添加了API和文档。这个想法很简单。给定一组表格中的行,你可以通过API访问Ampledata,系统会运行一个工作流程,通过搜索网络来丰富表格,添加你选择的列,并提供引用和确切来源。你可以把它看作是一个带有引用的批量增强平台。
Ampledata也是开源软件,所以欢迎自行托管并使用你自己的API密钥。如果你只是对技术感兴趣,也可以使用。
嗨,HN,我从零开始构建了一个游戏服务器编排器,作为一名独立开发者,我花了超过三年的时间,每天几乎工作10个小时,终于在2023年初完成了它。现在我26岁了!
我在完成这个项目过程中遇到的复杂性和需要研究的内容,连我自己都无法想象,但嘿,这就是我迄今为止最大的职业成就。
下面我将尝试简要介绍我游戏服务器编排器的一些核心和最重要的功能。
1. 核心绑定与CCD缓存对齐
我必须研究和理解CPU缓存布局。我发现,如果我的游戏容器(使用docker run)跨越不同的核心复合体(CCD)或与繁忙的邻居共享SMT兄弟线程,L3缓存的冲突会严重影响单核时钟的效率。
因此,我将所有非游戏服务器进程严格绑定在核心0及其SMT兄弟核心12上,使用GRUB:
我禁用了1000Hz的定时器中断,以防止上下文切换,从而避免污染L3缓存。
我还将RCU卸载到核心0和12,以避免对游戏容器的微中断,并将100%的性能留给游戏容器。
```bash
GRUB_CMDLINE_LINUX_DEFAULT="nomodeset isolcpus=1-11,13-23 nohz_full=1-11,13-23 rcu_nocbs=1-11,13-23"
```
至于游戏容器,正如我提到的,我直接使用docker run,因为不需要swarm,这实际上是一个糟糕的设计。我有一个编排服务,使用算法来计算将游戏服务器容器绑定到哪个CCD核心是最好的:
```csharp
// Zen 4核心复合体(CCD)映射
int siblingOffset = totalHardwareThreads / 2;
int coresPerCcd = siblingOffset / 2;
int getCcdId(int i) => ((i % siblingOffset) < coresPerCcd) ? 0 : 1;
int getSibling(int i) => (i < siblingOffset) ? (i + siblingOffset) : (i - siblingOffset);
```
我还将内存限制和内存保留设置为相等(--memory == --memory-reservation),以使内核将该RAM物理锁定,并阻止交换使用,以避免邻居噪声问题。
如上所述,编排器试图为游戏服务器找到性能最佳的线程,这意味着主机节点的CPU会被碎片化。针对这种情况,我有一个算法在主机节点上模拟每个正在运行的游戏容器的最佳位置,然后动态地、实时地重新定位一些或所有容器,而无需重启容器或断开任何活跃玩家的连接:
```bash
docker update --cpuset-cpus="{cpuSet}" {containerName}
```
2. 使用EBPF/XDP和NFTABLES防止DDoS攻击,因为游戏服务器经常遭受DDoS攻击、机器人或其他特别针对的攻击,可能是所谓的脚本小子或有时甚至是心情不好的玩家,哈哈。
一开始我尝试使用UFW,但最终放弃了,因为它与docker冲突,这让我花了相当长的时间才意识到这一点,因为我当时还在研究网络层的工作原理。
为了获得最佳保护,我决定对每个端口设置连接速率限制。如果达到限制,我会使用黑名单将违规者的IP记录下来,并设置特定的计时器,然后立即将这些黑名单IP注册到eBPF映射中。这些IP在禁令过期时会动态地从每个列表/映射中添加和移除。
不过,有一个边缘案例是AnonymousPipeClientStream,许多游戏有许多不同的mod和插件,这可能会增加数据包的速率。尽管我尽力在我设置的默认速率限制规则中考虑到这一点,并允许游戏服务器所有者在需要时调整这些限制,类似于Cloudflare的方式,提供四种配置文件:标准、宽松、严格、攻击中。
我已经根据实际数据尽可能优化了标准配置,应该足以满足99%的服务器需求,其他配置可以在一些重度修改的服务器等罕见情况下使用。
因此,DDoS缓解的最佳方法是使用nftables对每个游戏服务器端口设置限制。
我还将rmem_max/wmem_max缓冲区提升到16MB,以便特定的游戏容器线程在直接将映射数据注册到RAM时不会阻塞,默认的写入缓冲区大约只有200KB,通过这样做,玩家的时钟处理速度更快。
由于用户需要管理游戏文件,包括上传、下载、编辑、删除等,我使用fireqos来优先处理游戏流量,这意味着游戏流量走快速通道,不会因客户端使用文件管理器的操作而受到限制,从而确保游戏保持无延迟。
我还使用TCP BBR拥塞控制,而不是默认的Linux CUBIC,因为后者没有优化,导致回弹,因为它假设如果游戏服务器和玩家之间有数据包丢失,就一定存在网络拥塞,结果降低了传输速度,从而导致延迟峰值。BBR拥塞控制的作用是测量游戏服务器和玩家之间的实际带宽,并以玩家能够消耗的速度发送数据包,从而避免回弹。
我还使用公平排队(fq),以避免单个游戏服务器所有者在某些人决定上传或下载大文件时占用所有带宽。
```bash
# BBR拥塞控制
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# UDP/TCP缓冲区扩展
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
```
3. SSR缓存污染解决方案。
为了避免Angular SSR缓存污染,我有两个端点,/graphql - 公开和只读数据,直接在Cloudflare上缓存,该端点立即拒绝任何身份验证头,拒绝整个请求,以防止缓存污染和请求之间的状态共享。第二个端点是/secure,处理任何经过身份验证的数据,不缓存任何内容。此外,我所有的网络服务,如前端、API、数据库调用,都使用我的私有WireGuard网状网络,增加了一层安全性。
在Node.js的SSR过程中,我完全跳过了TLS握手,这会增加一些延迟,使用本地Docker swarm网络直接访问我的API。
-----
正如我提到的,我是一名独立开发者,完全自掏腰包启动这个项目,我有两台裸金属节点,一台在欧洲,另一台在美国中部。
今天,我的目标是看看我的编排器如何处理实际使用情况,然后再进行扩展,因此我邀请任何人使用我的免费试用启动一个游戏服务器,尝试挑战我的系统。
如果有人愿意,可以直接访问 [https://ray-hosting.com/en-US/free-trial](https://ray-hosting.com/en-US/free-trial) 注册以自动申请免费试用。不过需要信用卡,仅用于防止滥用。或者,如果你不想提供信用卡,我可以在你注册后直接从我的管理面板为你启动一个试用,以便你测试我的系统能力,只需在这里留言,因为我今天会关注这个帖子。我非常希望听到大家对架构、部署速度或任何其他想讨论的事情的真实看法和意见。
PS:我不是以英语为母语的人,所以写这个内容对我来说有点困难,哈哈,顺便说一下,我还有很多关于我的平台的内容想要讨论,但现在这让我精疲力竭了。哈哈,非常感谢你的阅读。