`

性能测试发现“redis cannot assign requested address”问题

 
阅读更多

 

场景描述:test_client(jmeter) -> nginx -> redis

 

问题表现:nginx频繁报错redis cannot assign requested address,查看nginx网络连接情况,发现有大量TIME_WAIT的连接,并且test_client的tps上不去。大量的TIME_WAIT状态使得local port在TIME_WAIT持续期间不能被再次分配,即没有可用的local port,最终导致新建连接失败。

 

问题分析一:

大量TIME_WAIT出现的主要原因是nginx频繁与服务端建立tcp短连接后,又主动关闭tcp连接引起的。我们使用的openresty的redis库(resty.redis)已经有连接池的概念,且关闭tcp连接时使用set_keepalive方式,所以搞不清楚为什么nginx会频繁关闭tcp连接,导致出现大量TIME_WAIT的tcp连接。

 

问题分析二:

lua-resty-redis的set_keepalive函数最终调用的是lua-nginx-module的tcpsock:setkeepalive函数,此函数有两个参数(max_idle_timeout, pool_size),即最大空闲时间和最大连接池大小。使用set_keepalive把该连接放到连接池后,该连接到达最大空闲时间或者连接池到达连接池最大值时,会把连接池中最久未使用的连接关闭掉。原文如下:

When the connection pool exceeds the available size limit, the least recently used (idle) connection already in the pool will be closed to make room for the current connection.

 

问题分析三:

基于以上的分析,当nginx的worker pool设置成128时(worker_processes=1),如果有200个并发连接(循环请求1000次)打到nginx,nginx会同时建立200个连接请求后端redis服务器,当200个并发连接第一次请求结束后,调用set_keepalive把连接归还给nginx(准确地说应该是lua-nginx-module)的连接池时,大约会有72(200-128)个连接无法放回连接池而关闭(tcpsock:close)。然后200个并发连接发起第二次请求,能够从连接池取到的可用连接中只有128个,剩余的72个连接只能再次建立tcp连接到后端redis服务器,请求结束后200个新连接放回到连接池的时候,由于连接池大小的限制只能有部分(或者一个都没有)连接放回连接池,大部分tcp连接还是只能关闭。这样周而复始,TIME_WAIT的连接会越来越多,且没有可用的local port,最终导致新建连接失败。

 

问题解决方式一:

这个问题可以通过设置两个内核参数(tcp_tw_recycle和tcp_tw_reuse)来间接解决,但tcp_tw_recycle有副作用,不建议打开。

但是这种方法治表不治本,即使可以快速回收/复用TIME_OUT的tcp连接,但是其实不能复用连接池连接时,还是需要新建nginx到redis服务器的tcp连接(因为已经close的tcp连接到达TIME_WAIT状态时,reuse此连接还是需要重新建立到redis server的tcp连接),所以开销还是很大。

 

问题解决方式二:

我们的解决方法是根据现实的需要,动态调整nginx到redis连接池的大小。如果我们最大支持test_client的1000个并发连接,那我们nginx到redis的连接池设置成1024(当然redis server的maxclient也要大于1024,否则瓶颈就变成redis server了)。这种解决方式并不完美,因为这样可能导致nginx空闲时有大量到redis server的tcp连接。后期可以参考ThreadPoolExecutor设置corePoolSize,maximumPoolSize或许更加合理(需要修改lua-nginx-module代码)。

PS:上面说到nginx到redis的连接成设置成1024(此值针对单nginx worker),对于worker_processes>1时也需要这样设置,是考虑到可能nginx master到nginx worker分配极端不均匀的情况。其实nginx性能还好,如果worket_processes=4时,此值设置成512绰绰有余。

 

 

参考链接:

https://github.com/openresty/lua-resty-redis

https://github.com/openresty/lua-nginx-module

https://github.com/openresty/lua-nginx-module#tcpsocksetkeepalive

http://blog.csdn.net/yunhua_lee/article/details/8146856

http://www.cnblogs.com/javawebsoa/archive/2013/05/18/3086034.html

http://jinnianshilongnian.iteye.com/blog/2187328

 

 

 
分享到:
评论

相关推荐

    Redis集群性能测试分析

    本次实验的目的主要是搭建Redis Cluster和TwemProxy Redis两种集群,分别对其进行性能测试,测试出集群性能的拐点,找出性能的瓶颈有哪些,并对两套集群进行比较,以便于在不同业务场景下择优选择。

    Redis性能测试报告

    Redis性能测试报告旨在详细记录和分析Redis中间件的性能,以确保其在实际生产环境中的稳定性和效率。报告涵盖了测试的各个方面,包括测试范围、目标、环境需求、方案以及结果的呈现。 首先,测试范围明确指出是针对...

    redis 读写性能测试代码

    在本文中,我们将深入探讨Redis的读写性能测试,特别是针对“写”的操作性能。 在标题中提到的“redis 读写性能测试代码”,我们通常会使用Java的Jedis库来实现。Jedis是Java社区广泛使用的Redis客户端,提供了丰富...

    Redis集群测试

    7. **测试策略**:测试Redis集群时,应包括性能测试(如并发读写测试)、压力测试(模拟大规模数据和高并发场景)、故障恢复测试(验证故障转移的正确性)以及数据一致性测试(检查数据在不同节点间的同步情况)。...

    memcache redis tair 性能测试报告

    【性能测试报告概述】 这份报告详细对比了三种常用的内存数据库——memcache、redis以及tair的性能表现。测试目的是为了评估这些缓存工具在不同场景下的处理能力,特别是在并发操作和不同大小的数据存储上的效率。...

    memcached&redis;性能测试

    memcached,redis性能测试,内存缓存系统的性能测试;

    Redis性能测试

    在本文中,我们将深入探讨Redis的性能测试,同时与CoolHash和SqlServer进行对比,以了解它们在不同场景下的表现。我们将通过一个小例子来展示测试过程,并提供相关的源码和jar包供读者参考。 1. Redis性能特性: ...

    windows下启动redis2.8服务端、客户端、性能测试工具等

    在Windows环境下设置和运行Redis 2.8服务端、客户端以及进行性能测试,是开发者和系统管理员的常见任务。以下是一份详细的步骤指南: 一、安装Redis 2.8 1. 下载:首先,从Redis官方网站或者第三方源获取适用于...

    redis 性能测试(读写)

    这里的"redis 写的操作性能测试代码"主要涉及如何使用 Jedis 客户端来测试 Redis 的写入性能。以下是一些相关的知识点: 1. **Redis 写操作**: - `SET` 命令:基本的设置键值对操作,例如 `set("key", "value")`...

    redis读性能测试.zip

    Redis,全称Remote Dictionary Server,是一款高性能的键值对存储系统,常被用作数据库、缓存和消息中间件。...记住,性能测试不仅是找出问题,更是为了提升服务质量。在实际应用中,持续监控和优化是关键。

    redis测试代码

    这些文件可能包括Python、Java、Node.js等语言的示例代码,用于模拟客户端与Redis服务器的交互,进行功能验证和性能测试。 通过这些测试代码,开发者可以模拟实际应用场景,确保Redis在部署到生产环境之前满足所有...

    redis简单小例子(测试类)

    这只是一个redis的简单小测试类,大家有兴趣可以下,里面都是一些常见的用法

    redis 性能测试

    在进行Redis性能测试时,通常会通过Jedis来模拟实际业务场景,评估Redis在高并发环境下的响应速度和处理能力。 在“redis 性能测试”这个主题中,我们将深入探讨以下几个关键知识点: 1. **Redis的基础概念**:...

    RedisDesktopManager 0.9.9

    **RedisDesktopManager 0.9.9:Mac平台上的优秀Redis图形化管理工具** RedisDesktopManager(简称RDM)是一款高效、易用的GUI客户端,专为管理Redis数据库而设计,尤其在Mac平台上表现突出。它以其简洁的界面、丰富...

    基于redis事件库开发,高性能socket性能测试工具

    高性能socket性能测试工具/框架,做socket性能测试工具的终结者。满足一般性能测试、延迟测试、最大连接数测试、吞吐量测试、压力测试、长时间稳定性测试、内存泄漏测试等场景。 简介: 基于redis事件库开发,one ...

    redis缓存分享,包含redis和redis测试的项目test

    测试通常会涵盖各种操作,如写入、读取、更新和删除数据,以及并发访问场景下的性能测试。测试过程中,我们还需要关注Redis的连接管理、过期策略、数据一致性等方面。 最后,"redis"文件可能是Redis服务器的配置...

    REDIS 性能相关配置研究

    Redis,全称Remote Dictionary Server,是一款高性能的键值存储系统,广泛应用于缓存、消息队列、数据库等多个领域。它的高性能主要得益于其基于内存的数据存储方式以及高效的命令处理机制。在深入研究Redis性能相关...

    redis安装与测试

    Redis是一款高性能的键值对数据库,常用于存储缓存数据和快速读取的数据。本文将详细介绍Redis在Linux环境下的安装过程以及如何进行测试,非常适合初次接触Redis的读者。 首先,让我们从下载Redis安装包开始。在...

    C++ 操作Redis数据库VS2013测试Demo及redis sdk

    Redis是一个高性能的键值对存储系统,常被用作数据库、缓存和消息中间件。在C++中与Redis交互,通常需要借助客户端库,这里提到的是`hiredis`,这是一个轻量级、高效的纯C语言实现的Redis客户端库。 1. **hiredis...

    java客户端测试redis集群

    - 性能测试:测量并发请求下的响应时间,评估系统的吞吐量和延迟。 4. **Jedis集群使用**:使用Jedis进行集群测试时,需要配置集群节点信息,初始化JedisCluster对象。然后,可以使用getClusterNodes()方法获取...

Global site tag (gtag.js) - Google Analytics