4.9.6 服务端与中间件网络优化实践

面向服务端与中间件的网络优化实践应从连接模型、传输协议、队列与缓存、超时与重试、负载均衡与高可用等维度系统梳理,并以真实业务流量为基准进行参数验证。优先明确业务特征(长连接/短连接、突发/均匀、读多写多、同步/异步)与链路拓扑(客户端—LB—应用—中间件—存储),避免单点优化引发级联问题。

原理草图:典型链路与关注点

文章图片

通用优化原则(含命令示例)
- 连接数与FD:评估峰值并预留裕度,合理设置进程FD上限、连接池大小与backlog,避免accept队列溢出。

# 查看当前FD与限制
ulimit -n
cat /proc/sys/fs/file-max

# 临时提升当前shell FD
ulimit -n 200000

# 内核/系统级(永久)配置
cat >/etc/sysctl.d/99-net-tuning.conf <<'EOF'
fs.file-max = 500000
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 100000
EOF
sysctl -p /etc/sysctl.d/99-net-tuning.conf

# 解释
# somaxconn: listen队列上限,避免大量并发时accept队列溢出
# netdev_max_backlog: 内核接收队列长度,防丢包
  • 超时与重试:客户端与服务端超时要分层(连接、读、写、空闲),重试需带退避与幂等保护。
# 用curl模拟连接与读超时
curl -m 2 --connect-timeout 1 http://127.0.0.1:8080/health

# 解释
# --connect-timeout: 连接阶段超时
# -m/--max-time: 总超时
  • 监控与抓包:以RTT、重传率、队列长度、RST/FIN比例、应用P99延迟为核心指标。
# RTT与丢包
ping -c 20 -i 0.2 10.0.0.10

# 连接与队列
ss -s
ss -lntp | head

# 抓包看重传与RST
tcpdump -i eth0 'tcp and (tcp[tcpflags] & (tcp-rst) != 0)' -nn

Nginx/Web服务(示例、安装、排错、练习)#

原理要点:事件驱动+连接复用。参数关注worker_*keepalivesendfileproxy_*

安装示例(RHEL系)

yum install -y nginx
systemctl enable --now nginx
nginx -V

配置示例(/etc/nginx/nginx.conf)

worker_processes auto;
events {
    worker_connections  65535;
    use epoll;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 30s;
    keepalive_requests 1000;

    server {
        listen 80 reuseport;
        location / {
            proxy_pass http://127.0.0.1:8080;
            proxy_connect_timeout 1s;
            proxy_read_timeout 5s;
            proxy_send_timeout 5s;
            client_max_body_size 10m;
        }
    }
}

验证命令

nginx -t
systemctl reload nginx
ss -lntp | grep nginx

排错清单
- 502/504:检查proxy_read_timeout与后端响应时间
- 大量TIME_WAIT:增大keepalive_timeout或启用连接复用
- 连接拒绝:确认worker_connectionsulimit -n

练习
- 将keepalive_timeout从30s改为5s,观察TIME_WAIT数量变化:

ss -ant state time-wait | wc -l

MySQL(示例、安装、排错、练习)#

原理要点:连接池控制+线程与网络超时协调。

安装示例(RHEL系)

yum install -y mysql-server
systemctl enable --now mysqld
mysql -uroot -e "select version();"

配置示例(/etc/my.cnf)

[mysqld]
max_connections=2000
net_read_timeout=10
net_write_timeout=10
max_allowed_packet=64M

验证命令

mysql -uroot -e "show variables like 'max_connections';"
mysql -uroot -e "show status like 'Threads_connected';"

排错清单
- Too many connections:调整连接池上限与max_connections
- 大包超时:增大max_allowed_packetnet_read_timeout
- 复制延迟:查看Seconds_Behind_Master与链路重传

练习

# 模拟多连接
for i in {1..200};do mysql -uroot -e "select 1" & done

Redis(示例、安装、排错、练习)#

原理要点:单线程高并发依赖网络与连接队列。

安装示例

yum install -y redis
systemctl enable --now redis
redis-cli ping

配置示例(/etc/redis.conf)

tcp-backlog 65535
timeout 0
repl-timeout 60
repl-backlog-size 128mb

验证命令

redis-cli info stats | egrep 'rejected_connections|total_connections_received'

排错清单
- 连接拒绝:检查tcp-backlogsomaxconn
- 延迟飙升:检查慢命令slowlog与pipeline是否开启

练习

# Pipeline压力测试
redis-cli --pipe <<'EOF'
SET k1 v1
SET k2 v2
GET k1
EOF

Kafka(示例、安装、排错、练习)#

原理要点:网络线程+IO线程分离,批量与压缩提升吞吐。

安装示例(使用二进制)

tar -xf kafka_2.13-3.6.0.tgz -C /opt
/opt/kafka_2.13-3.6.0/bin/kafka-storage.sh random-uuid

配置示例(/opt/kafka_2.13-3.6.0/config/server.properties)

num.network.threads=8
num.io.threads=16
socket.request.max.bytes=104857600

验证命令

# 生产与消费
/opt/kafka_2.13-3.6.0/bin/kafka-topics.sh --create \
  --bootstrap-server 127.0.0.1:9092 --topic t1 --partitions 3 --replication-factor 1

排错清单
- RequestQueueTime高:增加num.network.threads
- 网络延迟高:开启压缩compression.type=zstd

练习

/opt/kafka_2.13-3.6.0/bin/kafka-producer-perf-test.sh \
  --topic t1 --num-records 100000 --record-size 1000 --throughput 5000 \
  --producer-props bootstrap.servers=127.0.0.1:9092 linger.ms=5 batch.size=65536

ZooKeeper / Nacos(示例、安装、排错、练习)#

原理要点:长连接心跳,超时参数决定会话稳定性。

ZK安装示例

tar -xf apache-zookeeper-3.8.4-bin.tar.gz -C /opt
cp /opt/apache-zookeeper-3.8.4-bin/conf/zoo_sample.cfg /opt/apache-zookeeper-3.8.4-bin/conf/zoo.cfg
/opt/apache-zookeeper-3.8.4-bin/bin/zkServer.sh start

ZK配置示例(zoo.cfg)

tickTime=2000
initLimit=10
syncLimit=5
maxClientCnxns=200

验证命令

/opt/apache-zookeeper-3.8.4-bin/bin/zkCli.sh -server 127.0.0.1:2181 ls /

排错清单
- 会话频繁断开:增大sessionTimeouttickTime
- 客户端过多:提高maxClientCnxns并用连接池

练习
- 用脚本循环创建会话,观察连接数变化:

for i in {1..50};do echo "ls /" | /opt/apache-zookeeper-3.8.4-bin/bin/zkCli.sh -server 127.0.0.1:2181 >/dev/null;done

HAProxy / Keepalived(示例、安装、排错、练习)#

原理要点:L4/L7负载、队列与健康检查;VRRP心跳切换。

HAProxy安装与配置

yum install -y haproxy
cat >/etc/haproxy/haproxy.cfg <<'EOF'
global
  maxconn 20000
defaults
  mode http
  timeout connect 2s
  timeout client 10s
  timeout server 10s
frontend fe_http
  bind *:80
  default_backend be_app
backend be_app
  balance roundrobin
  server s1 127.0.0.1:8080 check
  server s2 127.0.0.1:8081 check
EOF
systemctl enable --now haproxy

Keepalived示例(/etc/keepalived/keepalived.conf)

vrrp_instance VI_1 {
  state MASTER
  interface eth0
  virtual_router_id 51
  priority 150
  advert_int 1
  virtual_ipaddress {
    10.0.0.100/24
  }
}

排错清单
- 后端排队:观察qcur/qtime并增大maxconn
- 频繁切换:增大advert_int或禁用抢占

练习

echo "show stat" | socat stdio /run/haproxy/admin.sock | head

ProxySQL(示例、安装、排错、练习)#

原理要点:连接复用+读写分离,减少后端连接压力。

安装示例

yum install -y proxysql
systemctl enable --now proxysql

配置示例(SQL管理口)

-- 连接管理端口
mysql -u admin -padmin -h 127.0.0.1 -P 6032

-- 设置后端连接与线程
UPDATE global_variables SET variable_value='4' WHERE variable_name='mysql-threads';
UPDATE global_variables SET variable_value='2000' WHERE variable_name='mysql-max_connections';
LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK;

排错清单
- 连接耗尽:增加mysql-max_connections与后端连接池
- 跨机房高RTT:调整路由规则避免跨地域读

练习
- 写入一条路由规则并验证:

INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup) VALUES (1,1,'^SELECT',20);
LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;

Docker / Kubernetes(示例、安装、排错、练习)#

原理要点:CNI选择、NAT/conntrack表、跨节点通信减少转发层级。

安装示例(Docker)

yum install -y docker
systemctl enable --now docker
docker info | egrep 'Server Version|Cgroup'

conntrack调整示例

sysctl -w net.netfilter.nf_conntrack_max=262144
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=600

K8s排错命令

# 查看Pod网络丢包/延迟(需安装工具)
kubectl exec -it pod-name -- sh -c "ping -c 10 10.244.0.1"

# 查看conntrack占用
conntrack -C

练习
- 部署两个Pod并测试跨节点RTT,记录RTT差异并分析CNI模式。


Prometheus / Jenkins(示例、安装、排错、练习)#

Prometheus安装与配置

tar -xf prometheus-2.48.0.linux-amd64.tar.gz -C /opt
cat >/opt/prometheus-2.48.0.linux-amd64/prometheus.yml <<'EOF'
global:
  scrape_interval: 15s
  scrape_timeout: 5s
scrape_configs:
  - job_name: 'node'
    static_configs:
    - targets: ['127.0.0.1:9100']
EOF

Jenkins网络参数示例

# 启动时设置HTTP端口与代理超时(示例)
java -jar jenkins.war --httpPort=8080 --handlerCountMax=100

排错清单
- Prometheus抓取超时:调整scrape_timeout与并发
- Jenkins构建失败:检查制品仓库连接与DNS解析

练习
- 将scrape_interval改为5s,观察CPU与网络影响。


问题定位要点(含示例)

# 高延迟伴随重传
ss -ti dst 10.0.0.10:3306 | egrep 'retrans|rtt'

# 连接拒绝或队列满
ss -lntp | egrep 'Recv-Q|Send-Q'

综合排错流程
1. 先确认链路与MTU:ping -M do -s 1472 <IP>
2. 看队列与重传:ss -stcpdump
3. 对比应用P99延迟与系统级指标
4. 小步修改参数并回归压测


综合练习(最小化验证)
- 目标:Nginx反代到应用端口,模拟200并发访问,观察TIME_WAIT。

# 压测
ab -n 10000 -c 200 http://127.0.0.1/

# 观察TIME_WAIT
ss -ant state time-wait | wc -l
  • 记录调整前后keepalive_timeout对TIME_WAIT的影响,并输出结论。