SCTP:记录一次Diameter消息卡顿延迟问题
1、背景
客户端:5个接口机
服务端:2个模拟器(模拟HSS,是一个Diameter服务端)
5个客户端的地址是:
- 10.212.27.29
- 10.212.27.55
- 10.212.24.17
- 10.212.24.101
- 10.212.24.39
2个服务端的地址是:
- 10.212.27.10
- 10.212.27.176
客户端通过SCTP协议主动链接服务端。
服务端监听SCTP端口:5868、5869、5870、5871。
2、现象
在客户端侧发现,每秒有多条UDR/UDA等Diameter消息存在卡顿:
自UDR从客户端发出给服务端,到客户端收到服务端回复的UDA——时长有多条存在100ms+。
在客户端、服务端两侧抓包,发现确实是服务端自收UDR、发UDA时间差有100ms+。
据在服务端上的SCTP抓包按Diameter消息的Session-ID过滤,可见确实慢。
3、原因
起初,猜测以为是服务端中处理UDR/UDA业务慢或者服务端Diameter模块有问题。
但是,在服务端Diameter模块中各处添加时间戳计算间隔,尤其是:
- 在服务端Diameter模块中收到SCTP/Diameter/UDR时刻T1;
- 在服务端Diameter模块中写入SCTP/Diameter/UDA时刻T2;
T2-T1也没有达到100ms。
可见,并不是服务端Diameter模块有时延,或是服务端UDR/UDA处理流程时延。
当然,也有可能是服务端Diameter模块读的慢。。。
最终,通过netstat发现:
1)服务端
netstat -anp | grep sctp | grep 58
可见,服务端给客户端的SCTP链路中,有大量的SCTP消息堆积。
理论上,我的一条UDR/UDA大概300-800B,也即一条SCTP链路总堆积有10-5条Diameter消息。
是因为客户端Diameter模块收读SCTP慢了吗?
2)客户端
netstat -anp | grep sctp | grep -E “10.212.27.10|10.212.27.176”
从客户端侧看,发现客户端Diameter模块与服务端Diameter模块的SCTP的读缓冲区都是空,没有堆积,并非是客户端Diameter模块收读的慢。
分析:
- 客户端侧看,SCTP接收缓冲区无堆积;
- 服务端侧看,SCTP发送缓冲区有堆积;
服务端是27.10、27.176,是27网段;
客户端是27.29、27.55、24.17、24.101、24.39,有27网段,也有24网段;
再仔细观察下服务端中netstat截图:
可以发现:
服务端(27网段)在与客户端(27网段)地址通信,发送缓冲区堆积是0;
服务端(27网段)在与客户端(24网段)地址通信,发送缓冲区堆积总是非0;
咨询实验室负责网络的同事,其表示:
实验室跨网段确实有较严重的丢包等网络问题。
至此,问题已经较为明朗:
因为客户端与服务端处于不同网段,网络问题导致SCTP链路有堆积。
因为SCTP链路有内核读写缓冲区,导致SCTP链路的消息延迟,无法被应用程序(服务端)感知:
应用程序调用底层socket系统write SCTP数据立刻返回。
应用程序能看到的是,write SCTP data to SCTP conn,是很快的,立刻返回,没有时延。
在将客户端与服务端同网段调整后,问题解决,不再有堆积,时延也消失。