个人技术学习记录

日常后端开发、Linux 系统网络与数据库底层原理个人学习笔记整理

Linux TCP 全连接队列与拥塞控制参数学习笔记

分类:Linux 网络栈 · 学习整理

在排查高并发短连接场景下的偶发连接超时问题时,需要重点区分半连接队列(SYN Queue)与全连接队列(Accept Queue)的溢出表现。 内核参数 net.core.somaxconn 决定了套接字监听队列的上限,应用层调用 listen(fd, backlog) 时实际生效值为二者中的较小值。

ss -lnt
netstat -s | grep -iE "listen|overflow"
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog net.ipv4.tcp_congestion_control

当链路存在一定时延带宽积(BDP)与轻度随机丢包时,传统的 CUBIC 算法容易将随机丢包误判为拥塞窗口减半信号;切换为 fq 队列规则配合 bbr 拥塞控制后,内核通过测量最小往返时延(RTprop)与瓶颈带宽(BtlBw)主动控制发包速率,能够显著降低排队时延抖动。

Go 标准库 net/http Transport 连接池复用踩坑记录

分类:Go 语言实践 · 学习整理

Go 标准库中的 http.DefaultTransport 虽然默认开启了 Keep-Alive,但其默认的 MaxIdleConnsPerHost 仅为 2。在对同一上游地址发起并发请求时,若空闲连接槽位不足,大量连接会在请求结束后立即进入 TIME_WAIT 状态并重新触发三次握手。

transport := &http.Transport{
    MaxIdleConns:        128,
    MaxIdleConnsPerHost: 32,
    IdleConnTimeout:     90 * time.Second,
    TLSHandshakeTimeout: 5 * time.Second,
}

另一个常见疏忽是未完整读取响应体即调用关闭:只有执行 io.Copy(io.Discard, resp.Body) 并随后调用 resp.Body.Close(),底层 TCP 连接才能被正常归还至空闲连接池复用。

SQLite WAL 模式下的并发读写与死锁规避

分类:存储与数据库 · 学习整理

SQLite 开启 PRAGMA journal_mode=WAL; 后,修改不会直接覆盖主数据库页,而是顺序追加写入预写日志(Write-Ahead Log),从而允许读事务与单个写事务并发执行。但 SQLite 本质上仍是单写者模型,同一时刻只能存在一个写锁。

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA busy_timeout = 5000;

在连接池将 MaxOpenConns 限制为 1 的单机工程实践中,事务闭包内部严禁再通过全局数据库句柄发起任何嵌套查询(例如在写事务中读取系统配置表),否则新查询会永久等待当前尚未提交的连接释放,直接造成进程级自锁。所有前置配置必须在开启写事务前读取完毕。

TLS 1.3 握手往返优化与反向代理头部规范

分类:Web 协议基础 · 学习整理

相比于 TLS 1.2 需要两次完整网络往返(2-RTT)才能完成密钥协商,TLS 1.3 将支持的椭圆曲线密钥共享参数直接携带在首个 ClientHello 报文中,使完整握手缩短为 1-RTT,进一步降低了跨地域 HTTPS 请求的首字节时间(TTFB)。

在七层反向代理部署结构中,边缘网关与后端进程之间保持 HTTP/1.1 Keep-Alive 或 HTTP/2 多路复用长连接,可避免每次外部请求重复建立后端 TLS 会话;同时需严格限定可信代理网段,仅信任受控网关写入的 X-Forwarded-For 与 X-Forwarded-Proto 字段,防止客户端伪造来源地址。