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的更多相关文章

  1. 通过配置Windows 防火墙允许使用TCP/IP协议远程访问数据库

    原文:通过配置Windows 防火墙允许使用TCP/IP协议远程访问数据库 本文适用于:2005.2008.2008R2所有版本 为了可以通过TCP/IP协议远程访问SQLServer数据库,需要做以 ...

  2. 转发 通过NAT和防火墙特性和TCP穿透的测评(翻译)

    转自 http://blog.csdn.net/sjin_1314/article/details/18178329 原文:Characterization and Measurement of TC ...

  3. [转帖]直击案发现场!TCP 10倍延迟的真相是?

    直击案发现场!TCP 10倍延迟的真相是? http://zhuanlan.51cto.com/art/201911/605268.htm 内核参数调优 非常重要啊. 什么是经验?就是遇到问题,解决问 ...

  4. [转帖]使用Nginx转发TCP/UDP数据

    使用Nginx转发TCP/UDP数据 https://www.cnblogs.com/guigujun/p/8075620.html 编译安装Nginx 从1.9.0开始,nginx就支持对TCP的转 ...

  5. LwIP raw api下使用tcp keep alive

    // The following code is implemented after tcp_new() or in tcp_connected call back... xxx_connected( ...

  6. ORACLE的Dead Connection Detection浅析

    在复杂的应用环境下,我们经常会遇到一些非常复杂并且有意思的问题,例如,我们会遇到网络异常(网络掉包.无线网络断线).客户端程序异常(例如应用程序崩溃Crash).操作系统蓝屏.客户端电脑掉电.死机重启 ...

  7. 关于日常使用Azure MySQL中遇到的连接问题以及排查方法分享

    由于防火墙问题,TCP keep alive 问题,以及 MySQL 自身的参数问题这三个在使用中比较常见,所以今天就分享下自己找到的排查方法. 今天先聊一聊防火墙问题 大多数人在第一次创建 MySQ ...

  8. TCP idle timeout 和TCP Keepalive 比较和分析

    TCP  idle timeout  和TCP Keepalive  是两个独立的功能. TCP  idle timeout  TCP  idle timeout  是系统TCP配置文件中的空闲超时设 ...

  9. Linux iptables 防火墙

    内容摘要 防火墙 防火墙定义 防火墙分类 netfilter/iptables netfilter 设计架构 iptables 简述 iptables 命令详解 命令语法 table 参数 comma ...

  10. centos 防火墙

    让防火墙放通tcp的 80端口: [root@localhost ~]# firewall-cmd --zone=public --add-port=80/tcp --permanent 重启防火墙以 ...

随机推荐

  1. 从0开始学微信逆向开发(android版)——第一栏

    首先给大家普及一下啥叫微信逆向开发,以及微信逆向开发能做什么: 场景1:小明是做微商的,他每天需要加很多很多的好友.然后他会通过微信的各种渠道去添加好友,比如(附近的人.摇一摇.漂流瓶.手机号搜索等) ...

  2. 【K8S系列】如何高效查看 k8s日志

    序言 你只管努力,其他交给时间,时间会证明一切. 文章标记颜色说明: 黄色:重要标题 红色:用来标记结论 绿色:用来标记一级论点 蓝色:用来标记二级论点 Kubernetes (k8s) 是一个容器编 ...

  3. 文心一言 VS 讯飞星火 VS chatgpt (36)-- 算法导论5.3 6题

    六.请解释如何实现算法 PERMUTE-BY-SORTING,以处理两个或更多优先级相同的情形.也就是说,即使有两个或更多优先级相同,你的算法也应该产生一个均匀随机排列. 文心一言: 算法 PERMU ...

  4. FreeMark模板基本知识

    FreeMarker模板基础知识 1.FreeMarker与jsp.Thymeleaf并排为三大模板引擎,用于把后端数据渲染到页面上,降低耦合度.动态数据+占位符+静态页面标签构成动态页面. 2.Fr ...

  5. PC端和移动端应用的开发差异

    PC端和移动端应用的开发差异主要体现在用户界面(UI)和用户体验(UX)设计.交互设计.性能优化.适配策略等方面.  

  6. 云图说 | MSSI之应用业务模型ABM,搭建业务与技术的数据治理桥梁

    摘要:应用业务模型ABM(Application Business Model)是MSSI为客户提供的统一模型管理服务. 本文分享自华为云社区<[云图说] | 第274期 MSSI之应用业务模型 ...

  7. 经验说丨华为云视频Cloud Native架构下实践

    摘要:来自华为云直播的段亮详细介绍华为云视频在Cloud Native的转型实践中遇到的问题.挑战以及解决之道. 随着云基础设施服务以及边缘计算技术的发展,Cloud Native,即云原生,架构理念 ...

  8. 5步教你将MRS数据导入DWS

    摘要:GaussDB(DWS)支持在相同网络中,配置一个GaussDB(DWS)集群连接到一个MRS集群,然后将数据从HDFS中的文件读取到GaussDB(DWS). MapReduce服务(MapR ...

  9. 从 Uber 数据泄露事件我们可以学到什么?

    Uber 数据泄露始于一名黑客从暗网市场购买属于一名 Uber 员工的被盗凭证.最初尝试使用这些凭据连接到 Uber 的网络失败,因为该帐户受 MFA 保护.为了克服这一安全障碍,黑客通过 What' ...

  10. DNS--智能地址解析(view视图)

    域名:xinenhui.com DNS服务器:192.168.198.128 DNS1:192.168.198.129 DNS2:192.168.198.146 1 简介 使客户端就近访问DNS服务器 ...