[转帖]防火墙、DCD与TCP Keep alive
https://www.laoxiong.net/tag/network
在以前我写的一篇文章《Oracle与防火墙》中提到,网络防火墙会切断长时间空闲的TCP连接,这个空闲时间具体多长可以在防火墙内部进行设置。防火墙切断连接之后,会有下面的可能:
- 切断连接之前,连接对应的Oracle会话正在执行一个耗时特别长的SQL,比如存储过程而在此过程中没有任何数据输出到客户端,这样当SQL执行完成之后,向客户端返回结果时,如果TCP连接已经被防火墙中断,这时候显然会出现错误,连接中断,那么会话也就会中断。但是客户端还不知道,会一直处于等待服务器返回结果的状态。
- 切断连接之前,Oracle会话一直处于空闲状态,在防火墙中断之后,客户端向Oracle服务器提交SQL时,由于TCP连接已经中断,这时客户端侦测到连接中断,那么客户端就会报ORA-3113/ORA-3114这类错误,然后会话中断。但是在Oracle服务器端,会话一直在处于等待客户端消息的状态。
- 当然,如果服务器和客户端都一直闲着,没有任何消息往来,那么客户端和客户端的会话就一直存在,直到客户端发送消息即提交SQL到Oracle服务器。
从上面的前面2种情况来看,防火墙切断数据库TCP连接,引起的后果就会有:
- 客户端报ORA-3113/3114错误,对这于长连接的后台应用不是个好事,特别是对那种C/C++开发的后台应用没有重连机制,就会出现问题或者程序退出。如果应用在一个较长的时间内没有任何活动,而这个时间超过了防火墙的设置,那应用的连接被中断。
- 对于有连接池或重连机制的应用,如果连接池过大,导致空闲连接过多,或者是防火墙的连接断开时间过短同时应用太闲,那么连接频繁地被中断,而在数据库服务器端,则连接越来越多,即会话数越来越多,甚至最终超过了数据为最大连接数。
- 其他一些影响,比如你在跑一个脚本而长时间没有输出,结果防火墙切断了连接,你之前的工作就白做,当然这些影响范围都较小。
那么如何防止出现以上的问题? 对于没有重连机制的长连接应用,临时的解决办法是调大防火墙的连接切断时长;或者应用端在闲时定期执行一条类似于select 1 from dual这样的SQL;或者在Oracle服务端开启DCD功能,而DCD(死连接检测,即Dead Connection Detection)的时间长度短于防火墙的连接切断时长;或者使用操作系统的tcp keep-alive功能。对于有重连机制或有连接池的应用,为了避免数据库端连接数满,可以使用DCD或tcp keep-alive功能,如果DCD或TCP keep-alive的时间短于防火墙连接切断时长,那么连接将不会中断,因为防火墙视连接为活动状态(不过按MOS文档的说法,DCD的包有可能被防火墙忽略,即用DCD使连接保持活动状态可能没有作用)。而如果DCD或TCP keep-alive的时间长于防火墙连接切断时长,那么连接被中断的会话和进程将得到清理。
这里简单介绍一下TCP keep-alive,顾名思议,就是让TCP连接保持存活状态,这是由TCP协议层实现的功能,也是在TCP连接空闲时间超过设置的时间,就会发送探测包,因此,这个功能跟Oracle的DCD是极为类似的,所不同的是,这是由协议层实现的功能,是不能通过trace应用进程来跟踪包的发送。
理论是完美的,而现实差距越很远。
下面是一个有关的案例。一套运行在AIX 5.3上的RAC数据库,数据库版本为10.2.0.4,这套数据库在sqlnet.ora文件中有设置sqlnet.expire_time=5,后果却是,数据库的连接数过几天就要满一次,防火墙设置的时间是8小时,也就是说只会切断空闲时间超过8小时的连接,这个时间已经足够长,晚上系统太闲,总会有部分连接空闲时间过长,但是由于设置了DCD,连接应该不会被防火墙切断,而即使防火墙切断了连接,那么在DCD的作用下,数据库服务器端的会话和进程也应该被清理才是,即使DCD不起作用,那TCP keep-alive也应该起作用才是,那为什么会话和进程数越来越多,甚至达到了最大进程数或会话数呢?
检查应用服务器(weblogic)的连接池,并核对应用服务器到数据库的TCP连接,发现连接池监控中的连接数量并不多,而对比应用服务器上看到的到数据库数据库的TCP连接数量和数据库数据器上看到的应用服务器建立过来的TCP连接数量,二者之间差距非常大,前者远远小于后者,就是说,大量的连接已经被切断,应用服务器的连接已经退出,但是数据库端的连接还没有释放。从weblogic的日志来看,经常出现类似于连接失效并建立新的数据库连接这样的信息。
DCD为什么没有起作用,是不是DCD的BUG?DCD的确是有很多BUG,但是完全不工作的BUG应该是很少的。将sqlnet.expire_time设为1,5以及其他值,都不起作用,甚至重启过主机都没有起作用(当然并不是专门为了DCD而重启主机)。
使用truss命令来跟踪Oracle进程:
SQL> host
$ truss -p 828090
kread(0, 0x0000000000000000, 0) (sleeping...)
...很长时间没有任何反应...
^CPstatus: process is not stopped
$
$ exit SQL> oradebug setospid 828090
Oracle pid: 247, Unix process pid: 828090, image: oracle@db2
SQL> oradebug short_stack
ksdxfstk+002c<-ksdxcb+04e4<-sspuser+0074<-000044C0<-nttrd+0120<-nsprecv+07a0<-nsrdr+0114<-nsdo+1710<-nsbrecv+0040<-nioqrc+04a8<-opikndf2+0688<-opitsk+08a8<-opiino+0990<-opiodr+0ae0<-opidrv+0484<-sou2o+0090<-opimai_real+01bc<-main+0098<-__start+0098
SQL> oradebug short_stack
ksdxfstk+002c<-ksdxcb+04e4<-sspuser+0074<-000044C0<-nttrd+0120<-nsprecv+07a0<-nsrdr+0114<-nsdo+1710<-nsbrecv+0040<-nioqrc+04a8<-opikndf2+0688<-opitsk+08a8<-opiino+0990<-opiodr+0ae0<-opidrv+0484<-sou2o+0090<-opimai_real+01bc<-main+0098<-__start+0098
没有看到DCD起任何作用的迹象,使用truss跟踪其他多个空闲Oracle也是如此。
那么TCP keep-alive呢,怎么样来判断有没有起作用?在AIX上其答案是使用kdb(这个需要root用户权限)。
在笔记本电脑上使用sqlplus连接到数据库,在数据库主机上使用netstat -Aan | grep 1521 | grep “你的IP地址”,以获得sqlplus连接的TCP连接信息,显示的第1列是一串16数据,然后使用kdb:
#kdb
The specified kernel file is a 64-bit kernel
Preserving 1418178 bytes of symbol table
First symbol __mulh
START END <name >
0000000000001000 0000000003E5C050 start+000FD8
F00000002FF47600 F00000002FFDC940 __ublock+000000
000000002FF22FF4 000000002FF22FF8 environ+000000
000000002FF22FF8 000000002FF22FFC errno+000000
F100070F00000000 F100070F10000000 pvproc+000000
F100070F10000000 F100070F18000000 pvthread+000000
PFT:
PVT:
id....................0002
raddr.....0000000002000000 eaddr.....F200800090000000
size..............00080000 align.............00001000
valid..1 ros....0 fixlmb.1 seg....0 wimg...2
Command enhancement entry point is called. Welcome to VXDRV subcommands
Command enhancement entry for vxodmdb called.called. Welcome to vxdrv subcommands
(0)> sockinfo f100060009b04398 tcpcb | egrep "KEEP|opts"
t_timer....... 00000000 (TCPT_KEEP)
timewait.prv@0000000000000000 inp_v6opts @0000000000000000
opts........ 0004 (REUSEADDR)
可以看到,这个TCP连接没有KEEPALIVE选项(属性),keep-alive对应的timer(TCPT_KEEP)数值为0,表示没有设置timer时间。
会不会是DCD功能屏蔽了TCP keep-alive?
将sqlnet.ora中expire_time设置去掉,然后重复上述步骤,这次有了变化:
#kdb
The specified kernel file is a 64-bit kernel
Preserving 1418178 bytes of symbol table
First symbol __mulh
START END <name >
0000000000001000 0000000003E5C050 start+000FD8
F00000002FF47600 F00000002FFDC940 __ublock+000000
000000002FF22FF4 000000002FF22FF8 environ+000000
000000002FF22FF8 000000002FF22FFC errno+000000
F100070F00000000 F100070F10000000 pvproc+000000
F100070F10000000 F100070F18000000 pvthread+000000
PFT:
PVT:
id....................0002
raddr.....0000000002000000 eaddr.....F200800090000000
size..............00080000 align.............00001000
valid..1 ros....0 fixlmb.1 seg....0 wimg...2
Command enhancement entry point is called. Welcome to VXDRV subcommands
Command enhancement entry for vxodmdb called.called. Welcome to vxdrv subcommands
(0)> sockinfo f100060009c1b398 tcpcb | egrep "KEEP|opts"
t_timer....... 00000464 (TCPT_KEEP)
timewait.prv@0000000000000000 inp_v6opts @0000000000000000
opts........ 000C (REUSEADDR|KEEPALIVE)
可以看到,这个TCP连接已经有了KEEPALIVE选项(属性),同时keep-alive timer为16进制数464,即十进制1124,表示还有562秒(timer这里的时间以半秒为单位)就会发送keep-alive探测包。
反复通过加上DCD设置和去掉DCD设置进行测试,发现只要一加上DCD功能,那么Oracle进程就不会为TCP连接设置keep-alive选项(属性),反之则会设置keep-alive。从这里很明显地看出来,DCD功能开启后,不但没有起作用,还关闭了TCP keep-alive功能。
对于这套系统,最后去掉了DCD设置,并将所有的空闲连接清理掉,经过多天的观察,系统的连接数一直保持稳定,与应用服务器的实际连接数保持一致。
那是不是启用了DCD之后,TCP keep-alive就会被关闭,这里不能贸然下定论,不同的版本、不同的平台或许有差异,至少我一个同事在Linux上测试时,tcp keep-alive是共存的。
在诊断处理这个案例的过程之中,不得不提到另外一点,写在此处,与大家分享。在诊断问题的初期阶段,询问系统维护人员(通常连应用和数据库一起维护),应用服务器和数据库之间是否有防火墙,如果有,是怎么样设置的TCP连接断开时间。而维护人员最开始的回答是没有防火墙。从表面上看,也应该是没有防火墙。数据库服务器其中一个IP地址是192.168.8.42,而两台应用服务器服务器的IP地址是192.168.8.201和192.168.8.202,咋一看是在同一网段,中间应该不会有防火墙。然而仔细检查相关数据:
$ifconfig -a
....省略部分输出....
en4: flags=5e080867,c0<up ,BROADCAST,DEBUG,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,CHECKSUM_OFFLOAD(ACTIVE),PSEG,LARGESEND,CHAIN>
inet 192.168.8.42 netmask 0xffffff80 broadcast 192.168.8.127
inet 192.168.8.43 netmask 0xffffff80 broadcast 192.168.8.127
tcp_sendspace 131072 tcp_recvspace 65536 rfc1323 0
可以看到,实际上数据库跟应用服务器是在不同的子网之中。这里子网掩码为0xffffff80,也就是我们通常写的子网掩码255.255.255.128,这样0-127为一个子网,128-255为一个子网(当然子网的第1个和最后一个地址都是不能使用的)。那么最后一个数字为201和202的两个IP地址显然就在第2个子网中,子网之间仍然需要有路由功能的网络设备,那么在之间有防火墙也是有可能的。用上面的方法去检查应用服务器的网络配置,发现其被划在了更小的子网之中。系统维护人员最终确认应用服务器和数据库之间的确是有防火墙存在。因此我们可以总结出两点:1,全面的知识对诊断数据库问题很有帮助。2, 如果经过详尽分析问题发现与别人说的不一致,需要坚持,并需要为自己的坚持寻找更多的数据来证实。
[转帖]防火墙、DCD与TCP Keep alive的更多相关文章
- 通过配置Windows 防火墙允许使用TCP/IP协议远程访问数据库
原文:通过配置Windows 防火墙允许使用TCP/IP协议远程访问数据库 本文适用于:2005.2008.2008R2所有版本 为了可以通过TCP/IP协议远程访问SQLServer数据库,需要做以 ...
- 转发 通过NAT和防火墙特性和TCP穿透的测评(翻译)
转自 http://blog.csdn.net/sjin_1314/article/details/18178329 原文:Characterization and Measurement of TC ...
- [转帖]直击案发现场!TCP 10倍延迟的真相是?
直击案发现场!TCP 10倍延迟的真相是? http://zhuanlan.51cto.com/art/201911/605268.htm 内核参数调优 非常重要啊. 什么是经验?就是遇到问题,解决问 ...
- [转帖]使用Nginx转发TCP/UDP数据
使用Nginx转发TCP/UDP数据 https://www.cnblogs.com/guigujun/p/8075620.html 编译安装Nginx 从1.9.0开始,nginx就支持对TCP的转 ...
- LwIP raw api下使用tcp keep alive
// The following code is implemented after tcp_new() or in tcp_connected call back... xxx_connected( ...
- ORACLE的Dead Connection Detection浅析
在复杂的应用环境下,我们经常会遇到一些非常复杂并且有意思的问题,例如,我们会遇到网络异常(网络掉包.无线网络断线).客户端程序异常(例如应用程序崩溃Crash).操作系统蓝屏.客户端电脑掉电.死机重启 ...
- 关于日常使用Azure MySQL中遇到的连接问题以及排查方法分享
由于防火墙问题,TCP keep alive 问题,以及 MySQL 自身的参数问题这三个在使用中比较常见,所以今天就分享下自己找到的排查方法. 今天先聊一聊防火墙问题 大多数人在第一次创建 MySQ ...
- TCP idle timeout 和TCP Keepalive 比较和分析
TCP idle timeout 和TCP Keepalive 是两个独立的功能. TCP idle timeout TCP idle timeout 是系统TCP配置文件中的空闲超时设 ...
- Linux iptables 防火墙
内容摘要 防火墙 防火墙定义 防火墙分类 netfilter/iptables netfilter 设计架构 iptables 简述 iptables 命令详解 命令语法 table 参数 comma ...
- centos 防火墙
让防火墙放通tcp的 80端口: [root@localhost ~]# firewall-cmd --zone=public --add-port=80/tcp --permanent 重启防火墙以 ...
随机推荐
- JavaFx之controlsfx8下载(十七)
JavaFx之controlsfx8下载(十七) controlsfx是JavaFx功能的扩展补充,这里我使用java8,我将源码下载下来并编译好jar,在java8的环境双击运行runSamples ...
- Linux的期末冲刺
选择 一.Linux基础 Linux目录结构 相关命令: cd, ls, pwd 详解: Linux 目录结构采用树状结构,根目录为 /.用户的帐户信息保存在 /etc/passwd 文件中,包括用户 ...
- 2021-01-26:mysql8.0做了什么改进?
福哥答案2021-01-26: 2020-01-26:mysql8.0做了什么改进? 帐户管理增加了对角色的支持. 支持原子数据定义语句(atomic DDL). 支持utf8mb4字符集. Inno ...
- C++篇:第三章_控制结构_知识点大全
C++篇为本人学C++时所做笔记(特别是疑难杂点),全是硬货,虽然看着枯燥但会让你收益颇丰,可用作学习C++的一大利器 三.控制结构 for循环的结束判定条件是boolean型 只要适当地修改代码,就 ...
- 《玩转鲲鹏DevKit系列》第四期:如何基于鲲鹏平台高效开发?
本文分享自华为云社区<<玩转鲲鹏DevKit系列>第四期:如何基于鲲鹏平台高效开发?>,作者:华为云社区精选 . 在鲲鹏软件新版本迭代或新功能开发过程中,使用鲲鹏DevKit ...
- 实践丨GaussDB(DWS)资源管理排队原理与问题定位
摘要:GaussDB(DWS)提供了资源管理功能,用户可以根据自身业务情况对资源进行划分,将资源按需划分成不同的资源池,不同资源池之间资源互相隔离. 本文分享自华为云社区<GaussDB(DWS ...
- 云小课 | 华为云KYON:网段零修改上云,简单又好用
摘要:KYON(Keep Your Own Network)是华为云推出的企业级云网络解决方案,KYON能让用户直接将IDC组网搬到云上,网段零修改,简单又好用. 本文分享自华为云社区<[云小课 ...
- 云小课|ModelArts Pro 视觉套件 零代码构建视觉AI应用
阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:ModelArts ...
- 教你从零搭建Web漏洞靶场OWASP Benchmark
摘要:Owasp benchmark 旨在评估安全测试工具的能力(准确率.覆盖度.扫描速度等等),量化安全测试工具的扫描能力,从而更好得比较各个安全工具优缺点. 本文分享自华为云社区<Web漏洞 ...
- websever
1 在浏览器键入url,按下回车会经历如下行为 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址; 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立 TC ...