GaussDB重要通信参数汇总
1 问题背景
在GaussDB通信运维中,很多情况是由于一些参数配置的不合理导致集群效率低、资源过载、连接异常等问题。对于通信库和操作系统两方面都提供了大量可供用户自定义的参数,熟练掌握一些重要的参数有助于快速定位现网通信故障问题。本文将关联参数分组讲述,便于大家更好的理解,若有差错、遗漏,欢迎纠正、补充。详细说明可见产品文档。
2 通信库参数
2.1 tcp_keepalives_idle、tcp_keepalives_interval、tcp_keepalives_count
TCP是无感知的虚拟连接,中间断开两端不会立刻得到通知。一般在使用长连接的环境下,需要心跳保活机制感知其是否存活,从而减少无效连接,释放资源。在操作系统级,提供了三个参数,可使用:sysctl –a | grep keepalive 查询。
net.ipv4. tcp_keepalive_time = 7200 (默认7200)
net.ipv4.tcp_keepalive_intvl = 75 (默认75)
net.ipv4.tcp_keepalive_probes = 9 (默认9)
其表示如果一个连接上7200s后没有任何数据发送,则设置了keepalive的一端会向对端发送keepalive保活报文,会有三种结果:
- 对端回复ACK。则本端TCP认为该连接依然存活,继续等待7200s后再发送keepalive报文;
- 对端回复RESET。说明对端进程已经重启,本端应用程序应该关闭该连接;
- 没有对端的任何回复。则本端重试,当重试9次后,每次重试间隔75s,仍然不可达,则向应用程序返回错误信息ETIMEOUT。
GaussDB中提供的这三个参数可以根据环境自定义,默认值均为0,期值望为:
tcp_keepalives_idle = 30
tcp_keepalives_interval = 30
tcp_keepalives_count = 9
2.2 comm_max_datanode、comm_max_stream、comm_max_receiver
comm_max_datanode表示TCP代理通信库支持的最大DN数,最小值为1,最大值为8192。当DN数小于256时,默认值为256;否则,为大于等于DN数的2的N次方。在集群扩容、缩容场景下,要注意此参数的变更。
comm_max_stream表示TCP代理通信库支持的最大并发stream数量,默认值为1024,最大为60000,此参数要保证大于并发数*每并发平均stream算子数*(smp的平方),否则会报错Cannot get stream index, maybe comm_max_stream is not enough。此外,在设置此参数时需要考虑占用内存问题,其大小为256byte*comm_max_stream*comm_max_datanode,可见在内存、comm_max_datanode和comm_max_stream三者之间需要一个动态的规划。
针对comm_max_stream不足问题,可以考虑三种解决方案:
- 新版本直接使用pgxc_comm_status视图查看DN的stream使用情况:select node_name, stream from pgxc_comm_status order by 2 desc;
- 在CN上查询当前任意两个DN之间的stream情况:select node_name, remote_name, count(*) as stream from pgxc_comm_send_stream group by 1, 2 order by 3 desc limit 30;
- 若当前业务恢复, 可使用脚本对stream进行监控;
然而,还有情况是个别的SQL语句严重消耗stream,此时可以使用实时topsql或历史topsql找到对应的语句,修改以解决问题。
comm_max_receiver表示TCP代理通信库接收端接收线程的数量,最大值为50,默认值为4。在大集群、大并发场景下,适当的调大该参数有利于提升查询的性能;但如果通信层可用内存不足,线程间有竞争会对接收性能有负面影响。
注:SMP是指对称多处理技术,数据库领域的SMP并行技术一般指利用多线程技术实现查询的并行执行,以充分利用CPU资源,从而提升查询性能。SMP特性通过算子并行来提升性能,同时会占用更多的系统资源,在使用时,需要根据使用场景与限制进行合理的配置。在GaussDB中,SMP功能由query_dop参数决定,默认值为1。
2.3 enable_stateless_pooler_reuse、comm_cn_dn_logic_conn
在pooler连接池通信模型中,客户端通过gsql新建会话后,postmaster线程会fork一个postgres线程用于数据的交互,其与相应的agent线程连接。若开启了pooler复用,即参数enable_stateless_pooler_reuse,可在pooler中根据database查找空闲的pool,直接获取连接使用即可;若未开启,则需要匹配user_name、database和pgoptions。在现网问题中,若出现连接数达到max_connections时,可以考虑清理空闲连接或开启pooler复用。
对于256节点的集群来说,并发场景导致CN和DN之间存在大量连接,每个连接占用一个端口,则CN的端口号很容易受限。为解决此问题,设计了CN多流,即CN与DN之间采用逻辑连接。comm_cn_dn_logic_conn参数默认值是off,在集群规模或并发达到一定程度时,需要将其开启为on,避免CN与DN之间由于端口号受限而无法建连。
值得注意的是,这两个参数都需要在CN和DN上同步设置,否则会导致集群不能正常通信。
2.4 comm_quota_size、comm_usable_memory
TCP代理通信库采用pull模式进行流量控制,避免消息堵塞。两个DN分别有一个buffer,当一条通道发送端数据量过大时,很容易造成buffer填满,阻塞了其他通道的发送。此时,对于每条通道设置一个quota,接收端根据buffer剩余空间的大小发送给发送端一个合理quota值,发送端根据quota大小发送数据。
comm_quota_size表示每个通道单次不间断发送数据量配额,默认值1MB。当通道发送数据量达到配额时,发送端等待接收端重新发送配额,进而继续发送数据,从而实现流控功能。其取值为0时,表示不使用quota,在一些大流量等场景中,查询之间可能会有影响。在1GE网卡环境中,受网卡能力限制,应该调小该参数,推荐20KB~40KB。如果环境内存充足,参数comm_usable_memory设置较大,可以适当调大,从而提升性能。
comm_usable_memory表示的是TCP代理通信库可使用的最大内存大小,默认值4000MB。此参数需要根据环境内存及部署方式具体配置,保证了系统不会因为通信层接收缓存造成进程内存膨胀。在单台机器上,通信占用内存最坏情况=部署节点个数* comm_usable_memory。考虑环境内存情况,此参数配置过小,会影响通信性能,过大则可能造成系统内存不足等问题。与comm_quota_size结合,进行合理的配置至关重要。
3 操作系统参数
TCP协议中包含了11种不同的状态,TCP连接会根据发送或者接收到的消息转换状态,若服务器中存在大量的异常状态,则会严重占用系统资源。操作系统提供了很多内核参数帮助用户进行合理管控。
3.1 net.ipv4.tcp_tw_reuse、net.ipv4.tcp_tw_recycle、net.ipv4.tcp_max_tw_buckets
客户端主动断开连接,收到对端的确认后,状态变为TIME_WAIT。TCP协议规定TIME_WAIT状态会一直保持2MSL(最长报文段生存期,60秒),确保旧的连接状态不会对新连接有影响。处于TIME_WAIT状态的连接占用资源不会被内核释放,所以作为服务器,在可能的情况下,尽量不要主动断开连接,以减少TIME_WAIT状态造成的资源浪费。
GaussDB设立了pooler缓存池,将空闲的TCP连接保留,方便客户端下次快速建连。然而对于高并发的情况,在断连时,pooler达到缓存上限直接释放,CN主动断开连接,此时会产生大量TIME_WAIT状态(释放的并发数*DN数)。此外,clean connection、DN之间的断连等情况均会导致此问题。
net.ipv4.tcp_tw_reuse表示开启重用,允许将TIME_WAIT状态的sockets重新用于新的TCP连接,默认为0,GaussDB基线为1。开启后,主动断连一方可在1s内回收。
net.ipv4.tcp_tw_recycle表示开启TCP连接中TIME_WAIT状态下的sockets快速回收,默认为0,GaussDB基线为1。由于数据库处于内网环境,开启后在3.5*RTO(Retransmission Time Out,重传超时时间)时间内回收,比tw_reuse稍快。
这两个参数均依赖net.ipv4.tcp_timestamps开启情况,操作系统默认开启,但实际仍需核查,否则reuse和recycle均会失效。此外还需保证各服务器的timestamp一致,否则连基本的TCP建连可能都无法成功。
此外,tcp_max_tw_buckets表示系统允许并发的TIME_WAIT的最大数量,默认180000,GaussDB基线为10000。当实际数量超过此值时,系统会将过多的清除掉,并打印日志time wait bucket table overflow。
3.2 net.ipv4.tcp_syn_retries、net.ipv4.tcp_synack_retries
TCP建连时需要进行三次握手操作,对于每一次握手避免因环境问题导致丢包,都设置了重传机制。
客户端向服务器端发送SYN请求建连后进入SYN_SENT状态,此时等待服务器端回复SYN+ACK,若超时未收到,则重传SYN,达到net.ipv4.tcp_syn_retries后放弃建连。由于第n次等待的时间=2的n-1次幂,总的超时等待时间=2的net.ipv4.tcp_syn_retries次幂-1,因此参数过大会造成长时间等待,而过小可能因环境偶发问题导致建连失败,GaussDB基线为5。
服务端收到客户端发来的SYN,回复SYN+ACK后,进入SYN_RCVD状态,此时还需等待客户端回复ACK,若超时未收到,则重传SYN+ACK,达到net.ipv4.tcp_synack_retries后放弃,建连失败。同理,此参数也决定着总的超时等待时间,GaussDB基线为5。
3.3 net.ipv4.tcp_retries1、net.ipv4.tcp_retries2
net.ipv4.tcp_retries1目前的解释有两种,第一种为放弃回应一个TCP连接请求前,需要进行多少次重试(描述的很模糊,暂时还未想到场景)。另一种表示当重传次数达到此值,TCP向IP层发送指令进行MTU探测、刷新路由等过程,避免由于网络链路发生变化而导致TCP传输失败。
net.ipv4.tcp_retries2表示的是TCP尝试重传数据的最大次数,实际中可能未达到此值便放弃了重传并关闭连接。在设置此值后,操作系统内核会计算出一个timeout,其中对于ESTABLISHED状态下的rto_base为200ms,TCP_RTO_MAX为120000ms。若第一次超时重传时间为1.5s,后每一次重传时间间隔为上次间隔的2倍,当总的超时时间大于timeout时,则立即放弃重传,连接断开。例如,设置tcp_retries2等于8,则计算出timeout等于102.2s。重传第1次时间间隔为1.5s,下一次为3s,再下一次为6s,以此类推。当到第7次时为96s,与前6次之和为190.5s,大于102.2s,则第7次重传放弃,连接断开。GaussDB基线为12,计算得timeout等于564.6s,9.41min。
1. if (tcp_retries2 <= 9)
2. timeout = ((2 << tcp_retries2) - 1) * rto_base;
3. else
4. timeout = ((2 << 9) - 1) * rto_base +
5. (tcp_retries2 - 9) * TCP_RTO_MAX;
3.4 net.core.rmem_default、net.core.rmem_max、net.ipv4.tcp_rmem
net.core.rmem_default表示TCP数据接收窗口默认大小
net.ipv4.tcp_rmem表示为自动调优定义socket使用的接收内存,有三个值,第一个表示socket接收缓冲区分配的最少字节数
4 定位手段
ping、netstat、ifconfig、sar等命令以及gsar.sh工具可快速帮助我们检测网络环境是否正常,若排除环境问题后,可优先考虑资源利用和参数配置问题。常用的命令有:
网络设备状态信息:sar –n DEV t n,t表示采样时间间隔,n表示采样次数;
tcp重传:netstat -anop|grep “on(”|sort -rnk 3|head 50
网络监控工具: gsar.sh
此外,很多参数配置问题报错很明显,这也是最容易进行定位的。例如2.2中提到的“Cannot get stream index, maybe comm_max_stream is not enough”。然而,问题的根因可能不在于此,贸然的修改参数会有效果,但这也可能仅仅是短暂的。此时,可以根据日志进行细致的分析,常用的视图有:
- stream
相关视图:pgxc_comm_status、pgxc_comm_send_stream
相关参数:comm_max_stream
- connection
相关视图:pgxc_stat_activity
相关参数:max_connectios、enable_stateless_pooler_reuse、comm_cn_dn_logic_conn
- memory
相关视图:pv_total_memory_detail
相关参数:comm_quota_size、comm_usable_memory
针对不同的资源利用情况,找到出现问题sql语句或者进行相应的合理的调参是解决问题的根本办法。
5 常见案例
5.1 tcp_keepalives_idle、tcp_keepalives_interval、tcp_keepalives_count
问题来源:
问题描述:集群执行查询操作,报流异常错误:ERROR: dn_6019_6110: failed to read response from Datanodes. Detail: 1039 Abnormal stream state
定位过程:
- 分析异常日志信息,可知出现异常是因为节点间的stream连接(逻辑连接)被关闭;
- 通过查找被关闭连接的对端node[4]的日志,发现逻辑连接被关闭的原因是socket(物理连接)被关闭了;
- 查看报错日志信息,“Poller receive error: event[25]”中的“event[25]”是操作系统的报错,表示连接已经断开或者hang住,操作系统默认会对socket检测有效性;
- 继续观察发现存在明显的丢包。操作系统的keepalive在发送3次socket是否有效检测时产生丢包,导致系统误认为socket异常,关闭了socket。
解决详情:将参数修改为期望值后,提升了操作系统检测socket是否断开的次数和检测间隔,问题解决。
5.2 comm_max_datanode
问题来源:http://rnd-dayu.huawei.com:8081/index.php/Question/detail?id=53752
问题描述:扩容初始化实例和服务报错,Gauss-52631: Invalid value for GUC parameter comm_max_datanode: 512
产品版本:GaussDB 200 8.0.0.1
解决详情:扩容后实际DN数量大于comm_max_datanode的值,手动修改CN和DN上的参数,gs_guc reload –Z coordinator –Z datanode –N all –I all –c “comm_max_datanode=1024”。
5.3 comm_max_stream
问题来源:http://rnd-dayu.huawei.com:8081/index.php/Question/detail?id=53607
问题描述:业务报错Cannot get stream index, maybe comm_max_stream is not enough
产品版本:GaussDB Elk 7.1.0.SP5
解决详情:现场comm_max_stream参数默认值为1024,在正常跑批时查询select node_name, remote_name, count(*) from pgxc_comm_send_stream group by 1, 2 order by 3 desc limit 100;得到DN间stream数量大约有600~700,当跑批时如果有临时查询,就会超过上限,导致报错。将此参数调整到2048,问题解决。
5.4 enable_stateless_pooler_reuse
问题来源:http://rnd-dayu.huawei.com:8081/index.php/Question/detail?id=38882
问题描述:XX测试集群报错:remaining connection slots are reserved for non-replication system admin connections
产品版本:GaussDB 200 LibrA V100R002C80SPC312
解决详情:该报错原因是由于DN连接达到max_connections=1000最大上限,再次获取给系统内部预留的连接时报错。通过对比guc参数,确认是由于该集群中enable_stateless_pooler_reuse参数为off,pooler连接无法复用导致,修改参数为on后解决。
6 总结
本文讲述了通信库中几个重要的参数,在现网各种各样的场景下,这些参数相互影响制约,其合理配置尤为重要。此外,熟悉这些参数可能引发的一些问题,也为快速定位定位通信问题提供了一种手段。在日后的版本开发中,期望系统可以对这些参数提供动态配置,这样可以减少很多不合理配置导致的问题,同时也能更加高效、合理的利用资源,从而提升数据库的效率。
- 点赞
- 收藏
- 关注作者
评论(0)