|
|
@ -654,4 +654,182 @@ listen_option() = {ip, inet:socket_address()} | {fd, Fd :: integer() >= 0} | {if |
|
|
|
address_family() | {port, inet:port_number()} | {backlog, B :: integer() >= 0} | {tcp_module, module()} | {netns, file: |
|
|
|
filename_all()} | {bind_to_device, binary()} | option() |
|
|
|
socket() |
|
|
|
As returned by accept/1,2 and connect/3,4. |
|
|
|
As returned by accept/1,2 and connect/3,4. |
|
|
|
|
|
|
|
在Erlang的`gen_tcp`模块中,`low_watermark`、`high_watermark`、`high_msgq_watermark`和`low_msgq_watermark`是控制网络数据流和内存管理的核心参数。它们的协同作用直接影响吞吐量、延迟和系统稳定性。以下是详细解析: |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **1. 参数定义与作用** |
|
|
|
#### **(1) `high_watermark`与`low_watermark`** |
|
|
|
- **功能**:控制**Erlang内部Socket实现的数据队列**。 |
|
|
|
- `high_watermark`:当队列数据量达到此阈值时,Socket标记为**繁忙(busy)**,发送进程会被挂起。 |
|
|
|
- `low_watermark`:当队列数据量降低到此阈值时,Socket恢复**非繁忙状态**,允许继续发送。 |
|
|
|
- **默认值**:均为8KB(不同版本可能略有差异)。 |
|
|
|
- **适用场景**:防止底层Socket缓冲区溢出,适用于高吞吐量场景(如文件传输、广播消息)。 |
|
|
|
|
|
|
|
#### **(2) `high_msgq_watermark`与`low_msgq_watermark`** |
|
|
|
- **功能**:控制**Erlang进程消息队列**的繁忙状态。 |
|
|
|
- `high_msgq_watermark`:消息队列数据量达到此值时,队列标记为繁忙,阻止新消息进入。 |
|
|
|
- `low_msgq_watermark`:消息队列数据量低于此值时,恢复非繁忙状态。 |
|
|
|
- **默认值**:分别为8KB和4KB。 |
|
|
|
- **适用场景**:防止进程消息队列爆炸(如恶意客户端高频发送小包)。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **2. 参数间的协同关系** |
|
|
|
#### **(1) 触发条件优先级** |
|
|
|
- **Socket繁忙状态**:当Socket队列(`high_watermark`)**或**消息队列(`high_msgq_watermark`)任一达到阈值时,发送进程会被挂起。 |
|
|
|
- **恢复条件**:需**同时满足**Socket队列低于`low_watermark`且消息队列低于`low_msgq_watermark`,才会恢复发送。 |
|
|
|
|
|
|
|
#### **(2) 典型数据流路径** |
|
|
|
```plaintext |
|
|
|
发送进程 → 消息队列 → Erlang内部Socket队列 → 操作系统Socket缓冲区 → 网络 |
|
|
|
``` |
|
|
|
- **消息队列**:进程间通信的中间缓存(受`*_msgq_watermark`控制); |
|
|
|
- **Socket队列**:Erlang虚拟机的发送缓冲区(受`*_watermark`控制)。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **3. 配置建议与调优** |
|
|
|
#### **(1) 默认值适用场景** |
|
|
|
- **常规交互式服务**(如HTTP短连接):默认值(8KB/4KB)可平衡吞吐与内存占用。 |
|
|
|
- **防御性设计**:通过`high_msgq_watermark`限制单个进程的负载,避免级联崩溃。 |
|
|
|
|
|
|
|
#### **(2) 高吞吐场景优化** |
|
|
|
- **增大水位线**:例如设置`{high_watermark, 64*1024}`和`{low_watermark, 32*1024}`,提升批量数据传输能力。 |
|
|
|
- **结合`delay_send`**:启用`{delay_send, true}`合并小包,减少调度器争用。 |
|
|
|
|
|
|
|
#### **(3) 低延迟场景优化** |
|
|
|
- **降低水位线**:例如`{high_watermark, 4*1024}`,减少队列积压导致的延迟。 |
|
|
|
- **禁用合并机制**:配合`{nodelay, true}`确保小包立即发送。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **4. 监控与调试** |
|
|
|
- **工具推荐**: |
|
|
|
- `recon`:监控进程消息队列长度(`recon:proc_count(message_queue_len, 5)`); |
|
|
|
- `inet:getopts/2`:查看Socket队列状态(如`inet:getopts(Socket, [high_watermark])`)。 |
|
|
|
- **异常处理**: |
|
|
|
- 若频繁触发繁忙状态,需检查网络拥塞或协议设计问题; |
|
|
|
- 若消息队列持续满载,考虑优化消息处理逻辑或拆分进程。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **总结** |
|
|
|
- **核心目标**:通过水位线机制平衡吞吐量、延迟和内存安全; |
|
|
|
- **调优原则**:根据场景选择水位线阈值,结合`delay_send`、`nodelay`等选项协同优化; |
|
|
|
- **风险规避**:避免盲目增大水位线导致内存溢出,或过度降低引发频繁阻塞。 |
|
|
|
|
|
|
|
具体参数需通过压测工具(如`Tsung`)结合实际流量验证。 |
|
|
|
|
|
|
|
针对SLG卡牌和MMO游戏的后端项目,`low_watermark`、`high_watermark`、`high_msgq_watermark`和`low_msgq_watermark`的设置需结合游戏特性和网络负载需求。以下是具体建议及优化逻辑: |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **一、SLG卡牌类游戏** |
|
|
|
#### **1. 核心需求** |
|
|
|
- **低频交互**:回合制战斗、抽卡、养成等操作,数据包间隔较长(0.5~2秒/次); |
|
|
|
- **突发流量**:活动开启时(如限时抽卡)可能产生瞬时高并发; |
|
|
|
- **数据一致性**:需保证抽卡结果、装备强化等操作的原子性。 |
|
|
|
|
|
|
|
#### **2. 推荐配置** |
|
|
|
```erlang |
|
|
|
% gen_tcp 监听配置 |
|
|
|
gen_tcp:listen(Port, [ |
|
|
|
{high_watermark, 32 * 1024}, % 32KB |
|
|
|
{low_watermark, 16 * 1024}, % 16KB |
|
|
|
{high_msgq_watermark, 64 * 1024}, % 64KB |
|
|
|
{low_msgq_watermark, 32 * 1024} % 32KB |
|
|
|
]). |
|
|
|
``` |
|
|
|
|
|
|
|
#### **3. 配置解析** |
|
|
|
- **Socket队列(high/low_watermark)** |
|
|
|
- 设置中等缓冲区(32KB/16KB):应对活动期的瞬时流量,避免频繁阻塞; |
|
|
|
- 抽卡接口的协议包通常较小(1~4KB),32KB可缓存约8~32个请求。 |
|
|
|
|
|
|
|
- **消息队列(high/low_msgq_watermark)** |
|
|
|
- 较大阈值(64KB/32KB):防止活动期间消息队列溢出(如万人同时十连抽); |
|
|
|
- 配合`{active, 100}`模式,允许短时堆积后自动恢复。 |
|
|
|
|
|
|
|
#### **4. 调优建议** |
|
|
|
- **监控重点**: |
|
|
|
- 使用`recon:proc_count(message_queue_len, 10)`检查消息队列堆积; |
|
|
|
- 若活动期间`high_watermark`频繁触发,可提升至64KB。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **二、MMO类游戏** |
|
|
|
#### **1. 核心需求** |
|
|
|
- **高频实时交互**:玩家移动、技能释放需50~200ms内同步; |
|
|
|
- **高吞吐量**:万人同屏时每秒处理10万+数据包; |
|
|
|
- **低延迟优先**:避免队列堆积增加额外延迟。 |
|
|
|
|
|
|
|
#### **2. 推荐配置** |
|
|
|
```erlang |
|
|
|
% gen_tcp 监听配置 |
|
|
|
gen_tcp:listen(Port, [ |
|
|
|
{high_watermark, 64 * 1024}, % 64KB |
|
|
|
{low_watermark, 8 * 1024}, % 8KB |
|
|
|
{high_msgq_watermark, 128 * 1024}, % 128KB |
|
|
|
{low_msgq_watermark, 64 * 1024} % 64KB |
|
|
|
]). |
|
|
|
``` |
|
|
|
|
|
|
|
#### **3. 配置解析** |
|
|
|
- **Socket队列(high/low_watermark)** |
|
|
|
- 大缓冲区(64KB)应对广播风暴(如国战技能特效); |
|
|
|
- 低恢复阈值(8KB):快速解除阻塞,确保实时性。 |
|
|
|
|
|
|
|
- **消息队列(high/low_msgq_watermark)** |
|
|
|
- 超大阈值(128KB/64KB):容忍突发流量(如玩家瞬移引发的周围实体状态同步); |
|
|
|
- 需配合`{active, once}`模式防御DDoS攻击。 |
|
|
|
|
|
|
|
#### **4. 调优建议** |
|
|
|
- **动态调整**: |
|
|
|
- 战斗密集期临时提升`high_watermark`至128KB; |
|
|
|
- 使用`inet:setopts(Socket, [{high_watermark, NewVal}])`动态修改。 |
|
|
|
- **硬件协同**: |
|
|
|
- 10Gbps网卡需设置`{recbuf, 256KB}`和`{sndbuf, 256KB}`,匹配内核参数。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **三、通用优化策略** |
|
|
|
#### **1. 防御性设计** |
|
|
|
- **消息队列监控**: |
|
|
|
```erlang |
|
|
|
%% 检查进程消息队列并告警 |
|
|
|
check_msgq(Pid) -> |
|
|
|
case process_info(Pid, message_queue_len) of |
|
|
|
{message_queue_len, Len} when Len > 1000 -> |
|
|
|
alert_system_operator(Pid, Len); |
|
|
|
_ -> ok |
|
|
|
end. |
|
|
|
``` |
|
|
|
- **自动熔断**:若队列持续超过`high_msgq_watermark`的80%,触发限流。 |
|
|
|
|
|
|
|
#### **2. 压测验证** |
|
|
|
- **工具选择**: |
|
|
|
- SLG:用Locust模拟抽卡、装备强化峰值; |
|
|
|
- MMO:用Tsung模拟万人移动同步。 |
|
|
|
- **关键指标**: |
|
|
|
- Socket队列平均深度(`inet:getopts/2`); |
|
|
|
- 消息队列峰值长度(`recon`)。 |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **四、参数设置总结** |
|
|
|
| 游戏类型 | high_watermark | low_watermark | high_msgq_watermark | low_msgq_watermark | 核心逻辑 | |
|
|
|
|------------|----------------|---------------|----------------------|---------------------|---------------------------------| |
|
|
|
| **SLG卡牌**| 32KB | 16KB | 64KB | 32KB | 平衡突发流量与内存占用,避免活动期卡顿 | |
|
|
|
| **MMO** | 64KB | 8KB | 128KB | 64KB | 容忍广播风暴,同时保障实时性 | |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### **五、注意事项** |
|
|
|
1. **不要盲目增大水位线**:过高的`high_watermark`可能导致内存溢出(尤其在32位系统); |
|
|
|
2. **结合`delay_send`使用**:MMO可启用`{delay_send, true}`提升吞吐,但需测试延迟影响; |
|
|
|
3. **版本差异**:Erlang/OTP 25+优化了水位线算法,相同配置下性能可能提升20%~30%。 |
|
|
|
|
|
|
|
实际配置需通过**灰度发布**逐步验证,观察CPU、内存及网络指标变化。 |