2016-11-27 32 views
7

我正在运行python应用程序(flask + redis-py)与uwsgi + nginx和使用aws elasticache(redis 2.8.24)。我发现在高负载下(每秒500次请求/使用loader.io 30秒),我正在失去请求(对于这个测试,我只用了一个单个服务器没有负载平衡器,1个uwsgi实例,4个进程,用于测试)。 stress testAWS Redis + uWSGI背后的NGINX - 高负载

我已经挖得更深一些,并发现这个负载下,一些要求ElastiCache是​​缓慢的。 例如:

  • 正常负荷:cache_set时间0.000654935836792
  • 重载:cache_set时间0.0122258663177 这不会发生的所有请求,只是随机occurres ..

我的AWS ElastiCache基于cache.m4.xlarge(默认AWS配置设置)上的2个节点。 查看已连接在过去3小时目前的客户: aws elasticache clients

我觉得这样做没有意义,因为目前14台服务器(其中8 XX RPS的高流量使用这个集群),我希望看到更高的客户利率。

uWSGI配置(版本2.0.5.1)

processes = 4 
enable-threads = true 
threads = 20 
vacuum = true 
die-on-term = true 
harakiri = 10 
max-requests = 5000 
thread-stacksize = 2048 
thunder-lock = true 
max-fd = 150000 
# currently disabled for testing 
#cheaper-algo = spare2 
#cheaper = 2 
#cheaper-initial = 2 
#workers = 4 
#cheaper-step = 1 

Nginx的是只使用Unix套接字网络代理uWSGI。

这是我如何打开一个连接到Redis的:

rdb = [ 
    redis.StrictRedis(host='server-endpoint', port=6379, db=0), 
    redis.StrictRedis(host='server-endpoint', port=6379, db=1) 
] 

我这是怎么设置的值。例如:

def cache_set(key, subkey, val, db, cache_timeout=DEFAULT_TIMEOUT): 
    t = time.time() 
    merged_key = key + ':' + subkey 
    res = rdb[db].set(merged_key, val, cache_timeout) 
    print 'cache_set time ' + str(time.time() - t) 
    return res 

cache_set('prefix', 'key_name', 'my glorious value', 0, 20) 

这是我得到的值:

def cache_get(key, subkey, db, _eval=False): 
    t = time.time() 
    merged_key = key + ':' + subkey 
    val = rdb[db].get(merged_key) 
    if _eval: 
     if val: 
      val = eval(val) 
     else: # None 
      val = 0 
    print 'cache_get time ' + str(time.time() - t) 
    return val 

cache_get('prefix', 'key_name', 0) 

版本:

  • uWSGI:2.0.5.1
  • 瓶:0.11.1
  • Redis的-PY:2.10.5
  • Redis的:24年2月8日

于是得出结论:

  1. 如果连接14台服务器,每台服务器有4个进程,并且每台服务器都打开一个连接到redis集群内的8个不同数据库,那么AWS客户端的计数会很低
  2. 什么导致请求响应时间爬升?
  3. 希望了解关于ElastiCache和/或uWSGI性能任何意见重载
+0

奥兹,你能找到解决办法吗?我面临着完全相同的问题。从字面上看...... nginx + flask + uwsgi一直很好,但是因为我在Elasticache中添加了redis,所以我在Elasticache中遇到了长时间运行查询的问题。 – camelCase

回答

2

简答下

所以,如果我是正确的,在我的情况下,问题不是Elasticache请求,但uWSGI内存使用情况。

长的答案

我已经安装了uwsgitop与此设置:

### Stats 
### --- 
### disabled by default 
### To see stats run: uwsgitop /tmp/uwsgi_stats.socket 
### uwsgitop must be install (pip install uwsgitop) 
stats = /tmp/uwsgi_stats.socket 

这将暴露uwsgi统计信息uwsgitop。

然后,我使用​​以350-500个请求/秒对应用程序进行压力测试。

我发现与我以前的配置是,uWSGI工作人员不断增长使用的内存大小,直到内存窒息,然后CPU尖刺。需要重新产卵的新工人也要求cpu,这会导致服务器出现某种过载 - 这导致nginx超时并关闭这些连接。

所以我做了一些研究和配置修改,直到我设法得到下面的设置,目前管理约〜650rps的每个实例~13ms的响应时间,这对我很好。

*我使用的应用程序(仍然使用一些)腌dat文件,其中一些人重加载磁盘 - 我已经减少了磁盘的依赖性最小*

对于任何人谁可能会看到它的未来 - 如果您需要快速响应 - 尽可能将所有内容同步。为前,用芹菜+ RabbitMQ的任何数据库请求,如果可能的话

uWSGI配置:

listen = 128 
processes = 8 
threads = 2 
max-requests = 10000 
reload-on-as = 4095 
reload-mercy = 5 
#reload-on-rss = 1024 
limit-as = 8192 
cpu-affinity = 3 
thread-stacksize = 1024 
max-fd = 250000 
buffer-size = 30000 
thunder-lock = true 
vacuum = true 
enable-threads = true 
no-orphans = true 
die-on-term = true 

NGINX相关部分:

user nginx; 
worker_processes 4; 
worker_rlimit_nofile 20000; 
thread_pool my_threads threads=16; 
pid /run/nginx.pid; 

events { 
    accept_mutex off; 
    # determines how much clients will be served per worker 
    # max clients = worker_connections * worker_processes 
    # max clients is also limited by the number of socket connections available on the system (~64k) 
    worker_connections 19000; 

    # optmized to serve many clients with each thread, essential for linux -- for testing environment 
    use epoll; 

    # accept as many connections as possible, may flood worker connections if set too low -- for testing environment 
    multi_accept on; 
} 

http { 
    ... 
    aio      threads; 
    sendfile    on; 
    sendfile_max_chunk  512k; 
    tcp_nopush    on; 
    tcp_nodelay    on; 
    keepalive_timeout  5 5; 
    keepalive_requests  0; 
    types_hash_max_size  2048; 
    send_timeout   15; 
    ... 
} 

希望它能帮助!