redis 产生大量 CLOSE_WAIT?

2015-11-19 14:51:25 +08:00
 BeginMan

Python 操作 redis 时,由于 redis 实例线程安全,所以我使用了两种方式:

(1).直接做全局变量,如下:

R = redis.Redis()
# 导入到多个需要使用 redis 的模块中,直接使用,如:
R.get('name')

(2).连接池,如下:

class mRedis(object):
    def __init__(self, db=0):
        self.db = db
        self.redis_pool = redis.ConnectionPool(host=settings.redis_svr_addr,
                                               port=settings.redis_svr_addr_port,
                                               db=self.db,
                                               password=settings.redis_svr_pass)


    def getR(self):
        return redis.Redis(connection_pool=self.redis_pool)

# 实例化直接使用
myredis = mRedis(db=0).getR()

但是在使用过程中,产生了大量 CLOSE_WAIT.,一大屏幕,如下:

tcp        1      0 127.0.0.1:62286             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15153             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:14972             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15134             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15030             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:62486             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15097             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:4912              127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:14517             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15155             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:59812             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15031             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15121             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:14812             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:59806             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:14813             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:14928             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:63476             127.0.0.1:6379              CLOSE_WAIT
tcp        1      0 127.0.0.1:15048             127.0.0.1:6379              CLOSE_WAIT

其中 redis.conf 设置 timeout 200

而且时常会出现 redis 连接超时的问题,导致 tornado 一直阻塞请求,看了下带宽,负载,CPU,内存都比较正常,暂时找不到原因,不知道是 redis 使用方面出了什么问题?求指点!!:-D

6192 次点击
所在节点    问与答
22 条回复
BeginMan
2015-11-19 14:55:07 +08:00
查了慢查询日志,发现

6379> SLOWLOG get
1) 1) (integer) 0
2) (integer) 1441609701
3) (integer) 151130
4) 1) "SAVE"
sujin190
2015-11-19 14:56:23 +08:00
每次生成连接池?那不是和每次打开连接一样了,还不关闭。。
BeginMan
2015-11-19 14:57:45 +08:00
@sujin190 都没有关闭。
HunterPan
2015-11-19 15:06:32 +08:00
close wait 从大道理上讲是客户端关闭了,但服务器段没再握手。
ufo22940268
2015-11-19 15:07:27 +08:00
前几天,因为我的 redis 版本不够高, ucloud 把我的 vps 限流量了。

LZ 看看这几天 redis 是不是出了什么高危漏洞
BeginMan
2015-11-19 15:07:53 +08:00
@HunterPan 恩 所以问题就定位在我的程序上了。。
HunterPan
2015-11-19 15:09:25 +08:00
上述表述有误:应该是主动关闭方,发起关闭,而被动方没有发送第二次握手。
BeginMan
2015-11-19 15:13:00 +08:00
@ufo22940268 谢谢,我的是版本是 redis 3.0.2 ,应该比较稳定,偶数不是稳定版本么。刚查了下好像没漏洞提示。
ipconfiger
2015-11-19 15:14:17 +08:00
pip install tornado-redis
BeginMan
2015-11-19 15:20:01 +08:00
@ipconfiger 你好,这个已经在项目二用上了。
pubby
2015-11-19 15:29:50 +08:00
为啥 Recv-Q 里面还有数据 1
BeginMan
2015-11-19 16:28:40 +08:00
全部改成线程池的方式后,观察了 半个多小时, CLOSE_WAIT 少了一大半。
sleeperqp
2015-11-19 16:44:05 +08:00
应该是客服端发送 close 请求 服务器端没有关闭
BOYPT
2015-11-19 16:50:03 +08:00
CLOSE_WAIT 的意思就是已经关闭了,再多都没关系。
ryd994
2015-11-19 17:23:27 +08:00
1. 线程池尽可能复用,用完记得关闭
2. 用 unix socket 文件就完全没有这个问题,而且性能要 好 的 多

@pubby
这是 CLOSE_WAIT 的作用之一,还有未读取的数据

@BOYPT
CLOSE_WAIT 只占很少资源,作用类似僵尸进程。但不是再多都没关系。太多还是会出事的。
e1eph4nt
2015-11-19 18:06:07 +08:00
看起来是 server 端关闭的, client 端还没读到这个 fin ,所以 recv-q 里面还有一个 segment
pubby
2015-11-19 18:34:14 +08:00
@e1eph4nt server 端关闭不会有 CLOSE_WAIT 的
https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/TCP_CLOSE.svg/2000px-TCP_CLOSE.svg.png

应该是收到了 FIN ,回了 ACK ,自己没发 FIN
esplendo
2015-11-19 19:41:32 +08:00
@ufo22940268
@BeginMan

是这样的,当时我们监测发现您的云主机未做针对 Redis 安全漏洞的措施,此台云主机有很大可能已经被入侵,对此我们先将此台云主机带宽进行限流。也麻烦尽快完善安全措施。

注:限流带宽值仍高于您的购买带宽,主要防止主机被攻破后出现异常流量及攻击行为。
e1eph4nt
2015-11-19 20:28:32 +08:00
@pubby 确实 kernel 应该已经回复了 ack ,我说的 client 指的是 user 态,不是很确定,只是试图解释为什么 recv-q 里面还有 1
e1eph4nt
2015-11-19 20:31:25 +08:00
@pubby 他的 server 和 client 都在 127.0.0.1

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/237326

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX